[20131121]奇怪的执行计划变化.txt

[20131121]奇怪的执行计划变化.txt

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,lpad('x',1000,'x')  name from dual connect by level
create index i_t_id on t(id) ;
exec dbms_stats.gather_table_stats(user, 'T',  no_invalidate => false);

SCOTT@test> alter session set statistics_level=all;
Session altered.

SCOTT@test> select avg(id) from t;
   AVG(ID)
----------
     500.5

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  1kadrxzj9ahk7, child number 0
-------------------------------------
select avg(id) from t
Plan hash value: 3548397654
-------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name   | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |      1 |        |     3 (100)|      1 |00:00:00.01 |       6 |
|   1 |  SORT AGGREGATE       |        |      1 |      1 |            |      1 |00:00:00.01 |       6 |
|   2 |   INDEX FAST FULL SCAN| I_T_ID |      1 |   1000 |     3   (0)|   1000 |00:00:00.01 |       6 |
-------------------------------------------------------------------------------------------------------
14 rows selected.

--可以发现执行计划选择了INDEX FAST FULL SCAN.逻辑读=6.

但是如果语句修改为select avg(id)+1 from t; 加入了运算,结果如何呢?
SCOTT@test> select avg(id)+1 from t;
 AVG(ID)+1
----------
     501.5

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  4d54cp5vqmzt0, child number 0
-------------------------------------
select avg(id)+1 from t
Plan hash value: 2966233522
--------------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |   279 (100)|      1 |00:00:00.01 |    1004 |
|   1 |  SORT AGGREGATE    |      |      1 |      1 |            |      1 |00:00:00.01 |    1004 |
|   2 |   TABLE ACCESS FULL| T    |      1 |   1000 |   279   (0)|   1000 |00:00:00.01 |    1004 |
--------------------------------------------------------------------------------------------------
14 rows selected.

--仅仅改为avg(id)+1,执行计划就发生了变化,变为TABLE ACCESS FULL.逻辑读=1004.
--加入条件id is not null 才可以解决这个问题.

SCOTT@test> select avg(id)+1 from t where id is not null;
 AVG(ID)+1
----------
     501.5

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  7bpga35zfgxb0, child number 0
-------------------------------------
select avg(id)+1 from t where id is not null
Plan hash value: 3548397654
-------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name   | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |      1 |        |     3 (100)|      1 |00:00:00.01 |       6 |
|   1 |  SORT AGGREGATE       |        |      1 |      1 |            |      1 |00:00:00.01 |       6 |
|*  2 |   INDEX FAST FULL SCAN| I_T_ID |      1 |   1000 |     3   (0)|   1000 |00:00:00.01 |       6 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("ID" IS NOT NULL)
19 rows selected.

--修改id为not null.
SCOTT@test> alter table scott.t modify(id  not null);
Table altered.

SCOTT@test> select avg(id)+1 from t ;
 AVG(ID)+1
----------
     501.5

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  4997mr261xaua, child number 0
-------------------------------------
select avg(id)+1 from t
Plan hash value: 3548397654
-------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name   | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |      1 |        |     3 (100)|      1 |00:00:00.01 |       6 |
|   1 |  SORT AGGREGATE       |        |      1 |      1 |            |      1 |00:00:00.01 |       6 |
|   2 |   INDEX FAST FULL SCAN| I_T_ID |      1 |   1000 |     3   (0)|   1000 |00:00:00.01 |       6 |
-------------------------------------------------------------------------------------------------------

参考:http://alexanderanokhin.wordpress.com/2013/11/16/filter-is-not-null/
给出了更加有意思的测试.

时间: 2024-07-30 10:55:39

[20131121]奇怪的执行计划变化.txt的相关文章

[20120214]异常数据导致执行计划改变.txt

