索引细讲

索引原理

   索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据

索引的优缺点

优势

可以快速检索,减少I/O次数,加快检索速度

根据索引分组和排序,可以加快分组和排序


劣势

索引本身也是表,因此会占用存储空间,一般来说,索引表占用的空间的数据表的1.5倍;

索引表的维护和创建需要时间成本,这个成本随着数据量增大而增大;

构建索引会降低数据表的修改操作(删除,添加,修改)的效率,因为在修改数据表的同时还需要修改索引表;

索引的分类

主键索引:不允许重复,不允许空值;
唯一索引:用来建立索引的列的值必须是唯一的,允许空值;
普通索引:用表中的普通列构建的索引,没有任何限制;
全文索引:用大文本对象的列构建的索引;
组合索引:用多个列组合构建的索引,这多个列中的值不允许有空值。

索引的使用策略

(1)主键自动建立唯一索引;
(2)经常作为查询条件在WHERE或者ORDER BY 语句中出现的列要建立索引;
(3)作为排序的列要建立索引;
(4)查询中与其他表关联的字段,外键关系建立索引
(5)用于聚合函数的列可以建立索引,例如使用了max(column_1)或者count(column_1)时的column_1就需要建立索引

 

索引失效的情况

(1)在组合索引中不能有列的值为NULL,如果有,那么这一列对组合索引就是无效的。


(2)LIKE操作中,'%aaa%'不会使用索引,也就是索引会失效,但是‘aaa%’可以使用索引(分情况)。

-- 走了索引,index,因为表里面只有两个字段,主键和索引字段
explain select * from departments where dept_name like  '%Develop%';
-- 没走索引,ALL,表里面除了主键和索引字段外,还有其他字段
explain select * from dept_manager where dept_no like '%d001%';


(3)在索引的列上使用表达式或者函数会使索引失效,例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。其它通配符同样,也就是说,在查询条件中使用正则表达式时,只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。


(4)在查询条件中使用不等于,包括<符号、>符号和!=会导致索引失效。特别的是如果对主键索引使用!=则不会使索引失效,如果对主键索引或者整数类型的索引使用<符号或者>符号不会使索引失效


(5)在查询条件中使用IS NULL或者IS NOT NULL会导致索引失效。


(6)字符串不加单引号会导致索引失效。更准确的说是类型不一致会导致失效,比如字段email是字符串类型的,使用WHERE email=99999 则会导致失败,应该改为WHERE email='99999'。


(7)在查询条件中使用OR连接多个条件会导致索引失效,除非OR链接的每个条件都加上索引,这时应该改为两次查询,然后用UNION ALL连接起来。


(8)尽量不要包括多列排序,如果一定要,最好为这队列构建组合索引;

Explain介绍

使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。

1 )id:相同,执行顺序由上至下;不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行

2)select_type 表示select的类型;SIMPLE 代表简单表,不用表连接或子查询,PRIMRY 主查询(外层查询),UNION UNION中的第二个或者后面的查询语句,SUBQUERY 子查询中的第一个SELECT;

3)table输出结果集的表;

4)type:访问类型 下面几种:
下面的值,从左到右,性能由最差到最好
ALL,index,range,ref,eq_ref,const,system,NULL
ALL:全表扫描
index:索引全扫描
range: 索引的范围扫描 用于<,<=,>,>=,between等操作
ref:使用非唯一索引扫描或者唯一索引的前缀扫描;
eq_ref:使用唯一索引扫描,多表链接中使用primary key或unique key作为关联条件;
const/system:单表中只有一个匹配行,查询速度快,根据主键或唯一索引进行的查询;
NULL:mysql不用访问表或者索引,直接能够得到结果;

5)possible_keys:查询中可能用到的索引;

6)key查询中实际用到的索引;

7)key_len 索引的长度;

8)ref:显示索引的哪一列被使用了,如果有可能是一个常数,哪些列或常量被用于查询索引列上的值
9)rows 扫描的行数;
10)Extra

Using filesort:说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作称为“文件排序”。
Using temporary:使用了用临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。
Using index:表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错。如果同时出现using where,表明索引被用来执行索引键值的查找;如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。
Using join buffer:表明使用了连接缓存,比如说在查询的时候,多表join的次数

非常多,那么将配置文件中的缓冲区的join buffer调大一些。


explain总结:

EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
部分统计信息是估算的,并非精确值
在5.6以及以后的版本中,除过select,其他比如insert,update和delete均可以使用explain查看执行计划

原文地址:https://www.cnblogs.com/crystal1126/p/14764442.html