← 返回所有文章

DATABASE / 001//4 分钟阅读

数据库索引:让查询少走几步,而不是越多越好

从一本书的目录出发,理解 B-tree 索引、联合索引与执行计划。

在一本厚书里找一个主题,可以从第一页翻起,也可以先查目录。数据库索引与目录有相似之处:用额外的数据结构缩小搜索范围。

索引省下的是什么

没有合适索引时,数据库可能需要扫描大量行,再检查哪些满足条件。B-tree 索引按键值组织数据,可以为等值、范围查询与一些排序场景提供更直接的访问路径。

代价也很明确:索引占用存储空间,写入、更新和删除数据时还要维护相关索引。多加一个索引,并不意味着所有操作都更快。

从真实查询出发

假设经常需要查询某位用户最近的订单:

SELECT id, created_at, total
FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 20;

在 PostgreSQL 中,可以评估一个联合 B-tree 索引:

CREATE INDEX orders_user_created_idx
ON orders (user_id, created_at DESC);

这与查询结构相呼应:先按用户缩小范围,再按时间顺序取结果。但是否采用、能省多少代价,仍要看数据分布与执行计划。

联合索引是一种排序约定

可以把 (user_id, created_at) 想成先按用户分组、每组再按时间排列的目录。它对带有 user_id 条件的查询通常更有帮助;只查时间的查询,不一定能得到同样的收益。

不要把这个直觉机械地套成「没有最左列就绝不可能使用索引」。数据库版本、索引类型和优化器能力都可能影响具体行为。应当通过计划验证。

执行计划比猜测更可靠

EXPLAIN
SELECT id, created_at, total
FROM orders
WHERE user_id = 42
ORDER BY created_at DESC
LIMIT 20;

重点看预计扫描行数、访问方式和排序节点。有了索引,优化器仍可能选择顺序扫描:小表、匹配比例高或随机访问代价较大时,这可能是合理决定。

EXPLAIN ANALYZE 会实际执行语句,再报告运行情况。对修改数据的 SQL 尤其要注意这一点;不要把它当作纯粹的预览开关。

建索引前的三个问题

  1. 哪一条高频或高代价查询需要改善?
  2. 条件能排除多少数据,是否还涉及排序或关联?
  3. 读性能的收益,是否值得额外的写入和存储成本?

优秀的索引设计,来自工作负载与测量,而不只是字段名称。

继续阅读

EOF / 感谢阅读继续探索 ↗

搜索笔记

在全部文章中搜索