根据Oracle-L邮件列表里主题「
Full scan vs index
」的讨论而来。
1、测试环境创建
SYS@HEMESRHTDB2(1.206)> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE11.2.0.3.0Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
SYS@HEMESRHTDB2(1.206)>
create table t2
as
with generator as (
select --+ materialize
rownum pk
from all_objects
where rownum<=4000
)
select
/*+ ordered use_nl(v2)*/
rownum pk,
round(dbms_random.value(1,2)) a,
round(dbms_random.value(1,5)) b,
round(dbms_random.value(1,10)) c,
round(dbms_random.value(1,100)) d,
round(dbms_random.value(1,1000000)) e
from
generator v1,
generator v2
where
rownum<=600000
/
Table created.
SYS@HEMESRHTDB2(1.206)> select * from t2 where rownum<=100;
PK A B C DE
---------- ---------- ---------- ---------- ---------- ----------
1 2 1 3 80 296354
2 2 3 9 47 531531
3 2 3 1 10 330623
4 2 5 2 35 21138
5 2 5 7 50 425066
6 2 3 9 75 322065
7 2 4 1 93 55360
8 2 1 8 99 378844
9 2 5 8 72 869863
10 2 5 2 63 373369
11 1 4 4 37 313221
12 1 5 8 68 40918
13 1 2 8 48 457786
14 2 3 2 83 316507
15 1 4 2 14 734118
16 1 4 7 59 47266
……
……
SYS@HEMESRHTDB2(1.206)> create index ix_t2_key on t2(PK,A) online nologging;
Index created.
SYS@HEMESRHTDB2(1.206)> create index ix_t2_D on t2(D) online nologging;
Index created.
SYS@HEMESRHTDB2(1.206)> alter session set statistics_level ='ALL' ;
Session altered.
2、测试4种情况
索引情况。
ix_t2_key on t2(PK,A)
ix_t2_D on t2(D)
Select count(*) from T2 where pk > 520000;
select count(*) from t2 where A=1;
Select count(D) from T2 where pk > 520000;
3、测试
实验1
SYS@HEMESRHTDB2(1.206)> select count(*) from T2 where pk > 520000;
SYS@HEMESRHTDB2(1.206)> select * from TABLE(dbms_xplan.display_cursor(NULL,NULL,'allstats last ADVANCED PEEKED_BINDS'));
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID9c98xbdbfww9r, child number 0
-------------------------------------
Select count(*) from T2 where pk > 520000
Plan hash value: 2050414396
实验2
SYS@HEMESRHTDB2(1.206)> select count(*) from t2 where A=1;
COUNT(*)
----------
299737
SYS@HEMESRHTDB2(1.206)> select * from TABLE(dbms_xplan.display_cursor(NULL,NULL,'allstats last ADVANCED PEEKED_BINDS'));
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID651cjf8pmhb51, child number 0
-------------------------------------
select count(*) from t2 where A=1
Plan hash value: 2933116225
实验3
SYS@HEMESRHTDB2(1.206)> select count(D) from t2 where pk>=520000;
COUNT(D)
----------
80001
SYS@HEMESRHTDB2(1.206)> select * from TABLE(dbms_xplan.display_cursor(NULL,NULL,'allstats last ADVANCED PEEKED_BINDS'));
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID41uuvuyutgn6q, child number 0
-------------------------------------
select count(D) from t2 where pk>=520000
Plan hash value: 3321871023
4、结论和延伸
实验1
SYS@HEMESRHTDB2(1.206)> select count(*) from T2 where pk > 520000;
按照预期走索引IX_T2_KEY。
实验2
SYS@HEMESRHTDB2(1.206)> select count(*) from t2 where A=1;
也同预期。
实验3
SYS@HEMESRHTDB2(1.206)> select count(D) from t2 where pk>=520000;
为啥变成count(D)就完全不一样了?
我们加上index hint看看效果如何?
延伸实验 Index hint
SYS@HEMESRHTDB2(1.206)> select /*+ index(T2 IX_T2_KEY) */ count(D) from t2 where pk>=520000;
COUNT(D)
----------
80001
SYS@HEMESRHTDB2(1.206)> select * from TABLE(dbms_xplan.display_cursor(NULL,NULL,'allstats last ADVANCED PEEKED_BINDS'));
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID4s4zzmrzdzrbt, child number 0
-------------------------------------
select /*+ index(T2 IX_T2_KEY) */ count(D) from t2 where pk>=520000
Plan hash value: 948933721
这儿看起来好像有些眉目了,Cost虽然比全表扫描的要大,但真正耗用的buffers根本就不大。
问题出在统计信息!!?
SYS@HEMESRHTDB2(1.206)>
select
column_name,
num_distinct,
histogram, num_buckets,
to_char(LAST_ANALYZED, 'yyyy-mm-dd hh24:mi:ss')
from all_tab_col_statistics
where upper(table_name)='T2';
no rows selected
果然咧,这时收集下统计信息。
SYS@HEMESRHTDB2(1.206)>
begin
dbms_stats.gather_table_stats(
ownname => user,
tabname => 'T2',
estimate_percent =>100,
cascade => true);
end;
/
PL/SQL procedure successfully completed.
「for all columns 」或者 「for all indexed columns」都OK,重要的是覆盖count(D) 字段,CBO才能够计算出正确的cost。
可以加个/*1*/之类的使执行计划重新解析,或是alter system flush shared_pool;
嗯,随你喜欢。
SYS@HEMESRHTDB2(1.206)> select /*1*/ count(D) from t2 where pk>=520000;
SYS@HEMESRHTDB2(1.206)> select * from TABLE(dbms_xplan.display_cursor(NULL,NULL,'allstats last ADVANCED PEEKED_BINDS'));
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID6z1bc6xv0anrn, child number 0
-------------------------------------
select /*1*/ count(D) from t2 where pk>=520000
Plan hash value: 948933721
这个时候,便会选择正确的索引了,
当然,你也可以把D字段包含入索引IX_T2_KEY中。
最后:
如果扫描的范围再大一些?会发生什么?
10万/60万
SYS@HEMESRHTDB2(1.206)> select /*2*/ count(D) from t2 where pk>=500000;
COUNT(D)
----------
100001
SYS@HEMESRHTDB2(1.206)> select * from TABLE(dbms_xplan.display_cursor(NULL,NULL,'allstats last ADVANCED PEEKED_BINDS'));
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID7shudyqdb5nbk, child number 0
-------------------------------------
select /*2*/ count(D) from t2 where pk>=500000
Plan hash value: 3321871023

