SQL索引未使用
针对自己曾经经历过的一道面试题,那些情况不走索引,于是搜索网络和书籍的一些资料,整理如下:
1、查询谓词没有使用索引的主要边界,换句话说就是select *,可能会导致不走索引。比如,你查询的是SELECT * FROM T WHERE Y=XXX;假如你的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 id<>100
8、表字段的属性导致不走索引,字符型的索引列会导致优化器认为需要扫描索引大部分数据且聚簇因子很大,最终导致弃用索引扫描而改用全表扫描方式由于字符型和数值型的在insert的时候排序不同,字符类型导致了聚簇因子很大,原因是插入顺序与排序顺序不同。详细点说,就是按照数字类型插入(1..3200000),按字符类型('1'...'32000000')t排序,在对字符类型使用大于运算符时,会导致优化器认为需要扫描索引大部分数据且聚簇因子很大,最终导致弃用索引扫描而改用全表扫描方式。
下面展示测试结果,
两个表的数据类型相似(只是ID字段类型不同),各插入了320万数据,ID字段范围为1~3200000。

模拟场景相关代码如下:

对于普通的采用数值类型的字段,范围查询就是正常的索引范围扫描,执行效率很高。

对于文本类型字段的表,范围查询就是对应的全表扫描,效率较低是显而易见的。
解决方法

将SQL语句由开放区间扫描(>=),修改为封闭区间(between xxx and max_value)。使得数据在索引局部顺序是“对的”。如果采用这种方式仍然不走索引扫描,还可以进一步细化分段或者采用“逐条提取+批绑定”的方法。
9.建立组合索引,但查询谓词并未使用组合索引的第一列,此处有一个INDEX SKIP SCAN概念,
10、like '%liu' 百分号在前请输入标题
11,not 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 RN FROM CIRCLEICONMAST I WHERE I.REGDT BETWEEN TO_DATE('20120619', 'YYYYMMDD') - 10000 AND TO_DATE('20120621', 'YYYYMMDD') AND NOT EXISTS ( SELECT C.VALIDFLG FROM CIRCLEMAST C WHERE 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 RN FROM CIRCLEICONMAST I, CIRCLEMAST CWHERE I.REGDT BETWEEN TO_DATE('20110620', 'YYYYMMDD') AND TO_DATE('20120621', 'YYYYMMDD') + 1 AND C.VALIDFLG NOT IN ('N', 'F') AND I.CIRCLEID = C.CIRCLEID AND I.ADMCHK = 'N'
SQL索引未使用的更多相关文章
- 我的SQL总结---未完待续
我的SQL总结---未完待续 版权声明:本文为博主原创文章,未经博主允许不得转载. 总结: 主要的SQL 语句: 数据操作(select, insert, delete, update) 访问控制(g ...
- 为何在查询中索引未被使用 (Doc ID 1549181.1)
To Bottom * 为何在查询中索引未被使用 (Doc ID 1549181.1) To Bottom 文档内容 用途 排错步骤 高速检查 表上是否存在索引? 索引是否应该 ...
- SQL索引管理器 - 用于SQL Server和Azure上的索引维护的免费GUI工具
我作为SQL Server DBA工作了8年多,管理和优化服务器的性能.在我的空闲时间,我想为宇宙和我的同事做一些有用的事情.这就是我们最终为SQL Server和Azure 提供免费索引维护工具的方 ...
- SQL索引学习-索引结构
前一阵无意中和同事讨论过一个SQL相关的题(通过一个小问题来学习SQL关联查询),很惭愧一个非常简单的问题由于种种原因居然没有回答正确,数据库知识方面我算不上技术好,谈起SQL知识的学习我得益于200 ...
- SQL索引学习-聚集索引
这篇接着我们的索引学习系列,这次主要来分享一些有关聚集索引的问题.上一篇SQL索引学习-索引结构主要是从一些基础概念上给大家分享了我的理解,没有实例,有朋友就提到了聚集索引的问题,这里列出来一下: 其 ...
- 数据库性能优化:SQL索引
SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? SQL索引有两种,聚集索引和非聚集索引 ...
- SQL索引一步到位
以下均非原创,仅供分享.学习!!! SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱. 1.1 什么是索引? S ...
- {好文备份}SQL索引一步到位
SQL索引一步到位(此文章为"数据库性能优化二:数据库表优化"附属文章之一) SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百 ...
- 转载:SQL索引一步到位
原文: http://www.cnblogs.com/AK2012/archive/2013/01/04/2844283.html SQL索引一步到位(此文章为“数据库性能优化二:数据库表优化”附属文 ...
随机推荐
- SPSS学习系列之SPSS Modeler怎么修改默认的内存大小(图文详解)
不多说,直接上干货! 问题来源: 如果你的电脑内存配置比较低的话,会随着数据量增加(尤其是大数据),带不起的情况很有可能发生,会出现一些内存报错... ... 解决办法: 打开“工具”,在modele ...
- Linux笔记:linux常用命令
文件目录操作 1.展示目录命令 ls # 展示当前目录下的可见文件 ls -a # 展示当前目录下所有的文件(包括隐藏的文件) ls -l # 展示当前目录下文件的详细信息 ll # 展示当前目录下文 ...
- 用python写一个爬虫——爬取性感小姐姐
忍着鼻血写代码 今天写一个简单的网上爬虫,爬取一个叫妹子图的网站里面所有妹子的图片. 然后试着先爬取了三页,大概有七百多张图片吧!各个诱人的很,有兴趣的同学可以一起来爬一下,大佬级程序员勿喷,简单爬虫 ...
- Java 集合框架(三)—— LinkedList
三.链表 —— LinkedList ArrayList 虽然好用,但是数组和数组列表都有一个重大的缺陷:从数组的中间位置删除一个元素要付出很大的代价,其原因是数组中处于被删除元素之后的所有元素都要向 ...
- JAVA 对象的行为 总结
对象的行为 1. 断点调试 a:定位(设置断点) b:启动调试 c:单步执行 观察变量(F5单步执行 F6单步跳过)d:修改2 static 静态 静态成员,为类的所有对象共享 在 ...
- NodeJS之 Express框架 app.use(express.static)
一 .设置静态文件目录 语法如下: app.use(express.static(_dirname + '/public')); //设置静态文件目录 注: 将静态文件目录设置为项目根目录 + ‘/p ...
- 为什么有int 和integer
1.Integer 是对象类型 int是原始类型 适用场合有很大的不同 之所以要把int封装成Integer 型 是因为 很多方法参数就只接收对象类型(Object) 还比如 范型 就只支持 对象类型 ...
- [WPF]记一个Win8"缩放级别"设置导致的问题
这是我电脑的分辨率设置: 关键在于设置了缩放级别"较大",即150%的缩放. 接下来在WinForm中用各种方法取得的屏幕分辨率都是缩放之后的,但是这个时候的鼠标事件中鼠标位置也是 ...
- MQ之如何做到消息幂等 (转 优秀)
一.缘起 MQ消息必达,架构上有两个核心设计点: (1)消息落地 (2)消息超时.重传.确认 再次回顾消息总线核心架构,它由 发送端.服务端.固化存储.接收端 四大部分组成. 为保证消息的可达性,超时 ...
- PHP中文件操作(2)-- 写文件
1.fread — 读取文件(可安全用于二进制文件) 语法:string fread ( int $handle , int $length ) $filename = "aa.txt&qu ...