服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Mysql - MySQL回表查询与索引覆盖的区别

MySQL回表查询与索引覆盖的区别

2023-03-21 14:53李歘歘 Mysql

本文主要介绍了MySQL回表查询与索引覆盖的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

回表查询

InnoDB索引分为两大类,一类是聚集索引(Clustered Index),一类是非聚集索引(Secondary Index)

聚集索引(聚簇索引):叶子节点中存的是整行数据,找到索引也就找到了数据,索引即数据,表中行的物理顺序与键值的逻辑(索引)顺序相同,一个表只能包含一个聚集索引。因为索引(目录)只能按照一种方法进行排序。

非聚集索引(普通索引、非聚簇索引、二级索引):非聚集索引的btree叶子节点中存储的是当行数据的PK(主键)。例如MYISAM通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因。

为什么非主键索引结构叶子结点存储的是主键值?

减少了出现行移动或者数据页分裂时二级索引的维护工作(当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引,一个表只能有一个聚簇索引,其他的都是二级索引,这样只需要修改聚簇索引就可以了,不需要重新构建二级索引)

在使用非聚集索引时,为了取到具体数据,则需要通过PK回到聚集索引里去查询数据。着就叫回表查询。扫描了2次索引树。所以效率相对较低。

索引覆盖

索引覆盖就是解决回表查询的一种方案。见名知意,就是查询的所有列均被所使用的索引列覆盖(可以是单列索引也可以是联合索引,通常是联合索引,单列索引很难覆盖查询的所有列)。

因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了,不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率。

id为聚集索引,name为非聚集索引:

?
1
select name, age from t where name = 'lcc';

就需要回表查询

索引覆盖:

在SQL中只查询name字段。这样name的索引就覆盖到了所有的查询列。

?
1
select name  from t where name = 'lcc';

将name的索引修改为联合索引(name, age ),之后还是执行select name, age from t where name = 'lcc'。这样也覆盖到了所有的查询列。
因为覆盖索引必须要存储索引的列值,而哈希索引、空间索引和全文索引等都不存储索引列值,从而只有使用B-Tree索引的数据可以做覆盖索引。

进行索引覆盖查询时,在explain(执行计划)的Extra列可以看到【Using Index】的信息。

索引覆盖的优点

  • 索引条目通常远小于数据行的大小,因为覆盖索引只需要读取索引,极大地减少了数据的访问量。
  • 索引是按照列值顺序存储的,对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO小很多。
  • 一些存储引擎比如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据的话需要一次系统调用,使用覆盖索引则避免了这一点。
  • 由于InnoDB的聚簇索引,覆盖索引对InnoDB引擎下的数据库表特别有用。因为InnoDB的二级索引在叶子节点中保存了行的主键值,如果二级索引能够覆盖查询,就避免了对主键索引的二次查询。

哪些场景适合使用索引覆盖来优化SQL

  • 当不需要查询整行记录时;
  • 全表count查询优化;
  • Limit分页查询;

哪些情况下不要建索引

  • 表记录太少
  • 经常增删改的表或者字段(如用户余额)
  • Where条件里用不到的字段不创建索引
  • 过滤性不好的不适合建索引(如性别)

索引下推

索引下推优化是 MySQL 5.6 引入的, 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

建立联合索引:

?
1
KEY `username` (`name`,`age`) )

执行:

?
1
select * from user2 where name like 'j%' and age=99;

上面的查询sql符合索引的最左前缀原则,所以将会用到 username 索引

5.5中上面这个 SQL 的执行流程是这样的:

  • 首先 MySQL 的 server 层调用存储引擎获取第一个以 j 开头的 username。
  • 存储引擎找到 username=‘j’ 的第一条记录后,在 B+Tree 的叶子结点中保存着主键 id,此时通过回表操作,去主键索引中找到该条记录的完整数据,并返回给 server 层。
  • server 层拿到数据之后,判断该条记录的 age 是否为 99,如果 age=99,就把该条记录返回给客户端,如果 age!=99,那就就丢弃该记录。

 5.6中上面这个 SQL 的执行流程是这样的:

  • MySQL 的 server 层首先调用存储引擎定位到第一个以 j 开头的 username。
  • 找到记录后,存储引擎并不急着回表,而是继续判断这条记录的 age 是否等于 99,如果 age=99,再去回表,如果 age 不等于 99,就不去回表了,直接继续读取下一条记录。

 到此这篇关于MySQL回表查询与索引覆盖的区别的文章就介绍到这了,更多相关MySQL回表查询与索引覆盖内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_42410605/article/details/122517749

延伸 · 阅读

精彩推荐
  • MysqlMySQL下海量数据的迁移步骤分享

    MySQL下海量数据的迁移步骤分享

    一般mysql小数据的情况可以通过直接复制目录,或者通过帝国备份工具,如果是海量数据(6亿)该怎么处理呢,下面看下别人是怎么处理的参考一下 ...

    MYSQL教程网5232020-01-12
  • MysqlMySQL索引总结(Index Type)

    MySQL索引总结(Index Type)

    本文主要介绍了MySQL索引总结(Index Type),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编...

    糖小豆子4352023-02-06
  • MysqlMySQL 升级方法指南大全

    MySQL 升级方法指南大全

    通常,从一个发布版本升级到另一个版本时,我们建议按照顺序来升级版本。例如,想要升级 MySQL 3.23 时,先升级到 MySQL 4.0,而不是直接升级到 MySQL 4.1 或...

    mysql技术网3052019-10-20
  • MysqlMySQL 修改数据库名称的一个新奇方法

    MySQL 修改数据库名称的一个新奇方法

    这篇文章主要介绍了MySQL 修改数据库名称的一个新奇方法,MySQL 修改数据库名的一个变通方法,需要的朋友可以参考下 ...

    吴炳锡4772020-04-13
  • Mysqlmysql查找删除表中重复数据方法总结

    mysql查找删除表中重复数据方法总结

    在本篇文章中小编给大家整理了关于mysql查找删除表中重复数据方法和相关知识点,需要的朋友们参考下。 ...

    MYSQL教程网4212020-09-23
  • MysqlMySQL查看和修改时区的方法

    MySQL查看和修改时区的方法

    这篇文章主要给大家介绍了关于MySQL查看和修改时区的方法,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的...

    CroWall22132020-11-28
  • Mysql从其他电脑访问本机的Mysql的设置方法

    从其他电脑访问本机的Mysql的设置方法

    如果需要让特定的用户从给定域(例如mydomain.com)的所有计算机上访问 MySQL 服务器,你可以执行在账户名的 host 部分使用了通配符“%” 的 GRANT 语句 ...

    mysql教程网5882019-10-24
  • MysqlNavicat查询结果不能修改的原因及解决方法

    Navicat查询结果不能修改的原因及解决方法

    下面小编就为大家带来一篇Navicat查询结果不能修改的原因及解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看...

    数据库之家15552020-07-05