日期:2014-05-17  浏览次数:21075 次

请教一个索引的问题:为什么建了索引的表查询还会全表扫描
要查询的SQL如下:
SQL code
SELECT SJGD.C_SJXZ,
       SJGD.C_GDID,
       SJGD.C_LSH,
       SJGD.C_GDMC,
       SJGD.C_ZT,
       SJGD.C_YXJ,
       SJGD.C_LB,
       SJGD.D_CJSJ,
       SJGD.C_CJR,
       RYXX.C_XM,
       RYXX.C_BM,
       RYXX.C_DW
  from T_SJGL_GD SJGD
  LEFT OUTER JOIN T_GY_XGRYXX RYXX on SJGD.C_GDID = RYXX.C_GDID
 WHERE RYXX.C_DW = '-999999999999889';


生成的执行计划如下:
SELECT STATEMENT, GOAL = ALL_ROWS 21 711 146466
 HASH JOIN 21 711 146466
  TABLE ACCESS FULL THUNIITSMUSER T_GY_XGRYXX 6 711 37683
  TABLE ACCESS FULL THUNIITSMUSER T_SJGL_GD 14 821 125613

对T_SJGL_GD表几乎用到的都建了索引,对T_GY_XGRYXX表的C_GDID和C_DW建立了单独的索引,现在是开发环境只有几千条数据,在生产环境中有几十万条数据。

------解决方案--------------------
HASH JOIN 是不走索引的,数据量的不同会影响执行计划,大数据量的时候Hash JOIN的效率会更好。

------解决方案--------------------
数据量小的时候,全表扫描要比走索引快,具体原因简单讲就是索引存在2次i/o 问题
这也是oracle 优化器作用的体现。

探讨

原来是数据量的问题,我换成生产库就能用索引了。

------解决方案--------------------
0、oracle读取磁盘数据的速度要不在内存里读取数据慢10000倍左右,因此越少的磁盘i/o 性能越好
1、oracle读取数据最小单位是数据块
2、每次读取的数据块个数是一定的
3、每个数据库里放的数据也是一定的
4、假设一次读取10个数据块,每个数据块里面10条数据,那么一次读取能读取 10*10=100条数据
5、假设一个表里面有1W条记录,现在要查询里面的800条记录
6、那么全表扫描只需要 读取100次即可把全表1W条数据读取完毕,并找到里面的800条数据
7、如果走索引,需要读取8次将索引放入内存,然后对每一条记录得到rowid 上磁盘上取下一条数据 总共需要810次
8、所以走索引不一定块。



探讨

引用:
数据量小的时候,全表扫描要比走索引快,具体原因简单讲就是索引存在2次i/o 问题
这也是oracle 优化器作用的体现。


引用:

原来是数据量的问题,我换成生产库就能用索引了。


另外 跟 原始数据量大小 以及符合条件的数据量大小
分别是什么关系请问