Skip to content

你可能忽略的索引细节

索引不是“加上就会更快”的通用优化开关,它本质上是额外维护的一份有序数据结构:查询受益,写入和存储付费。

原文链接

我的结论

  • 建索引之前先确认代价:读会更快,但每次写入也要同步维护索引,而且索引本身占空间
  • 复合索引、函数索引能不能命中取决于“顺序和表达式是否匹配”,不是只要字段出现过就行
  • 真正值得优先关注的是 EXPLAIN、partial index 和 covering index,它们比“多建几个索引试试”更接近有效优化

关键信息

文章把几个常见误区拆得很清楚。

第一,索引之所以能避免 full table scan,本质上依赖的是类似 binary search 的有序结构,所以它不是“免费加速”,而是一笔用空间和写入成本换读取性能的交易。

第二,复合索引不是字段集合,而是有顺序的数据结构。它会先按第一个字段排序,再在组内按第二个字段排序,所以查询条件和排序方式如果不符合这个前缀顺序,索引就可能帮不上忙。

第三,函数会改变索引匹配条件。索引建在 name 上,并不等于 lower(name) 也能命中;如果查询里用了表达式,就要考虑 functional index。

第四,索引的设计应该跟查询选择性一起考虑。像 “legendary = true” 这种只覆盖少量记录的条件,更适合 partial index;而如果查询所需列已经都在索引里,就能用 covering index,避免回表再取其他列。

摘录

Reads get faster, writes get slower.

indexes are real data structures and we must store them.

Composite indexes care about order

The index is on name, not lower(name).

Now the index has just 80 entries instead of 1000.

Everything the query needs is already in the index.

我的补充

  • 这篇文章最值得保留的不是某个数据库特性,而是一个检查顺序:先看查询模式,再看选择性,再用 EXPLAIN 验证
  • 很多“索引没生效”的问题,本质上不是数据库不聪明,而是索引顺序、表达式或返回列与查询并不匹配
  • 下次排查慢查询时,可以直接按这三个问题检查:有没有写放大成本、复合索引顺序是否正确、能不能改成 partial 或 covering index

ref

  • 来源:WuCai highlights + page note