当前位置: 首页 > 科技观察

MySQL的覆盖索引和回表

时间:2023-03-13 15:05:46 科技观察

索引使用的存储引擎:MySQL5.7InnoDB聚簇索引*如果表有主键,则主键为聚簇索引*如果表没有主键,则为聚簇索引默认情况下将第一个ANOTNULL,唯一的(UNIQUE)列用作聚集索引*以上均不会默认创建隐藏的row_id作为聚集索引。InnoDB的聚簇索引的叶子节点存放行记录(其实就是页结构,一个页包含多行数据),InnoDB必须至少有一个聚簇索引。可以看出使用聚簇索引查询会很快,因为可以直接定位到行记录。普通索引普通索引也叫二级索引,是聚集索引以外的索引,即非聚集索引。InnoDB的普通索引叶子节点存放的是主键(聚集索引)的值,而MyISAM的普通索引存放的是记录指针。示例创建表mysql>createtableuser(->idint(10)auto_increment,->namevarchar(30),->agetinyint(4),->primarykey(id),->indexidx_age(age)->)engine=innodbcharset=utf8mb4;id字段为聚簇索引,age字段为普通索引(二级索引)填充数据inserttintouser(name,age)values('张三',30);insertintouser(name,age)values('李Si',20);insertintouser(name,age)values('王武',40);insertintouser(name,age)values('刘八',10);mysql>select*fromuser;+----+--------+------+|id|name|age|+----+------+------+|1|张三|30||2|李四|20||3|王五|40||4|刘八|10|+----+--------+------+索引存储结构id为主键,所以它是一个聚集索引,它的叶子节点存储对应行记录的数据。普通索引(secondaryIndex)的值如果查询条件是主键(聚簇索引),只需要扫描一次B+树,通过聚簇索引定位到要查找的行记录数据。例如:select*fromuserwhereid=1;聚簇索引查找过程如果查询条件是普通索引(非聚簇索引),需要对B+树进行两次扫描,第一次扫描通过普通索引定位到聚簇索引的值,第二次扫描定位到通过聚集索引的值来查找行记录数据。例如:select*fromuserwhereage=30;1、先通过普通索引age=30定位到主键值id=12,再通过聚簇索引id=1定位到行记录数据。普通索引搜索过程的第一步是普通索引搜索过程的第二步是返回表查询。先通过普通索引的值定位聚簇索引值,再通过聚簇索引的值定位行记录数据。它需要对索引B+树进行两次扫描,其性能低于对索引树进行一次扫描。.索引覆盖只需要在一棵索引树上获取SQL需要的所有列数据,不需要回表,速度更快。例如:selectid,agefromuserwhereage=10;实现覆盖索引的常用方法是:将要查询的字段构建到联合索引中。1.例如实现:selectid,agefromuserwhereage=10;解释分析:因为age是一个普通的索引,当使用age索引时,扫描一次B+树就可以查询到对应的结果,从而实现了覆盖索引2,实现方式:selectid,age,namefromuserwhereage=10;解释分析:age是一个普通的索引,但是name列不在索引树上,所以通过age索引查询完id和age的值后,需要返回表再查询name的值。此时Extra列为NULL,表示已经执行回表查询。为了实现索引覆盖,需要构建复合索引idx_age_name(age,name)dropindexidx_ageonuser;createindexidx_age_nameonuser(`age`,`name`);解释分析:此时age和name字段就是复合索引idx_age_name。查询的字段id、age、name的值都在刚才的索引树上。复合索引B+树只需要扫描一次。这是为了实现索引覆盖。此时Extra字段为Usingindex,表示使用索引覆盖。哪些场景适合使用索引覆盖优化SQL全表计数查询优化mysql>createtableuser(->idint(10)auto_increment,->namevarchar(30),->agetinyint(4),->primarykey(id),->)引擎=innodbcharset=utf8mb4;例如:selectcount(age)fromuser;使用索引覆盖优化:createagefieldindexcreateindexidx_ageonuser(age);列查询回表优化上一篇文章中描述的例子例如:selectid,age,namefromuserwhereage=10使用索引覆盖:构建复合索引idx_age_name(age,name)分页查询例如:按年龄限制100,2从用户订单中选择id、年龄、姓名;因为name字段不是索引,所以分页查询需要返回表查询。此时Extra使用filesort对文件进行排序,查询性能较低。使用索引覆盖:构建复合索引idx_age_name(age,name)