mysql 覆盖索引 聚簇索引_聚簇索引和覆盖索引

在上一文《MySQL索引原理和高性能索引策略》中,我们分析了高性能索引的几个策略,今天我们了解一下聚簇索引和覆盖索引,它们也是高性能索引策略之一。

1.聚簇索引

聚簇索引的数据分布

聚簇索引并不是一个单独的索引类型,而是一种数据存储方式。在InnoDB中,聚簇索引实际上在同一个结构中保存了B-Tree索引和数据行。节点页只包含索引列,叶子也才包含行的全部数据。由于聚簇索引数据行和相邻的键值紧凑地存储在一起,也就是说,无法把数据行和索引分开存储,因此,由于数据行只有一份,聚簇索引在一个表只有一个。

InnoDB通过主键聚集索引;如果没有定义主键,则会选择一个唯一的非空索引替代;如果还是没有这样的索引,则会隐式定义一个主键来作为聚簇索引。InnoDB只聚集同一个页面中的记录,包含相邻键值的页面可能会相距甚远。

为什么要把数据进行聚集?比如实现一个电子邮箱系统,可以根据用户ID做数据聚集,数据聚集后只需要从磁盘读取少数的数据页就能够读到用户的全部邮件。假设不使用聚簇索引,那么读取用户的每封邮件很可能都会导致一次磁盘IO。

相对非聚簇索引,使用聚簇索引可以减少一次回表,加快数据访问。

页分裂(page split)问题

聚簇索引表数据的插入是顺序插入,基于聚簇索引的表在插入新行,或者主键被更新时,可能面临页分裂问题。当行的主键值要求插入行在一个已满的页中时,存储引擎会将页分裂成两个页面来容纳这一行,页分裂会导致表占用更多的磁盘空间。

总之,相对二级索引,使用聚簇索引可以减少一次回表查询,通过把相关数据聚集、减少磁盘IO次数来保证查询的高效。

2.覆盖索引

通常大家都会依据查询条件WHERE来创建合适的索引,这样做没什么问题,但如果懂得设计索引时充分考虑到整个查询,包含需要返回的数据集字段,则又更高明一些。覆盖索引指的就是索引的叶子结点已经包含了需要查询的数据,这样就没必要根据主键进行二次回表查询,显然覆盖索引效率更高一些。

覆盖索引是非常实用的工具,能够极大地提升性能:索引条目通常远小于数据行大小,如果只需要读取索引,那MySQL能够极大的减少数据访问量。如果没使用覆盖索引,响应时间可能大部分花在数据拷贝上了。

InnoDB可以减少根据主键的二次回表查询。

我们可以通过EXPLAIN来分析查询语句是不是覆盖索引。还是用sakila这个DB来作为我们的测试数据库。

explain select store_id,film_id from inventory;

id|select_type|table |partitions|type |possible_keys|key |key_len|ref|rows|filtered|Extra |

--|-----------|---------|----------|-----|-------------|--------------------|-------|---|----|--------|-----------| 1|SIMPLE |inventory| |index| |idx_store_id_film_id|3 | |4581| 100.0|Using index|

看最后一列Extra,Using index说明使用覆盖索引。

这里很容易把Extra列的Using index和type列的index搞混淆,这两者完全不同,type用来说明MySQL查找行的方式。

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值