MySQL的索引数据结构、索引优化及使用原则

一、 B+Tree 相比于其他索引数据结构(如 B-Tree、二叉树,以及 Hash 表)的优势;

二、掌握实际工作中常用的建立高效索引的技巧(如前缀索引、建立覆盖索引等)。

三、索引使用原则

一、MySQL从数据结构的角度来看, MySQL 常见索引有 B+Tree 索引、HASH 索引、Full-Text 索引。 MySQL 常见的存储引擎 InnoDB、MyISAM 和 Memory 。
在实际应用中,InnoDB 是 MySQL 建表时默认的存储引擎,B+Tree 索引类型也是 MySQL 存储引擎采用最多的索引类型。
在创建表时,InnoDB 存储引擎默认使用表的主键作为主键索引,该主键索引就是聚簇索引(Clustered Index),创建的主键索引默认使用的是 B+Tree 索引。

B+Tree 相比于其他常见索引结构,如 B 树、二叉树或 Hash 索引结构的优势在哪儿?
1、B+Tree 相对于 B 树 索引结构的优势

B+Tree 只在叶子节点存储数据,而 B 树 的非叶子节点也要存储数据,所以 B+Tree 的单个节点的数据量更小,在相同的磁盘 I/O 次数下,就能查询更多的节点。

另外,B+Tree 叶子节点采用的是单链表连接,适合 MySQL 中常见的基于范围的顺序查找,而 B 树无法做到这一点。

2、B+Tree 相对于二叉树索引结构的优势
对于有 N 个叶子节点的 B+Tree,其搜索复杂度为O(logdN),其中 d 表示节点允许的最大子节点个数为 d 个。在实际的应用当中, d 值是大于100的,这样就保证了,即使数据达到千万级别时,B+Tree 的高度依然维持在 3-4 层左右,也就是说一次数据查询操作只需要做 3~4 次的磁盘 I/O 操作就能查询到目标数据(这里的查询参考上面 B+Tree 的聚簇索引的查询过程)。

而二叉树的每个父节点的儿子节点个数只能是 2 个,意味着其搜索复杂度为 O(logN),这已经比 B+Tree 高出不少,因此二叉树检索到目标数据所经历的磁盘 I/O 次数要更多。

B+Tree 相对于 Hash 表存储结构的优势

范围查询是 MySQL 中常见的场景,但是 Hash 表不适合做范围查询,它更适合做等值的查询,这也是 B+Tree 索引要比 Hash 表索引有着更广泛的适用场景的原因。

二、常见优化索引的方法
1、前缀索引优化

前缀索引就是用某个字段中,字符串的前几个字符建立索引,比如我们可以在订单表上对商品名称字段的前 5 个字符建立索引。使用前缀索引是为了减小索引字段大小,可以增加一个索引页中存储的索引值,有效提高索引的查询速度。在一些大字符串的字段作为索引时,使用前缀索引可以帮助我们减小索引项的大小。

但是,前缀索引有一定的局限性,例如 order by 就无法使用前缀索引,无法把前缀索引用作覆盖索引。

2、覆盖索引优化

覆盖索引是指 SQL 中 query 的所有字段,在索引 B+tree 的叶子节点上都能找得到的那些索引,从辅助索引中查询得到记录,而不需要通过聚簇索引查询获得。假设我们只需要查询商品的名称、价格,有什么方式可以避免回表呢?

我们可以建立一个组合索引,即商品ID、名称、价格作为一个组合索引。如果索引中存在这些数据,查询将不会再次检索主键索引,从而避免回表。所以,使用覆盖索引的好处很明显,即不需要查询出包含整行记录的所有信息,也就减少了大量的 I/O 操作。

3、联合索引

联合索引时,存在最左匹配原则,也就是按照最左优先的方式进行索引的匹配。比如联合索引 (userpin, username),如果查询条件是 WHERE userpin=1 AND username=2,就可以匹配上联合索引;或者查询条件是 WHERE userpin=1,也能匹配上联合索引,但是如果查询条件是 WHERE username=2,就无法匹配上联合索引。

另外,建立联合索引时的字段顺序,对索引效率也有很大影响。越靠前的字段被用于索引过滤的概率越高,实际开发工作中建立联合索引时,要把区分度大的字段排在前面,这样区分度大的字段越有可能被更多的 SQL 使用到。

区分度就是某个字段 column 不同值的个数除以表的总行数,比如性别的区分度就很小,不适合建立索引或不适合排在联合索引列的靠前的位置,而 uuid 这类字段就比较适合做索引或排在联合索引列的靠前的位置。

三、索引的使用原则

1、什么时候适用索引:
字段有唯一性限制的时候,比如商品编码
经常用户WHERE查询条件的字段
经常用户GROUP BY 和ORDER BY的字段

2、什么时候不需要创建索引:
WHERE条件,GROUP BY ,ORDER BY里用不到的字段
字段中存在大量重复数据,不需要创建索引
表数据太少的时候,不需要创建索引
经常更新的字段不用创建索引,避免索引的维护成本高

3、什么情况下索引失效:
如果索引进行了表达式计算,则会失效
如果索引使用了函数,则会失效
当使用LIKE进行模糊查询的时候,后面不能是%
使用联合索引的时候需要注意最左原则
为了更好的利用索引,索引列要设置为NOT NULL约束

猜你喜欢

转载自blog.csdn.net/qq_30353203/article/details/113411434