什么是索引覆盖,索引下推,回表

索引覆盖

索引覆盖是指查询操作可以完全通过索引来完成,而无需访问表中的数据行。当一个查询的所有数据需求都可以通过索引中的数据来满足时,就发生了索引覆盖。这样,数据库就不需要进行额外的数据查找,从而减少了磁盘I/O操作,提高了查询性能1

例如,如果有一个查询语句是:

SELECT name, age FROM users WHERE name = '张三';

如果nameage都包含在一个索引中,那么这个查询就可以通过索引覆盖来完成,不需要回表查询。

索引下推

索引下推是MySQL 5.6及以上版本引入的优化技术。它允许在索引遍历过程中应用查询条件,从而减少访问不必要数据的次数。这意味着数据库引擎会在索引层面过滤数据,而不是在找到所有可能的索引后再在服务器层面进行过滤2

例如,对于查询:

SELECT * FROM users WHERE name LIKE '张%' AND age = 30;

在启用索引下推的情况下,数据库引擎会在遍历索引时直接应用age = 30的条件,而不是在找到所有姓张的记录后再进行过滤。

重要考虑事项

  • 索引覆盖的一个关键要求是查询中的所有列都必须在索引中。如果查询引用了索引中没有的列,那么就无法实现索引覆盖。

  • 索引下推可以显著减少因为回表操作而导致的性能开销。它通过在存储引擎层面进行更多的数据过滤,减少了服务器层面的工作量。

  • 在设计索引时,应该考虑查询模式,以便最大限度地利用索引覆盖和索引下推的优势。

回表

回表查询是数据库操作中的一个术语,特别是在使用索引进行数据检索时。它发生在使用非聚集索引(Secondary Index)进行查询时,索引中只包含了索引列的副本以及指向对应主键的引用。当查询语句中需要返回的列不在索引列上时,即使通过索引定位了相关行,仍然需要回表获取其他列的值。这意味着数据库需要进行两次查找:一次在非聚集索引上定位数据,一次在聚集索引或主键索引上获取完整的数据行。

代码示例

在MySQL中,如果有一个表,其中id是主键,而name有一个普通索引。当执行如下查询时:

SELECT * FROM table WHERE name = 'ls';

由于name列有一个普通索引,查询会首先使用这个索引。但是,普通索引只存储了name值和对应的主键id,并没有sextype等其他信息。因此,数据库需要回到主键索引上,根据id再次查询以获取完整的数据行。

优化方法

为了避免回表查询,可以使用索引覆盖。这意味着查询涉及的所有列都包含在索引中,从而避免了第二次查询。例如,如果查询只涉及idname

SELECT id, name FROM table WHERE name = 'ls';

这样就不会发生回表查询。但如果查询包括sex列:

SELECT id, name, sex FROM table WHERE name = 'ls';

就需要回表查询,因为sex不在name索引中。解决这个问题的方法是创建一个包含namesex的联合索引。

### 索引覆盖 索引覆盖是指当某个查询可以完全由索引来满足,即所需的数据项都存在于索引中而无需访问实际的表记录。这种方式减少了磁盘 I/O 的次数,从而提高了查询的速度[^4]。 对于非聚簇索引而言,如果一个查询只需要获取那些已经在索引中的列,则可以直接从该索引读取这些值而不必再回到原始表格去查找对应的行位置,这便是所谓的“索引覆盖”。这种情况下,不仅节省了大量的随机存取时间,还减轻了CPU 和内存的压力[^5]。 ```sql -- 示例:假设有一个名为 `users` 表,并且存在 (name, age) 联合索引 SELECT name, age FROM users WHERE name = 'John'; ``` 在这个例子中,由于所选字段都在联合索引里,所以 MySQL 可以直接通过这个索引来完成整个查询过程,这就是典型的索引覆盖的应用场景。 ### 索引下推 索引下推是一种优化手段,在执行查询的过程中尽可能早地应用过滤条件来缩小检索范围。具体来说就是在遍历索引树的同时就对符合条件的部分做进一步筛选而不是等到全部匹配后再去做判断[^1]。 这种方法特别适用于多层嵌套子句或复杂表达式的场合;它允许数据库引擎更高效地处理大型数据集并减少不必要的回表操作——也就是不需要每次都返回到原表中寻找完整的记录信息。最终达到降低 IO 成本的目的。 #### 工作机制: - 当 SQL 查询涉及到某些特定类型的谓词(如 AND/OR 运算符连接起来的一系列比较),则可以在索引扫描期间就开始评估它们; - 如果某条记录不符合任何一个早期可计算出来的条件,则立即停止对该路径后续节点的操作; - 结果就是只有一部分真正有可能成为结果集成员的数据会被传递给更高层次来进行最后验证。 ```sql -- 示例:假设有如下查询语句 SELECT * FROM orders WHERE order_date >= '2023-01-01' AND status IN ('shipped', 'delivered'); ``` 这里,即使是在索引扫描过程中遇到不满足日期区间或者状态不在指定集合内的订单也可以提前排除掉,进而加快整个查询流程。 ### 数据库优化建议 为了更好地利用上述两种特性实现高效的数据库性能调优,应该注意以下几点: - 合理规划和构建适合业务逻辑需求的各种单列或多列组合形式的索引结构; - 尽量让经常一起使用的几个属性形成复合型索引以便于共同参与查询定位工作; - 定期审查现有系统里的所有索引定义情况,去除无用甚至有害的设计方案防止造成浪费; - 使用合适的工具和技术监控SQL执行计划的变化趋势及时调整策略适应新的负载模式变化。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涵冰...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值