为什么索引没被采用

简单来说,数据库没用你的索引有两种情况:

  1. 你的索引不合适
  2. 查询优化器认为不使用索引更快

想要创建合适的索引,可以看上一篇文章《理解数据库如何使用索引》

接下来我们来探讨一下在创建了合适的索引的情况下,为什么查询优化器会认为不使用索引更快。

数据库如何读取数据

在讨论之前,我们先来了解一下数据库是怎么读取数据的。数据库读取数据的方式有以下两种:

  • 使用索引:通过索引获取符合条件的行在文件上的位置,然后从文件中依次读取。因为这些行在文件的不同位置,所以每读取一行就需要跳转到文件的不同位置。这种读取方式称为随机读取。
  • 不适用索引:从表的文件中顺序读取所有行,筛选出符合条件的行。这种读取方式称为顺序读取。

顺序读取的速度要比随机读取快得多。特别是在机械硬盘上,硬盘移动磁头的速度非常慢。虽然现在 SSD 硬盘的随机读取速度已经很快了,但顺序读取速度仍然要比随机读取快。

为什么不使用索引更快

读取的行数较多

假设我们有一张表,这张表有 100 行数据。硬盘随机读取一行数据需要的时间为 4,硬盘顺序读取一行数据需要的时间为 1。以下是使用索引和不使用索引的情况下,数据库读取 n 行数据所需的时间:

  • 使用索引:4 * n
  • 不使用索引:1 * 100

不难看出,当 n 小于 25 时,使用索引更快;当 n 大于 25 时,不使用索引更快。即当查询的行数占表的比例较大时,不使用索引会更快。这个比例的大小取决于硬盘的随机读取速度和顺序读取速度,并不是一个固定的值,我们通常认为这个比例在 10% 到 30% 之间。

💡 如果你使用的是速度较快的 SSD 硬盘,可以给数据库设置一个较低的随机读取开销,让查询优化器更倾向于使用索引。在 PostgreSQL 中,可以将 random_page_cost 设置为 1.1。

统计信息过时

查询优化器是怎么知道符合条件的行数占表的比例的呢?数据库会统计表的一些信息,包括表的行数、索引列的值的分布等。优化器会根据这些信息估算使用索引和不使用索引的开销。如果统计信息过时了,也会导致优化器做出错误的决策。

比如符合条件的行数实际占比 5%,但统计信息显示占比 50%,优化器就会错误的认为不使用索引更快。

💡 建议在进行大量更改之后使用 ANALYZE TABLE 重新计算统计数据,或者定时重新计算。

相关推荐
杨云龙UP12 分钟前
生产环境MySQL多实例XtraBackup全量备份与rsync异地自动传输实践
linux·运维·数据库·mysql·xtrabackup·主从复制·备份恢复
熊文豪21 分钟前
SQLServer数据迁移之后,那张报表还能不能秒出
数据库·sqlserver·电科金仓
凤山老林32 分钟前
高保真集成测试:Spring Boot 结合 Testcontainers 的工程落地
spring boot·后端·集成测试
JosieBook33 分钟前
【数据库】把数据优势转化为决策优势:TimechoAI时序大模型使用解析
数据库
步行cgn34 分钟前
MyBatis <trim> 标签完全解析:动态 SQL 的终极武器
后端
XPoet39 分钟前
AI 编程工程化:实战——从 0 到 1 搭建 AI 编程工作流
前端·后端·ai编程
掘金者阿豪39 分钟前
向量数据库不是终点,企业AI真正需要的是融合数据库
后端
程序员cxuan44 分钟前
OpenAI Linux 版来了!
人工智能·后端·程序员
大黄评测1 小时前
Angular 表单:响应式表单高级用法,Typed Forms 类型化表单实战
后端
大勇前进1 小时前
Angular 变更检测深度讲解:OnPush 策略什么时候用、踩过哪些坑
后端