[20180316]为什么不使用INDEX FULL SCAN (MIN/MAX).txt
[20180316]为什么不使用INDEX FULL SCAN (MIN/MAX).txt
--//链接:http://www.itpub.net/thread-2100456-1-1.html.自己重复测试看看.
1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
SCOTT@book> create table t as select * from dba_objects ;
Table created.
SCOTT@book> create index i_t_object_id on t(object_id);
Index created.
--//分析表略.Method_Opt => 'FOR ALL COLUMNS SIZE 1 '.
2.测试:
SCOTT@book> select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
N10
---------------------
90461
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID f2u3nkrcsdzbb, child number 0
-------------------------------------
select /*+ index(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 2966233522
---------------------------------------------------------------------------
| Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 347 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | TABLE ACCESS FULL| T | 86989 | 424K| 347 (1)| 00:00:05 |
----------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / T@SEL$1
--//连索引都不用.设置约束object_id is null 看看.
SCOTT@book> delete from t where object_id is null ;
2 rows deleted.
SCOTT@book> commit ;
Commit complete.
SCOTT@book> alter table t modify(object_id not null);
Table altered.
SCOTT@book> select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
N10
---------------------
90461
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID f2u3nkrcsdzbb, child number 0
-------------------------------------
select /*+ index(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 4145094723
----------------------------------------------------------------------------------------------
| Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 195 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | FIRST ROW | | 86989 | 424K| 195 (1)| 00:00:03 |
| 3 | INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID | 86989 | 424K| 195 (1)| 00:00:03 |
----------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
3 - SEL$1 / T@SEL$1
Note
-----
- Warning: basic plan statistics not available. These are only collected when:
* hint 'gather_plan_statistics' is used for the statement or
* parameter 'statistics_level' is set to 'ALL', at session or system level
--//可以使用索引,并且走INDEX FULL SCAN (MIN/MAX).不加提示看看:
SCOTT@book> select /*+ inde111x(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
N10
---------------------
90461
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 1d6mkncu6tjms, child number 0
-------------------------------------
select /*+ inde111x(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 3095383276
----------------------------------------------------------------------------------------
| Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 54 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | INDEX FAST FULL SCAN| I_T_OBJECT_ID | 86989 | 424K| 54 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / T@SEL$1
Note
-----
- Warning: basic plan statistics not available. These are only collected when:
* hint 'gather_plan_statistics' is used for the statement or
* parameter 'statistics_level' is set to 'ALL', at session or system level
--//可以发现不加提示,虽然使用索引,但是执行计划走的是INDEX FAST FULL SCAN.
--//注意看一个细节:cost=54.而前面加提示:cost=195,为什么会这样,导致执行计划认为选择INDEX FAST FULL SCAN更优.
SCOTT@book> alter session set statistics_level=all;
Session altered.
SCOTT@book> select max(object_id) n10 from t;
N10
---------------------
90460
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID df1726cj0y4vz, child number 0
-------------------------------------
select max(object_id) n10 from t
Plan hash value: 2939893782
--------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 2 (100)| | 1 |00:00:00.01 | 2 |
| 1 | SORT AGGREGATE | | 1 | 1 | 5 | | | 1 |00:00:00.01 | 2 |
| 2 | INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID | 1 | 1 | 5 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 2 |
--------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / T@SEL$1
--//如果取最大值cost=2.问题集中在select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;的cost如何计算.
--//oraclenvl2,nvl函数有一个特点,要先运算第2,3个参数值.如下例子可以证明:
SYS@book> grant execute on sys.dbms_lock to scott;
Grant succeeded.
--//以scott用户执行:
CREATE OR REPLACE FUNCTION SCOTT.sleep (seconds IN NUMBER)
RETURN NUMBER AS
BEGIN
sys.dbms_lock.sleep(seconds);
RETURN seconds;
END;
/
SCOTT@book> set timing on
SCOTT@book> select nvl2(1,sleep(1),sleep(2)) from dual ;
NVL2(1,SLEEP(1),SLEEP(2))
-------------------------
1
Elapsed: 00:00:03.00
--//执行需要时间3秒.也就证明先运算sleep(1),sleep(2),在算第1个参数,oracle不会选择短路执行路径.
SCOTT@book> select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
N10
---------------------
90461
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID f2u3nkrcsdzbb, child number 0
-------------------------------------
select /*+ index(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 4145094723
---------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 195 (100)| | 1 |00:00:00.01 | 2 |
| 1 | SORT AGGREGATE | | 1 | 1 | 5 | | | 1 |00:00:00.01 | 2 |
| 2 | FIRST ROW | | 1 | 86989 | 424K| 195 (1)| 00:00:03 | 1 |00:00:00.01 | 2 |
| 3 | INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID | 1 | 86989 | 424K| 195 (1)| 00:00:03 | 1 |00:00:00.01 | 2 |
---------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
3 - SEL$1 / T@SEL$1
--//注意看E-Rows=86989.而前面select max(object_id) n10 from t;的E-Rows=1.可以认为当执行nvl2(max(object_id),max(object_id),3000000)+1时,
--//第2个参数max(object_id),oracle认为这个是变量,运算86989次.导致成本上升为195,通过10053定位看看.
--//而如果使用nvl函数nvl(max(object_id),3000000)+1,第2参数是常量,不需要这种的运算.
3.10053分析:
SCOTT@book> @ &r/10053on 12
Session altered.
SCOTT@book> Select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
N10
---------------------
90461
--//注意要改动sql语句,进行1次硬分析10053才跟踪到.
SCOTT@book> @ &r/10053off
Session altered.
--//检查转储:
-----------------------------
SYSTEM STATISTICS INFORMATION
-----------------------------
Using NOWORKLOAD Stats
CPUSPEEDNW: 3074 millions instructions/sec (default is 100)
IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
IOSEEKTIM: 10 milliseconds (default is 10)
MBRC: NO VALUE blocks (default is 8)
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: T Alias: T
#Rows: 86989 #Blks: 1270 AvgRowLen: 98.00 ChainCnt: 0.00
Index Stats::
Index: I_T_OBJECT_ID Col#: 4
LVLS: 1 #LB: 193 #DK: 86987 LB/K: 1.00 DB/K: 1.00 CLUF: 1368.00
User hint to use this index
Access path analysis for T
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for T[T]
Table: T Alias: T
Card: Original: 86989.000000 Rounded: 86989 Computed: 86989.00 Non Adjusted: 86989.00
Access Path: index (FullScan)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Index: I_T_OBJECT_ID
resc_io: 194.00 resc_cpu: 18778959
ix_sel: 1.000000 ix_sel_with_filters: 1.000000
Cost: 194.51 Resp: 194.51 Degree: 1
Best:: AccessPath: IndexRange
Index: I_T_OBJECT_ID
Cost: 194.51 Degree: 1 Resp: 194.51 Card: 86989.00 Bytes: 0
***************************************
--//注意看下划线部分 Access Path: index (FullScan).
--// Best:: AccessPath: IndexRange
--//对比如下的10053转储
SCOTT@book> @ &r/10053on 12
Session altered.
SCOTT@book> Select max(object_id) n10 from t;
N10
---------------------
90460
SCOTT@book> @ &r/10053off
Session altered.
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: T Alias: T
#Rows: 86989 #Blks: 1270 AvgRowLen: 98.00 ChainCnt: 0.00
Index Stats::
Index: I_T_OBJECT_ID Col#: 4
LVLS: 1 #LB: 193 #DK: 86987 LB/K: 1.00 DB/K: 1.00 CLUF: 1368.00
Access path analysis for T
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for T[T]
Table: T Alias: T
Card: Original: 86989.000000 Rounded: 86989 Computed: 86989.00 Non Adjusted: 86989.00
Access Path: TableScan
Cost: 346.74 Resp: 346.74 Degree: 0
Cost_io: 346.00 Cost_cpu: 27311919
Resp_io: 346.00 Resp_cpu: 27311919
Access Path: index (index (FFS))
Index: I_T_OBJECT_ID
resc_io: 54.00 resc_cpu: 11812878
ix_sel: 0.000000 ix_sel_with_filters: 1.000000
Access Path: index (FFS)
Cost: 54.32 Resp: 54.32 Degree: 1
Cost_io: 54.00 Cost_cpu: 11812878
Resp_io: 54.00 Resp_cpu: 11812878
Access Path: index (Min/Max)
Index: I_T_OBJECT_ID
resc_io: 2.00 resc_cpu: 14443
ix_sel: 0.000000 ix_sel_with_filters: 0.000000
Cost: 2.00 Resp: 2.00 Degree: 1
Best:: AccessPath: IndexRange
Index: I_T_OBJECT_ID
Cost: 2.00 Degree: 1 Resp: 2.00 Card: 1.00 Bytes: 0
***************************************
--//可以看出oracle分析得到的最佳执行计划实际上是Best:: AccessPath: IndexRange.
--//cost的成本实际上是IndexRange的成本.
SCOTT@book> select /*+ index(t) */ count(*) from t where object_id between 1 and 1e6;
COUNT(*)
----------
86987
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID 1ypsa9k66p3us, child number 0
-------------------------------------
select /*+ index(t) */ count(*) from t where object_id between 1 and 1e6
Plan hash value: 565091764
-----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 195 (100)| | 1 |00:00:00.03 | 194 |
| 1 | SORT AGGREGATE | | 1 | 1 | 5 | | | 1 |00:00:00.03 | 194 |
|* 2 | INDEX RANGE SCAN| I_T_OBJECT_ID | 1 | 86987 | 424K| 195 (1)| 00:00:03 | 86987 |00:00:00.02 | 194 |
-----------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID">=1 AND "OBJECT_ID"<=1000000)
--//注:一定要加提示/*+ index(t) */,不然执行计划会选择INDEX FAST FULL SCAN.而这样执行计划是INDEX RANGE SCAN.cost正好是195.
--//这样的结果导致执行计划不会选择INDEX FULL SCAN (MIN/MAX).
--//实际上可以使用Coalesce参数可以避免短路执行.
SCOTT@book> select Coalesce(1,sleep(1)) from dual ;
COALESCE(1,SLEEP(1))
--------------------
1
SCOTT@book> set timing on
SCOTT@book> select Coalesce(1,sleep(1)) from dual ;
COALESCE(1,SLEEP(1))
--------------------
1
Elapsed: 00:00:00.01
SCOTT@book> set timing off
--//Coalesce参数可以短路执行.
SCOTT@book> Select /*+ ind111ex(t,i_t_object_id) */ Coalesce(max(object_id),3000000)+1 n10 from t;
N10
---------------------
90461
SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
--------------------------------------
SQL_ID 7m1705d3c8b1c, child number 0
-------------------------------------
Select /*+ ind111ex(t,i_t_object_id) */
Coalesce(max(object_id),3000000)+1 n10 from t
Plan hash value: 2939893782
--------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 2 (100)| | 1 |00:00:00.01 | 2 |
| 1 | SORT AGGREGATE | | 1 | 1 | 5 | | | 1 |00:00:00.01 | 2 |
| 2 | INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID | 1 | 1 | 5 | 2 (0)| 00:00:01 | 1 |00:00:00.01 | 2 |
--------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$1 / T@SEL$1
--//最主要问题在于开发根本不应该使用nvl2函数.nvl,Coalesce就没有问题.
[20180316]为什么不使用INDEX FULL SCAN (MIN/MAX).txt的更多相关文章
- Oracle 11G INDEX FULL SCAN 和 INDEX FAST FULL SCAN 对比分析
SQL> drop table test; 表已删除. SQL> create table test as select * from dba_objects where 1!=1; 表已 ...
- 【每日一摩斯】-Index Skip Scan Feature (212391.1)
INDEX Skip Scan,也就是索引快速扫描,一般是指谓词中不带复合索引第一列,但扫描索引块要快于扫描表的数据块,此时CBO会选择INDEX SS的方式. 官方讲的,这个概念也好理解,如果将复合 ...
- INDEX FAST FULL SCAN和INDEX FULL SCAN
INDEX FULL SCAN 索引全扫描.单块读 .它扫描的结果是有序的,因为索引是有序的.它通常发生在 下面几种情况(注意:即使SQL满足以下情况 不一定会走索引全扫描) 1. SQL语句有ord ...
- Index Full Scan vs Index Fast Full Scan-1103
[Oracle] Index Full Scan vs Index Fast Full Scan作者:汪海 (Wanghai) 日期:14-Aug-2005 出处:http://spaces.msn. ...
- index full scan/index fast full scan/index range scan
**************************1************************************* 索引状态: valid. N/A . ...
- index unique scan
INDEX UNIQUE SCAN 索引唯一扫描.单块读 只可能发生在unique index/primary key 等值查找 等待事件:db file s ...
- INDEX RANG SCAN无需回表的情况
create table a3 as select * from dba_objects create index a3_idx1 on a3(owner); select owner from a3 ...
- 索引跳跃式扫描(INDEX SKIP SCAN)
索引跳跃式扫描(INDEX SKIP SCAN) 索引跳跃式扫描(INDEX SKIP SCAN)适用于所有类型的复合B树索引(包括唯一性索引和非唯一性索引),它使那些在where条件中没有对目标索引 ...
- 索引全扫描(INDEX FULL SCAN)
所谓的索引全扫描(INDEX FULL SCAN)就是指要扫描目标索引所有叶子块的所有索引行.这里需要注意的是,索引全扫描需要扫描目标索引的所有叶子块,但这并不意味着需要扫描该索引的所有分支块.在默认 ...
随机推荐
- javascript 异步解析
js 异步解析 一 .js单线程分析 我们都知道js的一大特点是单线程,也就是同一时间点,只能处理一件事,一句js代码.那为什么js要设计成单线程而不是多线程呢?这主要和js的用途有关,js作为浏览器 ...
- python之装饰器(decorator)
python的装饰器如果用得好,那是大神,用的不好最好别用... 装饰器(decorator)主要包含俩大属性: 1.不能改变原有函数的调用方式 2.不能改变原有函数的代码 第一个表示,我不需要改变原 ...
- python异步编程--回调模型(selectors模块)
目录 0. 参考地址 1. 前言 2. 核心类 3. SelectSelector核心函数代码分析 3.1 注册 3.2 注销 3.3 查询 4. 别名 5. 总结 6. 代码报错问题 1. 文件描述 ...
- for in 循环 和for循环 for of循环
for in 循环得到的是数组的key值 for in 循环用以遍历对象的属性 var scores=[10,11,12]; var total=0; for(var score in scores ...
- OkHttp3 简述
- Python编码和Unicode
原文链接: ERIC MORITZ 翻译: 伯乐在线- 贱圣OMG译文链接: http://blog.jobbole.com/50345/ 我确定有很多关于Unicode和Python的说明,但为 ...
- DevExpress GridControl小结
1. 如何解决单击记录整行选中的问题 View->OptionsBehavior->EditorShowMode 设置为:Click 2. 如何新增一条记录 (1).gridView.Ad ...
- postgres 更新数据表
新增非空列: alter table t_test add column user_id integer; update t_test set user_id=0; alter table t_tes ...
- JSP+Servlet+mysql简单示例【图文教程】
下载MYSQL:http://dev.mysql.com/downloads/ 下载安装版的 然后安装(安装步骤就不详细说了) 安装好之后,点击托盘图标,打开管理工具 创建一个数据库 数据库的名字 ...
- C# Code First 配置(二)
上一篇文章地址 C# Code First 配置 此文章主要介绍配置映射到表中的详细字段.信息等,如下: System.ComponentModel.DataAnnotations 包含的特性: At ...