按存储方式分
- B-树,B+树
- 哈希索引
Memory引擎默认索引时哈希索引
逻辑区分
- 普通索引
- 主键索引:mysql会自动为主键创建主键索引
- 唯一索引:索引值必须唯一的普通索引
- 全文索引
- 空间索引:MyISAM引起支持,用于地理空间数据类型GEOMETRY,SPATIAL关键字
实际使用划分
- 单例索引
- 多列索引
Innodb的聚集索引和非聚集索引
1.聚集索引
索引键值和数据紧凑存储在一起,索引的逻辑顺序和数据的物理顺序一致。InnoDB中聚集索引叶子节点直接存储的是整条数据。
2. 非聚集索引
索引和数据不在一起,叶子节点保存的是当前索引键值和主键索引键值。
通过非聚集索引查询到主键之后,需要根据主键键值去扫描主键索引的B+树,这种操作叫做回表。
B-树和B+树区别
- m阶B-树节点最多存储m-1个值,B+树可以存储m个值
- B+树的非叶子节点不保存数据,只保存指针同样大小的节点可以保存更多的key,树就更矮IO次数更少。非叶子节点的key最后都会存在于叶子节点里,而且是叶子节点的最大值或最小值。
- B+树因为最终的数据是保存在叶子节点里,所以IO次数是稳定的。
- B+树的叶子节点构成一个有序链表。便于范围查找。
MyISAM引擎的索引
MyISAM引擎不支持事务,不支持外键,不支持行级锁,只支持表级锁。适用于读多写少的场景。记录行数不需要遍历全部行来统计行数。
MyISAM中叶子节点存储的是当前索引值和当前数据文件对应的磁盘地址。主键索引和非主键索引没有区别。
主键索引为什么速度快
因为主键索引不需要回表。只扫描一颗B+树
索引下推
5.6以前,存储引擎遍历索引后把数据返回给Server层,由Server层进行where条件计算。
5.6 开始,部分where条件可以通过索引中的列进行计算时,存储引擎会进行这部分where条件的计算,减少回表次数和返回给Server层的数据量。
多范围读
5.6以后,减少磁盘的随机IO访问,进可能的把随机访问转换为顺序访问。
缓存辅助索引键值,按照主键进行排序,然后按照主键顺序进行访问。
索引合并
5.0之后,表中建立了很多单例索引,查询时用了很多列,mysql能识别单列索引进行扫描,然后把结果合并。
or条件的并集 union ,and的交集。
MySQL如何选择索引
MySQL选择索引是根据开销来选择。
索引判断基数Cardinality
Cardinality:索引中唯一值的估计值,越接近行数,索引的选择性越高。
Cardinality是通过采样来实现计算的,并不是一个精确值,而是一个统计值。并不会实时更新,更新会带来一定开销。
Cardinality更新策略:
- 表中1/M的数据发生变化,1/16
- 数据变化次数超过一定值,少量行频繁更新的情况下。
即发生变化的行数或次数达到一定值。
Cardinality计算方式
InnoDB默认对N个叶子节点进行抽样:
- 获得叶子节点总是A
- 随机获得N个叶子节点,统计每个叶子节点不同记录个数获得总数total
- total ÷ N 得到平均每个叶子节点不同记录个数
- total ÷ N × A
即随机采样N个叶子节点,统计每个叶子节点唯一值个数,然后得到这N个叶子节点的唯一值平均值,然后用这个平均值乘叶子节点总数A。
离散度
即Cardinality与count(*)之比
可以强制使用某个索引force index
建议使用某个索引use index
最左匹配原则
- 模糊查询
like语句,对关键字从左到右进行匹配,如果第一个字符不确定则无法使用 - 多列索引
如a,b两列索引,条件只有b时失效。因为索引是按照先a有序再b有序存储的。
无法使用索引的情况
- 在索引列上使用函数,加减乘除计算
- 字符串不加引号
- 使用 !, <>,not like, not in 反向查询
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/database/288728.html