请教一个索引的问题:为什么建了索引的表查询还会全表扫描
要查询的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、所以走索引不一定块。