今天上午,用户反应一条sql执行有点慢.我检查发现,原来使用索引的语句现在变成了全表扫描,而且昨晚oracle数据库自动分析过这个表. 语句很复杂,抽取有问题的部分: SELECT *  FROM med_operation_schedule a WHERE (       scheduled_date_time >= TO_DATE ('2012-02-15 00:00', 'yyyy-mm-dd hh24:mi')           AND scheduled_date_time     

[20120915]10046事件与执行计划改变.txt

    使用10046事件来跟踪解决oracle的许多问题,是非常常用的手段,但是实际上可能出现跟踪的sql执行计划与原来不同的情况,自己应该引起注意. 测试如下: 1.测试环境建立: SQL> select * from v$version ; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition

一条SQL语句的执行计划变化探究(r10笔记第9天)

继续上次分析的一个问题,一个简单的SQL语句执行计划有些奇怪,明明可以走唯一性索引但是却走了另外一个索引. 当然了,最后逐步定位,发现是在直方图的地方有一些差别.取消直方图之后,执行计划立刻恢复了正常. 当然问题来了,这个是为什么呢,收集统计信息中的auto选项是什么含义呢.为什么两个数据类型一样的(varchar2(64))的列,境遇却大大不同. 我们来看看一些统计信息的数据. 为了跟进一步验证数据的分布律和选取代价,我们查询它的直方图信息. SQL>   select to_char(end

执行计划变化导致CPU负载高的问题分析

前几天碰到一个CPU负载较高的问题.从系统层面来看,情况不是很严重,但是从应用的角度来说,已经感觉到很慢了.因为前端的调用频率还是比较高.所以会把这个问题放大. 使用top -c查看了基本的服务器信息.可以看到负载大概在30%左右.IO wait不高. top - 19:30:48 up 179 days,  4:54,  3 users,  load average: 4.43, 4.28, 4.14 Tasks: 669 total,   6 running, 661 sleeping,  

[20121212]谨慎使用set autotrace traceonly查看执行计划[补充].txt

使用toad自带sqlmonitor,toad10以上版本现在叫sqltrace. 12:00:24 SQL> set autotrace traceonly ;12:01:23 SQL> select * from t2 where id=45; 10000 rows selected. Execution Plan----------------------------------------------------------Plan hash value: 1513984157 ---

一条SQL语句的执行计划变化探究

最近有个同事碰到一个问题,想让我给点思路.我大体了解了一下,是一个系统目前在做压力测试,但是经业务反馈发现某个环节的处理时间有些长,排查了一圈,最后这件事情就落在了DB这边,希望DB能够给点意见,是否存在一些性能瓶颈.     我们从开发同学那里得到的一个基本的SQL语句,根据关键字从v$sql中做了提取,发现对应的SQL语句的执行时间还是OK的. 得到的SQL语句如下:SQL_ID        SQL_FULLTEXT ------------- ----------------------

【OUTLINE】使用Oracle Outline技术暂时锁定SQL的执行计划

  Oracle的Outline技术可以在特殊情况下保证执行计划的稳定性.在极端情况下可以使用此项技术实现暂时锁定执行计划的目的.  主要使用场景如下:  ①短时间内无法完成SQL的优化任务,此时可以使用outline暂时锁定SQL执行计划:  ②在CBO优化模式下,当统计信息出现问题时,会导致执行计划出现异常变化,此时可以使用outline暂时调整SQL执行计划:  ③由于数据库的bug导致SQL的执行计划出现异常,使用outline锁定执行计划.   记录一下关于outline的使用方法,供

[20130909]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED.txt

[20130909]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED.txt 在写[20130809]12c Clustering Factor.txt,链接 提到执行计划里面存在TABLE ACCESS BY INDEX ROWID BATCHED,这里的BATCHED表示什么? 自己不是很清楚. 既然多了一个batched,一定与原来的不同,具体含义是什么呢?做一些简单的探究: 1.建立测试环境: SCOTT@test01p> @ver BANNER  

[20120104]稳定一条sql语句的执行计划.txt

[20120104]稳定一条sql语句的执行计划.txt http://www.itpub.net/thread-1495845-1-1.htmlhttp://space.itpub.net/267265/viewspace-723066 ORACLE8I升级11G R2后,查询系统视图特别慢 我的测试版本:SQL> select * from v$version where rownumBANNER------------------------------------------------