MySQL 聚簇索引 和覆盖索引
一.聚簇索引
1.聚簇索引并不是一种单独所以,而是一种数据储存方式。
InnoDB 的聚簇索引实际上在同一结构中保存了B-Tree 索引和数据行。
2.当表有聚簇索引时,它的数据行实际上存放在索引的叶子页中。“聚簇”表示数据行和相邻的键值紧凑的储存在一起。
3.对应InnoDB 来说如果表没有定义主键,会选择一个唯一的非空索引代替。如果没有这样的索引InnoDB 会隐式定义一个主键来作为聚簇索引。InnoDB 只聚集在同一页面中的记录。
4.聚簇索引的优势:
(1)可以把相关数据保存在一起。 (2)数据访问更快。数据和索引保存在同一个 B-Tree 。 (3)使用覆盖索引扫描的查询可以直接使用页节点的主键值
5.聚簇索引的缺点:
(1)聚簇索引最大的提高了I/O密集型应用的性能,但如果数据全部都放到内存中,则数据的顺序就没有那么重要了,聚簇索引也就没什么优势了。
(2)插入速度严重依赖插入顺序。按照主键插入的方式是InnoDB 速度最快的方式,但如果不是按照主键顺序加载数据,那么在加载后最好使用OPTIMIZE TABLE 命令重新组织一2下表
(3)更新聚簇索引列的代价很高。因为会强制InnoDB 将每个被更新的行移动到新的位置
6.二级索引
主键索引的叶子节点存的是整行数据,在InnoDB 里,主键索引也被称为聚簇索引
非主键索引的叶子节点内容是主键的值。在InnoDB 里。非主键索引也被称为二级索引。
如:select* from order where user_id=3; user_id是普通索引。则会先搜索user_id 的索引树,得到id=5,再到id 索引树搜索一次,这个过程就是 “回表”。
也就是说非主键索引需要查询2次
二.覆盖索引
1.mysql 可以使用索引直接来获取列的数据,这样就可以不再需要读取数据行。
如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回表查询呢?如果一个索引包含(覆盖)所有要查询的字段的值,那么就称为“覆盖索引”
2.覆盖索引可以提高查询的性能,不需要会表,好处是:
(1)索引条目通常小于数据行,如果只需读取索引,那么mysql 就会减少访问量 (2)索引是按照列值顺序存储的,索引I/O 密集型的范围查询会比随机从磁盘读取每一行数据的I/O 要少得多 (3)一些存储引擎如MyISAM 在内存只缓存索引,数据则依赖操作系统来缓存,因此要访问数据需要一次系统调用,这可能导致严重的性能问题,尤其是那些系统调用占了数据访问中最大开销的场景 (4)InnoDB 的聚簇索引,覆盖索引对InnoDB 表的特别有用。InnoDB 的二级索引在叶子节点保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询。
3
select id from order where user_id between 1 and 3
这时候只需要查ID 的值,而ID 已经在user_id 索引树上,因此可以直接提供查询结果,不需要回表。
select * from order where user_id between 1 and 3
一旦用了select *,就会有其他列需要读取,这时在读完index以后还需要去读data才会返回结果。
这两种处理方式性能差异非常大,特别是返回行数比较多,并且读数据需要 I/O 的时候,可能会有几十上百倍的差异。因此建议根据需要用select *
ps:文章参考《高性能mysql》一书