数据库索引失效

一.索引失效的情况

第1种情况(一些特殊符号):

    例如: select * from emp where ename like '%T'; 字段ename上即使添加了索引,也不会走索引,为什么?
      原因模糊匹配like当中以“%”开头了,mysql找不到。另外<>,not exists,not in也不会走索引;

第2种情况:

     使用or,or两边的条件字段都有索引,才会走索引;其中任意一边的任何一个字段没有索引,那么另一个字段上的索引也会失效。
    解决方案:可以使用union联合查询;

例如:dept表,loc字段有索引,deptname字段没有索引;
select * from dept where loc = '福建' or deptname = '信息部';
查询位于福建的或者信息部的部门信息,由于deptname没有索引,会导致loc的索引失效,可以使用union联合查询,这样loc字段的索引还是生效的;
select * from dept where loc = '福建' union select * from dept where deptname = '信息部';

第3种情况:

    使用复合索引的时候,没有用到最左侧的字段作为查找条件,索引失效
    备注:什么是复合索引?两个字段,或者更多的字段联合起来添加一个索引,叫做复合索引。
    create index emp_job_sal_index on emp(job,sal);

索引正常:explain select * from emp where job = 'MANAGER';
索引失效:explain select * from emp where sal = 800;

第4种情况:

    在where当中索引列使用了运算(+,-,*,/,!,<> 等),索引失效。
    create index emp_sal_index on emp(sal);

索引正常:explain select * from emp where sal = 800;
索引失效:explain select * from emp where sal+1 = 800;

第5种情况:

    在where当中索引列使用了函数
    ename字段有索引
    explain select * from emp where lower(ename) = 'smith';

第6种情况:

    小表查询或查询的数据量大于表数据量的30%,走全表扫描更快,会不使用索引;

第7种情况:

隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误. 例如表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Oracle,这样会导致索引失效.

错误的例子:select * from test where tu_mdn=13333333333;
正确的例子:select * from test where tu_mdn='13333333333';

第8种情况:

没有查询条件,或表中未建立索引, 或where条件中不包含索引对应列;

第9种情况:

索引本身失效;特别是短时间内,有大量的数据变更,统计信息不准确,导致索引失效;oracle压测经常碰到;需在线重建索引+数据分析;如果仍然不能解决,需DBA介入,进行索引固化;

二.SQL语句执行计划解析,查看SQL的索引使用情况

MySQL的Explain关键字


841ec6ee9a2c4b2181f295a33f1c5530.png

在select语句之前增加explain关键字,可以模拟优化器,分析查询语句或结构的性能瓶颈,返回执行计划的信息,而不是执行这条SQL;执行结果显示如下几列。
注意:如果from中包含子查询,仍会执行该子查询,将结果放入临时表中

id列
select的序号列, 有几个select就有几个id, 并且id的顺序是按select出现的顺序增长的, id越大执行优先级越高, 相同则由上而下执行, null则最后执行
select_type列
select_type列表示对应简单还是复杂的查询.
simple: 简单查询, 语句不包含子查询和union
primary: 复杂查询中最外层的select
subquery: 包含在select中的子查询(不在from字句中)
derived: 包含在from子句中的子查询, Mysql会将结果保存在一个临时表中, 也叫派生表(derive)
union: 在union中的第二个和随后的select

table列
表示这一列的一行正在访问哪一个表;

type列
表示关联类型或访问类型, 即Mysql决定如何查找表中的行, 一般要保证到range以上, 最好到ref
NULL: 这种情况是不需要去表中查询数据, 可以直接从索引中获取
system: const的特例, 整张表中只有一条数据
const: 通过主键或者唯一的键来查询数据, 表中只有一条匹配数据, 只需要查询一次, 速度非常快
eq_ref: primary key 或unique key索引的所有部分被连接使用,最多只会返回一条符合条件的记录。
这可能是在const之外最好的联接类型了,简单的select查询不会出现这种type。
ref: 相比eq_ref不使用唯一索引, 而是使用非唯一索引或唯一索引部分前缀, 索引要和某个值比较, 可能返回多个符合列
range: 范围扫描通常出现在in(), between, <>=等语句中, 使用索引给定范围的行
index: 通过扫描二级索引就可以获取到需要的字段, 不需要再进行回表获取数据
(主键索引在叶子节点会存储所有数据, 而二级索引只存储主键, 所以通常来说所需字段如果能通过二级索引全部获取 到的话会优先从二级索引获取)
这里是因为表中只有id和name属性, 通过idx_name二级索引可以直接获取所有字段
ALL: 扫描全表, 扫描聚簇索引的所有叶子结点.

possible_keys列
这一列显示可能使用哪些索引来查找.
可能出现possible_keys有值,而key显示NULL的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。
如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查where子句看是否可以创造一个适当的索引来提高查询性能,然后用explain查看效果。

key列
这一列显示mysql实际采用哪个索引来优化对该表的访问。如果没有使用索引,则该列是NULL。
如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用force index、ignore index。

key_len列
这一列显示了mysql在索引里使用的字节数, 通过这个值可以算出具体使用了索引中的哪些列。

ref列
这一列显示了key列索引中使用的列或常量, 常见的有const, 字段名

rows列
这一列显示的是mysql预估要读取的行数, 并不是准确值

Extra列
这一列展示的是额外信息, 常见重要值如下
Using index: 通过覆盖索引直接获取数据
Using where: 使用where进行查询, 但是查询列未被索引覆盖
Using index condition: 查询的列不完全被索引覆盖, where条件中是一个前导列范围
Using temporary: mysql需要使用临时表来处理查询, 这种情况通常需要优化
Using filesort: 使用外部排序而不是索引排序, 数据较小时在内存排序, 较大时在磁盘排序
Select tables optimized away: 使用了某些聚合函数

三.索引创建,删除,和重建

1.分析表和索引(analyze不会重建索引)
analyze table tablename compute statistics 等同于
analyze table tablename compute statistics for table for all indexs for all columns
for talbe的统计信息存在于试图 user_tables,all_tables,dba_tables;
for all indexs的统计信息存在于试图 user_indexs,all_indexs,dba_indexs;
for all columns的统计信息存在于试图 user_tab_columns,all_tab_columns,dba_tab_columns;
也可以手工分析索引(analyze index idx_t_compute statistics);

2.创建,删除索引:
create index indexname on tablename;
drop index indexname on tablename;

3.索引重建;
---ORACLE
alter index indexname rebuild; 或alter index indexname rebuild online;
---MYSQL
ALTER INDEX INDEX_NAME REBUILD online;
REPAIR TABLE tbl_name QUICK;
repair table XXX USE_FRM;
优先使用online,实在不行也要在空闲的时候用rebuild,非必要不用drop index/create index;
alter index rebuild online实质上是扫描表而不是扫描现有的索引块来实现索引的重建;
alter index rebuild 只扫描现有的索引块来实现索引的重建。
online时能够在该索引的基表上执行DML,在在对基表操做的同时能够REBUILD INDEX,可是不能执行DDL语句,因此他们的锁机制是不样的。 建立索引时一般会对该表设置一个表级共享(DML)锁,若是设置ONLINE , 若是是非ONLINE方式,一般会对该表设置一个表级共享(DML)锁,那么就对DML语句冲突;若是设置ONLINE ,(会使用临时日志IOT表来记录中间改变的数据),但要使用两倍于传统方法的空间.表会变成行级共享锁,在建立索引或者ALTER完成后,对临时日志表 与基表进行MERGE ;
注意并行处理,DDL,位图索引不能使用ONLINE。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容