根据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 课程五之优化器和执行计划
课程目标 完成本课程的学习后,您应该能够: •优化器的作用 •优化器的类型 •优化器的优化步骤 •扫描的基本类型 •表连接的执行计划 •其他运算方式的执行计划 •如何看执行计划顺序 •如何获取执行计划 ...
随机推荐
- hdu1702 ACboy needs your help again!(栈处理)
ACboy needs your help again! Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ( ...
- PIE SDK栅格生成等值线、面
1.算法功能简介 等值线图能直观地展示数据的变化趋势,是众多领域展示成果的重要图建之一,被广泛应用于石油勘探.矿物开采.气象预报等众多领域.等值线的绘制是指从大量采样数据中提取出具有相同值的点的信 ...
- PIE SDK自定义滤波
1.算法功能简介 自定义滤波可以自由设置滤波模板,对数据进行处理,自定义滤波器的一般规则要求: ( 1) 滤波器的大小应该是奇数,这样它才有一个中心,例如 3x3, 5x5 或者 7x7.有中心了,也 ...
- python学习12-反射 判断函数与方法(转载)
一.三个内置函数 1.issubclass(a, b) 判断a类是否是b类的子类 class Foo: pass class Zi(Foo): pass class Sun(Zi): passpri ...
- Gradle发布项目到 maven(1)
常见的 Maven 仓库 JCenter.MavenCenter.JitPack epositories { google() // google 仓库 jcenter() // JCenter 仓库 ...
- Maven---pom.xml 详解(转)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- Python 的 __new__()方法与实例化
__new__() 是新式类中才有的方法,它执行在构造方法创建实例之前.可以这么理解,在 Python 中类中的构造方法 __init__() 负责将类实例化,而在 __init__() 启动之前,_ ...
- mac安装monkey工具
一.monkey测试简介: monkey工具是Android自动化测试工具的一种,主要对Android,APP可进行压力测试.(总结) Monkey是Android中的一个命令行工具,可以运行在模拟器 ...
- hibernate 简单入门 配置
hibernate两个配置文件,一个是类和表的映射关系文件,一个是数据库连接的配置文件 类和表的映射关系 <?xml version="1.0" encoding=" ...
- 新建maven工程index.jsp页面报错
引入servlet依赖jar <dependency><groupId>javax.servlet</groupId><artifactId>servl ...