[20140109]显示执行计划的问题.txt

昨天看别人调优,我跟对方讲使用SET Autotrace看执行计划可能不真实的.
自己做一个简单的例子来说明:

1.建立测试环境:
SCOTT@test> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

create table t pctfree 99 as select rownum id ,'test' name from dual connect by levelcreate index i_t_id on t(id);

exec dbms_stats.gather_table_stats(user, 'T',  method_opt=>'for all columns size 1 ',no_invalidate => false);

variable n number;
exec :n := 10;
select * from t where id>=:n;

2.测试:
SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  0ck6kww1pfuw8, child number 0
-------------------------------------
select * from t where id>=:n
Plan hash value: 1601196873
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    71 (100)|
|*  1 |  TABLE ACCESS FULL| T    |    992 |    71   (0)|
--------------------------------------------------------
Peeked Binds (identified by position):
--------------------------------------
   1 - (NUMBER): 10
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID">=:N)

--因为n=10,很小,oracle 的绑定变量peek发现选择全表扫描更加合理.

SCOTT@test> set autotrace traceonly
SCOTT@test> select * from t where id>=:n;
991 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 4153437776
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |    50 |   450 |     5   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |    50 |   450 |     5   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_T_ID |     9 |       |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID">=TO_NUMBER(:N))
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        250  consistent gets
          0  physical reads
          0  redo size
      10185  bytes sent via SQL*Net to client
        563  bytes received via SQL*Net from client
          6  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        991  rows processed

3.突然想起以前遇到的问题,set autotrace traceonly explain问题,这个还可能导致执行计划的改变.
http://blog.itpub.net/267265/viewspace-716004/

SCOTT@test> alter system flush shared_pool;
System altered.

SCOTT@test> select * from v$sql where sql_id='0ck6kww1pfuw8';
no rows selected

SCOTT@test> set autotrace traceonly explain
SCOTT@test> select * from t where id>=:n;
Execution Plan
---------------------------
Plan hash value: 4153437776
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |    50 |   450 |     5   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |    50 |   450 |     5   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_T_ID |     9 |       |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID">=TO_NUMBER(:N))

SCOTT@test> set autotrace off
SCOTT@test> select sql_id,child_number,sql_text from v$sql where sql_id='0ck6kww1pfuw8';
SQL_ID        CHILD_NUMBER SQL_TEXT
------------- ------------ ------------------------------------------------------------
0ck6kww1pfuw8            0 select * from t where id>=:n
--可以发现已经生成了执行计划.

SCOTT@test> select * from t where id>=:n;
SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  0ck6kww1pfuw8, child number 0
-------------------------------------
select * from t where id>=:n
Plan hash value: 4153437776
--------------------------------------------------------------------
| Id  | Operation                   | Name   | E-Rows | Cost (%CPU)|
--------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |        |     5 (100)|
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |     50 |     5   (0)|
|*  2 |   INDEX RANGE SCAN          | I_T_ID |      9 |     2   (0)|
--------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID">=:N)
  
--可以发现执行计划改变.

总结:
--可以发现看到的执行计划选择索引,而实际上根本不是这么回事.实际上如果你使用 explain plan for...,在使用
--select * from table(dbms_xplan.display());查询也是一样的问题.

--总之10g以后看执行计划最好使用dbms_xplan.display_cursor来看.或者不使用参数看执行计划,也许这样会准一点.

时间: 2024-10-23 20:12:46

[20140109]显示执行计划的问题.txt的相关文章

[20140221]执行计划以及dblink.txt

[20140221]执行计划以及dblink.txt --昨天我调整一个sql语句,忽略一个细节,sql里面使用了视图,视图里面使用dblink.我正是关注逻辑读不大,让我忽视了优化. --举一些例子来说明问题. 1.建立测试环境: SCOTT@test> @ver BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterpri

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一1.2 显示执行计划

