根据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
 
 

Full scan vs index 执行计划的实验的更多相关文章

  1. Oracle中的执行计划

    使用autotrace sqlplus系统参数:SQL> set autotrace trace onSQL> select * from dual;DUM---XExecution Pl ...

  2. SQL Server 性能调优 之执行计划(Execution Plan)调优

    SQL Server 存在三种 Join 策略:Hash Join,Merge Join,Nested Loop Join. Hash Join:用来处理没有排过序/没有索引的数据,它在内存中把 Jo ...

  3. PostgreSQL执行计划:Bitmap scan VS index only scan

    之前了解过postgresql的Bitmap scan,只是粗略地了解到是通过标记数据页面来实现数据检索的,执行计划中的的Bitmap scan一些细节并不十分清楚.这里借助一个执行计划来分析bitm ...

  4. 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这四者的区别 ...

  5. 执行计划中常见index访问方式(转)

    近期有朋友对于单个表上的index各种情况比较模糊,这里对于单个表上,单个index出现的大多数情况进行了总结性测试,给出了测试结果,至于为什么出现这样的试验结果未做过多解释,给读者留下思考的空间.本 ...

  6. MySQL执行计划extra中的using index 和 using where using index 的区别

    本文出处:http://www.cnblogs.com/wy123/p/7366486.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

  7. 索引使用,分析初探。(explain分析执行计划,以及强制使用force index)

    促使这次探索的初衷还是因为要对一个定时脚本性能进行优化. 脚本有两个指定状态分别是status, latest_process_status,和一个超期时间expire_time进行限制. 按照我以前 ...

  8. [z]Oracle性能优化-读懂执行计划

    http://blog.csdn.net/lifetragedy/article/details/51320192 Oracle的执行计划   得到执行计划的方式       Autotrace例子 ...

  9. Oracle 课程五之优化器和执行计划

    课程目标 完成本课程的学习后,您应该能够: •优化器的作用 •优化器的类型 •优化器的优化步骤 •扫描的基本类型 •表连接的执行计划 •其他运算方式的执行计划 •如何看执行计划顺序 •如何获取执行计划 ...

随机推荐

  1. hdu1702 ACboy needs your help again!(栈处理)

    ACboy needs your help again! Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  2. PIE SDK栅格生成等值线、面

      1.算法功能简介 等值线图能直观地展示数据的变化趋势,是众多领域展示成果的重要图建之一,被广泛应用于石油勘探.矿物开采.气象预报等众多领域.等值线的绘制是指从大量采样数据中提取出具有相同值的点的信 ...

  3. PIE SDK自定义滤波

    1.算法功能简介 自定义滤波可以自由设置滤波模板,对数据进行处理,自定义滤波器的一般规则要求: ( 1) 滤波器的大小应该是奇数,这样它才有一个中心,例如 3x3, 5x5 或者 7x7.有中心了,也 ...

  4. python学习12-反射 判断函数与方法(转载)

    一.三个内置函数 1.issubclass(a, b)  判断a类是否是b类的子类 class Foo: pass class Zi(Foo): pass class Sun(Zi): passpri ...

  5. Gradle发布项目到 maven(1)

    常见的 Maven 仓库 JCenter.MavenCenter.JitPack epositories { google() // google 仓库 jcenter() // JCenter 仓库 ...

  6. Maven---pom.xml 详解(转)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  7. Python 的 __new__()方法与实例化

    __new__() 是新式类中才有的方法,它执行在构造方法创建实例之前.可以这么理解,在 Python 中类中的构造方法 __init__() 负责将类实例化,而在 __init__() 启动之前,_ ...

  8. mac安装monkey工具

    一.monkey测试简介: monkey工具是Android自动化测试工具的一种,主要对Android,APP可进行压力测试.(总结) Monkey是Android中的一个命令行工具,可以运行在模拟器 ...

  9. hibernate 简单入门 配置

    hibernate两个配置文件,一个是类和表的映射关系文件,一个是数据库连接的配置文件 类和表的映射关系 <?xml version="1.0" encoding=" ...

  10. 新建maven工程index.jsp页面报错

    引入servlet依赖jar <dependency><groupId>javax.servlet</groupId><artifactId>servl ...