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 尤其要注意这一点;不要把它当作纯粹的预览开关。
建索引前的三个问题
- 哪一条高频或高代价查询需要改善?
- 条件能排除多少数据,是否还涉及排序或关联?
- 读性能的收益,是否值得额外的写入和存储成本?
优秀的索引设计,来自工作负载与测量,而不只是字段名称。
继续阅读
EOF / 感谢阅读继续探索 ↗