1.2 显示执行计划 我们现在知道,有三个途径可以获取查询计划:v$sql_plan.dba_hist_sql_plan和PLAN_TABLE.如果需要读取一条SQL语句的执行计划,就需要知道该条语句的SQL_ID,如果该语句存在多个游标或者执行计划,则还需要知道游标的CHILD_NUMBER或计划的哈希值(可选).而无论我们通过哪个途径来获取执行计划,显示方式主要是两种:语句查询和包DBMS_XPLAN显示. 1.2.1 通过查询语句显示计划 通过查询语句从一些视图里读出执行计划并作格式化输出

【显示执行计划】在普通用户下使用set autot 查看执行计划

在普通用户下查看执行计划 时 ,会遇到如下问题: SQL> CONN SCOTT/SCOTT 已连接. SQL> SET AUTOT TRACE搜集统计信息时出错 ORA-942 SP2-0611: 启用 STATISTICS 报告时出错 SQL> SET AUTOT ON 搜集统计信息时出错 ORA-942 SP2-0611: 启用 STATISTICS 报告时出错 SQL> SET AUTOT OFF SQL> SET AUTOT ON 搜集统计信息时出错 ORA-942

oracle数据库性能调优技术:深入理解嵌套循环执行计划

一.概述 这篇文章是数据库性能调优技术的第三篇.上一篇文章讲解了深入了解单表执行计划,单表执行计划是理解多表执行计划的基础. 两张表的连接有三种执行方式:1)嵌套循环连接:2)散列连接:3)归并连接.两张表连接时选择这三种中的哪一种呢?这取决于索引.以及连接的代价.在该系列的第三篇(本文)文章中讲解嵌套循环连接,第四篇文章中讲解散列连接,第五篇文章中讲解归并连接.在第六篇以后会分析IN子查询以及EXISTS子查询. 达梦数据库.oracle数据库.sql server数据库在数据库执行计划方面并

Oracle中获取执行计划的几种方法

1. 预估执行计划 - Explain Plan Explain plan以SQL语句作为输入,得到这条 SQL语句的执行计划,并将执行计划输出存储到计划表中. 首先,在你要执行的SQL语 句前加explain plan for,此时将生成的执行计划存储到计划表中,语句如下: explain plan for SQL语句 然后,在计划表中查询刚刚生成的执行计划,语 句如下: select * from table(dbms_xplan.display); 注意:Explain plan 只生成执

Oracle中获取执行计划的几种方法分析

以下是对Oracle中获取执行计划的几种方法进行了详细的分析介绍,需要的朋友可以参考下   1. 预估执行计划 - Explain PlanExplain plan以SQL语句作为输入,得到这条SQL语句的执行计划,并将执行计划输出存储到计划表中. 首先,在你要执行的SQL语句前加explain plan for,此时将生成的执行计划存储到计划表中,语句如下: explain plan for SQL语句然后,在计划表中查询刚刚生成的执行计划,语句如下: select * from table(

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一2.5 执行计划中其他信息的含义

2.5 执行计划中其他信息的含义 通过DBMS_XPLAN输出执行计划,除了计划本身外,还可以获得一些其他信息帮助我们进一步分析执行计划及语句性能. 2.5.1 查询块和对象别名 在使用DBMS_XPLAN显示执行计划时,选择'ADVANCED'预定义格式作为参数或者加入'ALIAS'控制字符串,可以在输出中看到以下内容: Query Block Name / Object Alias (identified by operation id): -------------------------

查看oracle执行计划方法( 一)

关于oracle执行计划的概念,参考之前的博客:http://blog.csdn.net/cymm_liu/article/details/7996599 如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的每一步执行是否存在问题. 如果一条SQL平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以断定是执行计划出了问题. 看懂执行计划也就成了SQL优化的先决条件. 这里的SQL优化指的是SQL性能问题的定位,定位后就可以解决问题. 一. 

Oracle 执行计划(Explain Plan) 说明

如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的每一步执行是否存在问题. 如果一条SQL平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以断定是执行计划出了问题.              看懂执行计划也就成了SQL优化的先决条件. 这里的SQL优化指的是SQL性能问题的定位,定位后就可以解决问题.     一.         查看执行计划的三种方法 1.1 设置autotrace 序号 命令 解释 1 SET AUTOTRACE