索引优化
一、索引类型
1. B-Tree 索引
特点
- a).B-Tree 索引能够加快数的查询速度
- b).B-Tree 索引以B+树的结构存储数据:
- 每一个叶子节点到根部的距离相同
- InnoDB引擎指针指向被索引的数据而不是主键,MyISAM引擎指针指向物理地址
- 顺序存储,适合进行范围查找
何时命中
- 全值匹配的查询
order_no = ‘20190825102500001’ - 匹配最左前缀的查询
– 创建如下索引
KEYindex
(order_no
,order_date
) USING BTREE
当 where order_no = ‘20190825102500001’ 时依然可以命中索引
当 where order_date = ‘20190805’ 时无法命中索引 - 匹配列前缀查询
当 where order_no like ‘20190825%’ 时可命中
当 where order_no like ‘%82500001’ 时不可命中 - 匹配范围值的查询
当 where order_no > ‘20190825102500001’ 时可命中 - 精确匹配左前列并范围匹配另外一列
– 创建如下索引
KEYindex
(order_no
,order_date
) USING BTREE
当 where order_no = ‘20190825102500001’ and order_date > ‘20190825’ 时依然可以命中索引 - 只访问索引的查询
使用限制
- 如果不是按照索引最左列开始查找,则无法使用索引
- 使用索引时不能跳过索引中的列
– 创建如下索引
KEYindex
(order_date
,‘user_name’,‘mobile’) USING BTREE
当 where order_date = ‘20190825’ and mobile = ‘15900001111’ 时无法命中索引,即不能跳过 user_name 列 - not in 和 <> 操作无法使用索引
- 如果查询中有某个索引列的范围查询,则其右边所有列都无法使用索引
2. Hash 索引
特点
- Hash 索引是基于 Hash 表来实现的,只有查询条件精确匹配 Hash 索引中所有列时,才能够命中索引
- 对于 Hash 索引中所有列,存储引擎都会为每一行计算一个 Hash 码, Hash 索引中存储的就是 Hash 码,Hash 码通常会比较小,存在 Hash 冲突
- Hash 索引中存储 键、值、Hash码、对应行的指针
何时命中
- 仅当查询条件全部匹配是才命中,因此不适合范围查找,只适合等值查询
使用限制
- Hash 索引必须进行二次查找,因为无论是 Memory 引擎还是 InnoDB 引擎 对频繁访问的行都存储在内存当中了,而内存的访问速度很快,所以基本可以忽略
- Hash 索引无法用于排序
- Hash 索引不支持部分索引查找也不支持范围查询
- 存在 Hash 冲突,适合在重复概率小的列建立 Hash 索引,比如【证件号码】,而类似【性别】就不适合
3. 索引好处
- 索引大大减少了存储引擎需要扫描的数据量
- 索引可以帮助我们进行排序以避免使用临时表,避免IO消耗以提高处理能力
- 索引可以把随机 IO 变为顺序 IO
4. 索引不是越多越好
- 索引会增加写操作的成本:insert、update、delete 时需要维护索引,InnoDB 引入了插入缓存解决该问题
- 太多的索引会增加传优化器的选择时间:MySQL 查询优化器会根据索引的统计信息和查询条件来选择合适的索引。而同一个查询有很多的索引可以使用时,会增加查询优化器分析的时间,从而影响查询效率