慢查询日志,顾名思义也就是查询慢的日志(记录数据库事件, 协助用户分析和解决问题),是指mysql记录所有执行超过long_query_time参数设定的时间阀值得SQL语句得日志。该日志可以为SQL语句的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志的功能,首先要开启。
MySQL官方的定义为:索引是帮助MySQL获取数据的数据结构。可以看出索引是数据结构。
数据结构中比B树的B+树存在更快的查找树,MySQL为什么没有采用呢?因为索引文件是储存在磁盘中的,索引太大那么磁盘IO无法一次读入进,二叉查找树虽然快,但是比较"高",需要读很多次,这样磁盘IO的速度大大高于二叉查找树快的速度。所以采用B树,这种树设计的"矮",IO次数最少。也就加快了数据库的速度。
B树和B+树的区别可以参考:
https://www.cnblogs.com/windy-xmwh/p/9298509.html
B树
B+树
B树和B+树最大区别在于B树每个节点储存key和value,但是B+树每个节点只存key,只有叶子节点存的是整个树的value,然后用指针串成链表,B+树的优势在于,索引节点数据紧凑,并且遍历整个树快,只需要从叶子节点遍历即可,但是B树也有其优点,就是如果查找的数离根节点很近,那么就会十分快。
索引并不是越多越好,第一,需要维护这个索引表,表太多增大储存压力。第二,每次的更新数据都是需要重新维护索引表,会带来成本。所以以下情况下的列,适合建立索引,但一般一张表不要超过5个索引。
联合索引又叫复合索引,即一个覆盖表中两列或者以上的索引,重点是左匹配问题,例如联合索引为col1,col2,col3, SELECT * FROM table WHERE col1=? AND col2=? AND col3=? 限定条件必须符合左匹配此联合索引才可以起作用。比如col1,col2或者col1,col2,col3 但是col2,col3则不行。
由于联合索引的数据底层,是最左边的col1列作为索引,其余列都分布在叶子节点中。
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句是表结构的性能瓶颈。
去清楚以下内容,方便对数据的执行优化
id:select子句的操作顺序
select_type:主要用于查看区别此次查询的类型,例如是:普通查询、联合查询、子查询等
type:显示的是访问类型,结果也不同
性能的好坏顺序(优化最好到range)
system>const>eq_ref>ref>range>index>ALL
possible_key和key:一个代表可能使用的索引,一个代表当前使用的索引
key_len:本次所选择的索引长度有多少字节,通常我们可借此判断联合索引有多少列被选择了。
rows:根据索引的情况估算出执行本次SQL语句要查询的行数。
Extra:包含了不能在其它列显示,但十分重要的额外信息。
(1) 联合索引,尽量全值匹配。也就是where条件最好把这几个列都添加上。
(2)联合索引,必须符合左匹配原则。也就是限定查询条件必须从最左边的列开始。否则索引回失效,例如:
可以执行,但是把name删除后,索引无法生效。如果去掉age,只有name是生效的,pos无效。因为在B树的叶子节点中,是按列名的顺序进行排列的,少了中间列,则无法查找到最后一列的数据。
左匹配只是不能缺少,交换位置是可以的。
(3)不要在索引列上做任何的操作(计算,函数,类型转换),会造成索引的失效
(4)尽量使用覆盖查询(索引列和查询列一致), 少使用select
(5)在使用不等于(< > !=) 的范围查找时,索引会失效,在这种情况下使用覆盖索引会使索引重新生效
(6)注意null和not对索引是有影响的
如果列设置为not null,那么你去搜索null,sql语句是不会生效的
如果设置为not null的列,你去查找not null,等同于范围查询,除了在覆盖索引的情况下,其余情况都会导致索引失效。
(7).Like查询可能导致全表扫描,从而引发全表扫描,%写在前面会导致索引失效,在后不会
(8)字符串类型的数据,不加引号,会导致索引失效
(9)OR改UNION查询效率高
MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。与OR在查询上效果相同,但索引不会失效。
or也属于范围查询,会带来索引的失效。
(10)如果复制表,采用Insert方法效率太慢,将上一张表的数据利用OTFILE语句输出为文件,然后用LOAD语句,加载到新的表中,复制速度比纯INSERT快20倍左右
总结:在索引失效的各种情况下,使用覆盖索引必然使可以生效的,但是尽量不去这么做,因为索引覆盖不是万能的,可能不符合业务需求。正确的方法是按照策略的错误点去改正。
另外在范围查询的非覆盖查询的条件下,索引都是会失效的