宜昌商城网站建设,百度一下首页网页手机版,震旦网站谁做的,太原企业建站系统转载自 sql中索引不会被用到的几种情况
1、查询谓词没有使用索引的主要边界,换句话说就是select *#xff0c;可能会导致不走索引。
比如#xff0c;你查询的是SELECT * FROM T WHERE YXXX;假如你的T表上有一个包含Y值的组合索引#xff0c;但是优化器会认为需要一行行的…转载自 sql中索引不会被用到的几种情况
1、查询谓词没有使用索引的主要边界,换句话说就是select *可能会导致不走索引。
比如你查询的是SELECT * FROM T WHERE YXXX;假如你的T表上有一个包含Y值的组合索引但是优化器会认为需要一行行的扫描会更有效这个时候优化器可能会选择TABLE ACCESS FULL但是如果换成了SELECT Y FROM T WHERE Y XXX优化器会直接去索引中找到Y的值因为从B树中就可以找到相应的值。 2、单键值的b树索引列上存在null值导致COUNT(*)不能走索引。
如果在B树索引中有一个空值那么查询诸如SELECT COUNT(*) FROM T 的时候因为HASHSET中不能存储空值的所以优化器不会走索引有两种方式可以让索引有效一种是SELECT COUNT(*) FROM T WHERE XXX IS NOT NULL或者把这个列的属性改为not null (不能为空)。 3、索引列上有函数运算导致不走索引
如果在T表上有一个索引Y但是你的查询语句是这样子SELECT * FROM T WHERE FUN(Y) XXX。这个时候索引也不会被用到因为你要查询的列中所有的行都需要被计算一遍因此如果要让这种sql语句的效率提高的话在这个表上建立一个基于函数的索引比如CREATE INDEX IDX FUNT ON T(FUN(Y));这种方式等于Oracle会建立一个存储所有函数计算结果的值再进行查询的时候就不需要进行计算了因为很多函数存在不同返回值因此必须标明这个函数是有固定返回值的。 4、隐式转换导致不走索引。
索引不适用于隐式转换的情况比如你的SELECT * FROM T WHERE Y 5 在Y上面有一个索引但是Y列是VARCHAR2的那么Oracle会将上面的5进行一个隐式的转换SELECT * FROM T WHERE TO_NUMBER(Y) 5,这个时候也是有可能用不到索引的。 5、表的数据库小或者需要选择大部分数据不走索引
在Oracle的初始化参数中有一个参数是一次读取的数据块的数目比如你的表只有几个数据块大小而且可以被Oracle一次性抓取那么就没有使用索引的必要了因为抓取索引还需要去根据rowid从数据块中获取相应的元素值因此在表特别小的情况下索引没有用到是情理当中的事情。
6、cbo优化器下统计信息不准确导致不走索引
很长时间没有做表分析或者重新收集表状态信息了在数据字典中表的统计信息是不准确的这个情况下可能会使用错误的索引这个效率可能也是比较低的。
7、或者(不等于可能导致不走索引也可能走 INDEX FAST FULL SCAN
例如select id from test where id100
8、表字段的属性导致不走索引字符型的索引列会导致优化器认为需要扫描索引大部分数据且聚簇因子很大最终导致弃用索引扫描而改用全表扫描方式
由于字符型和数值型的在insert的时候排序不同字符类型导致了聚簇因子很大原因是插入顺序与排序顺序不同。详细点说就是按照数字类型插入1..3200000按字符类型1...32000000t排序在对字符类型使用大于运算符时会导致优化器认为需要扫描索引大部分数据且聚簇因子很大最终导致弃用索引扫描而改用全表扫描方式。
下面展示测试结果
两个表的数据类型相似只是ID字段类型不同各插入了320万数据ID字段范围为1~3200000。
模拟场景
相关代码如下
对于普通的采用数值类型的字段范围查询就是正常的索引范围扫描执行效率很高。
对于文本类型字段的表范围查询就是对应的全表扫描效率较低是显而易见的。
解决方法 将SQL语句由开放区间扫描修改为封闭区间between xxx and max_value。使得数据在索引局部顺序是“对的”。如果采用这种方式仍然不走索引扫描还可以进一步细化分段或者采用“逐条提取批绑定”的方法。 9.建立组合索引但查询谓词并未使用组合索引的第一列此处有一个INDEX SKIP SCAN概念,
10、like %liu 百分号在前
11not in ,not exist
可以尝试把not in 或者 not exsts改成左连接的方式前提是有子查询并且子查询有where条件。
例如
SELECT/* INDEX(I CIRCLEICONMAST_IX1)*/I.ICONNO,I.CIRCLEID,I.FILEPATH,I.REGDT,I.FILEPATH || / || I.FILENAME IMGNAME,I.FILEPATH || / || th_160_ || I.FILENAME SMALLIMGNAME,I.MEMBERID,I.ADMCHK STATUS,I.ADMCHK ORIGINALSTATUS,ROWNUM RNFROM CIRCLEICONMAST IWHERE I.REGDT BETWEEN TO_DATE(20120619, YYYYMMDD) - 10000 ANDTO_DATE(20120621, YYYYMMDD)AND NOT EXISTS (SELECT C.VALIDFLGFROM CIRCLEMAST CWHERE C.VALIDFLG IN (N, F)AND I.CIRCLEID C.CIRCLEID) AND I.ADMCHK N
改成左连接
SELECT/* INDEX(I CIRCLEICONMAST_IX1)*/I.ICONNO,I.CIRCLEID,I.FILEPATH,I.REGDT,I.FILEPATH || / || I.FILENAME IMGNAME,I.FILEPATH || / || th_160_ || I.FILENAME SMALLIMGNAME,I.MEMBERID,I.ADMCHK STATUS,I.ADMCHK ORIGINALSTATUS,ROWNUM RNFROM CIRCLEICONMAST I, CIRCLEMAST CWHERE I.REGDT BETWEEN TO_DATE(20110620, YYYYMMDD) ANDTO_DATE(20120621, YYYYMMDD) 1AND C.VALIDFLG NOT IN (N, F)AND I.CIRCLEID C.CIRCLEIDAND I.ADMCHK N
总结oracle中有很多情况会导致index失效并且走全表扫描的代价是相当大的所以在写sql的时候一定要注意这个会使索引失效的情况养成良好的习惯。