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索引一步到位(此文章为“数据库性能优化二:数据库表优化”附属文 ...
随机推荐
- 【C#】override,Abstract,Virtual 介绍及区别--转载
要扩展或修改继承的方法.属性.索引器或事件的抽象实现或虚实现,必须使用 override 修饰符. 1. override 方法提供从基类继承的成员的新实现.通过 override 声明重写的方法称为 ...
- IE10以下优雅降级(作为范例)
扒下来一段 优雅降级的代码. <!--[if lt IE 10]> <style> .ie-tip{margin-top: 100px;font-size: 16px;text ...
- notepad++上搭建gtk+2.0/3.x开发环境
前言 老师布置了一道题需要用到图形界面,于是开始找图形库.最后选择了gtk+图形库,然后折腾了大概一天. 这里记录自己新学到的知识,同时也给后来者一些便利. 准备 下载以下内容 notepad++(由 ...
- C语言中判断字符串str1是否以str2开始或结束
#include <stdlib.h> #include <string.h> #include <stdio.h> /**判断str1是否以str2开头 * 如果 ...
- java Html 转 PDF
Html 转 PDF 使用 flying-saucer 插件来完成 导入flying-saucer依赖 <dependency> <groupId>org.xhtmlrende ...
- JAVA-4NIO之Channel之间的数据传输
转载:自并发编程网ifeve.com 在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个c ...
- SQLAlchemy之SQL Expression
SQLAlchemy是一个强大的Python SQL工具箱, 提供了包括ORM在内的各种支持. 首先使用pip安装; pip install SQLAlchemy SQL Expression Lan ...
- IOS开发常见第三方总结
链接](https://github.com/languages/Objective-C/most_watched) * [three20](https://github.com/facebook ...
- Extjs报错处理
错误信息: IE:SCRIPT1009: 缺少 '}' FF: SyntaxError: identifier starts immediately after numeric literal ... ...
- hadoop学习笔记(六):HDFS文件的读写流程
一.HDFS读取文件流程: 详解读取流程: Client调用FileSystem.open()方法: 1 FileSystem通过RPC与NN通信,NN返回该文件的部分或全部block列表(含有blo ...