题目重点:用选择性、回表、复合键和执行计划解释索引,不把建索引当所有查询的万能优化。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 讨论常见关系库有序索引,具体planner、MVCC与索引类型依数据库而变。
解题路线
- 索引保存按可查找key组织的辅助入口,使等值或范围查询无需逐行判断整表。表扫描O(N)行,树查找可沿少量页定位匹配区间,再读取结果行。
- 索引不是无条件更快:命中大比例行时随机回表IO可能比连续扫描昂贵;小表、低选择性或统计信息错误也会使planner选全扫。应看执行计划与实际读页/返回行数。
- 复合索引按列序形成键序,例如(user_id,created_at)适合固定用户的时间范围;不能未经条件分析保证单独created_at搜索同样有效。函数、隐式类型转换和collation也影响可用匹配。
- 覆盖索引可减少回表,但是否真正index-only还受数据库可见性等条件;把全业务字段都塞进索引会增加空间、写放大和缓存压力。
- 写入/更新/删除要同步维护索引,并影响锁、日志与页分裂。索引过多牺牲写吞吐,建索引也可能占资源或阻塞,上线方式按数据库特性验证。
- 测试同时测结果一致性、计划、代表负载和冷/热缓存,观察p95而不是仅一次查询时间。先定位热点谓词与排序,再选索引,不能只根据字段名猜。
手动走一遍
百万订单只查某用户最近20条,(user_id,created_at)能定位一段并按序取;查全表90%订单时同索引未必胜过顺序扫描。新增status索引也会让每次状态变更多一次维护。
规模与取舍
树定位通常O(log_B N)页级访问,返回k条至少Ω(k),回表/排序另计;存储与写开销按键宽、条目数和索引个数增长。
易错点与追问
容易失分的边界
- 有索引一定使用且一定快。
- 只算定位不计回表和输出。
- 复合索引列序无影响。
继续深挖
- 怎样读EXPLAIN和实际行数?
- 为什么低选择性索引可能不用?
- 覆盖索引有什么代价?
技术参考
- PostgreSQL Index Introduction:技术语义参考,具体题目按本文约定。
