索引 — 建了却不走的原因
一句话总结
索引是按值排序的独立结构;优化器不使用索引通常是正确决定。
工作原理
B 树支持等值、范围和排序,但列上包裹函数会破坏可用顺序。
-- 안 탄다: 컬럼에 함수가 걸렸다
SELECT * FROM orders WHERE date(created_at) = '2026-07-26';
-- 탄다: 범위 조건으로 바꿔 컬럼을 그대로 둔다
SELECT * FROM orders
WHERE created_at >= '2026-07-26' AND created_at < '2026-07-27';
隐式转换和 LIKE '%kim%' 也可能阻止索引定位。若计划的 Filter 行显示函数,应检查此问题。复合索引 (a, b, c) 遵循最左列规则,应把等值列放前、范围列放后。
索引扫描需要随机访问堆页,返回大量行时可能比顺序扫描更慢。强制 enable_seqscan = off 往往适得其反。重要因素包括 random_page_cost、索引与堆的相关度,以及是否覆盖全部返回列。覆盖索引可进行 Index Only Scan。
针对少量 pending 行,可建立 WHERE status = 'pending' 的部分索引,减小体积和写入成本。但每次 INSERT、DELETE 都要维护全部索引。
阅读计划
比较预计行数与实际行数,先找超过十倍的偏差;计算节点自身时间与循环次数;检查过滤掉的行;区分缓存与磁盘读取,并在接近生产规模的数据上重复测量。
下个练习
建立多种索引、保存执行计划,并测量强制索引反而更慢的情况。