- Oracle中的执行计划
使用autotrace sqlplus系统参数:SQL> set autotrace trace onSQL> select * from dual;DUM---XExecution Pl ...
- SQL Server 性能调优 之执行计划(Execution Plan)调优
SQL Server 存在三种 Join 策略:Hash Join,Merge Join,Nested Loop Join. Hash Join:用来处理没有排过序/没有索引的数据,它在内存中把 Jo ...
- PostgreSQL执行计划:Bitmap scan VS index only scan
之前了解过postgresql的Bitmap scan,只是粗略地了解到是通过标记数据页面来实现数据检索的,执行计划中的的Bitmap scan一些细节并不十分清楚.这里借助一个执行计划来分析bitm ...
- MySQL 执行计划中Extra(Using where,Using index,Using index condition,Using index,Using where)的浅析
关于如何理解MySQL执行计划中Extra列的Using where.Using Index.Using index condition,Using index,Using where这四者的区别 ...
- 执行计划中常见index访问方式(转)
近期有朋友对于单个表上的index各种情况比较模糊,这里对于单个表上,单个index出现的大多数情况进行了总结性测试,给出了测试结果,至于为什么出现这样的试验结果未做过多解释,给读者留下思考的空间.本 ...
- MySQL执行计划extra中的using index 和 using where using index 的区别
本文出处:http://www.cnblogs.com/wy123/p/7366486.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- 索引使用,分析初探。(explain分析执行计划,以及强制使用force index)
促使这次探索的初衷还是因为要对一个定时脚本性能进行优化. 脚本有两个指定状态分别是status, latest_process_status,和一个超期时间expire_time进行限制. 按照我以前 ...
- [z]Oracle性能优化-读懂执行计划
http://blog.csdn.net/lifetragedy/article/details/51320192 Oracle的执行计划 得到执行计划的方式 Autotrace例子 ...
- Oracle 课程五之优化器和执行计划
课程目标 完成本课程的学习后,您应该能够: •优化器的作用 •优化器的类型 •优化器的优化步骤 •扫描的基本类型 •表连接的执行计划 •其他运算方式的执行计划 •如何看执行计划顺序 •如何获取执行计划 ...
随机推荐
- 简单的html渲染模板引擎
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- mysql 5.7.20 server status 是stopped的解决办法
mysql 5.7.20 server status 是stopped的解决办法 在安装mysql 5.7.20的过程中,前几个过程都没什么问题,但是最后一个步骤就出问题了.当check一直提示con ...
- SSH Intro - Remove entry
ssh-keygen -f "/home/frank/.ssh/known_hosts" -R ec2-54-222-218-195.cn-north-1.compute.amaz ...
- TOJ 4394 Rebuild Road
描述 Once,in a kingdom,there are N cities.M roads have been buit such that from one city you can reach ...
- 1.3 js基础
1.操作样式 .style 操作行间样式 .className 直接修改class 2.操作属性 . 操作已有的属性 [] 点能做的方括号都能做,方括号里放字符串,能放变量. 3. ...
- 机器学习——GBDT
基础概念 GBDT(Gradient Boosting Decision Tree) 全称梯度提升决策树,是一种迭代的决策树算法.GBDT是集成学习Boosting的家族成员,GBDT中的树是回归树, ...
- Javascript模块化编程(三)require.js的用法及功能介绍
这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战.我采用的是一个非常流行的库require.js感兴趣的朋友可以了解下啊 我采用的是一个非常流行的 ...
- Linux防火墙/iptables使用
iptables是linux下的防火墙组件服务,这两天一直使用,总结一下使用方法: 1.检查iptables是否安装 rpm -qa|grep iptables 如果没有安装该组件,可以通过yum i ...
- [转]Oracle job procedure 存储过程定时任务
本文转自:http://www.cnblogs.com/hoojo/p/oracle_procedure_job_interval.html oracle job有定时执行的功能,可以在指定的时间点或 ...
- windows下配置nginx环境
一. nginx软件拷贝 拷贝 nginx文件 到对应的服务目录中 如 E:/service/nginx nginx文件地址: 链接: http://pan.baidu.com/s/1c25oq6O ...