针对**二值标识字段(0/1)**的最优索引方案(2000万大表)
这两个字段都是只有 0/1 的二值状态,常规复合索引效率一般,必须用「部分索引(Partial Index)」——这是 PG 专为这种场景设计的终极优化方案,体积最小、速度最快、创建最快。
一、终极方案:部分索引(强烈推荐)
直接执行(生产环境首选并发创建,不锁表)
-- 并发创建部分索引(不锁表,2000万大表生产环境必用)
CREATE INDEX CONCURRENTLY idx_scancode_partial
ON tk_scancoderecord (fcreatetime)
INCLUDE (FId)
WHERE fk_pdaflag = '1'
AND fk_sendreadheadflag = '';
这个索引强在哪里?
- 只索引符合你条件的极少量数据
你的查询结果为空/极少,这个索引只存满足
pdaflag='1' 且 sendread=''的行,可能只有几十行,体积几乎可以忽略。 - 天然带排序
索引键直接用
fcreatetime,查询自带排序,连内存排序都省了。 - 覆盖索引
INCLUDE(FId)实现Index Only Scan,完全不查原表。 - 二值字段的最优解 避开了二值字段区分度低的缺点,只索引你需要的那一小部分数据。
二、备选方案:常规复合索引(兼容更多场景)
如果你除了当前查询,还会用这两个标识字段做其他查询,用这个:
-- 并发创建复合索引
CREATE INDEX CONCURRENTLY idx_scancode_flag_time
ON tk_scancoderecord (fk_pdaflag, fk_sendreadheadflag, fcreatetime)
INCLUDE (FId);
三、核心原理(为什么二值字段要这么建)
- 二值字段(0/1)区分度极低 单独/复合索引都会扫描大量无效数据,速度慢、体积大。
- 部分索引 = 精准切片
直接把
WHERE 条件写进索引定义,只索引你要的那几行数据,性能碾压常规索引。 - 你的查询场景完美匹配 结果为空/少量数据 → 部分索引极小,查询瞬间出结果。
四、验证索引生效
执行执行计划,看到这两个标志就是最优状态:
EXPLAIN ANALYZE
SELECT A.FId "id", A.fcreatetime "createtime"
FROM tk_scancoderecord A
WHERE A.fk_pdaflag = '1' AND A.fk_sendreadheadflag = ''
ORDER BY A.fcreatetime;
✅ 生效标志
Index Only Scan using idx_scancode_partial(仅索引扫描)Rows: 极少(无全表扫描)
五、必看注意事项
- 生产环境必须加
CONCURRENTLY2000万大表不加会锁表,导致业务不可用。 - 创建后执行统计信息更新
ANALYZE tk_scancoderecord; - 删除旧索引 避免索引冲突,提升优化器判断效率。
总结
- 二值标识字段 + 少量结果集 = 部分索引(首选)
- 直接用第一条 SQL 创建,速度最快、体积最小、最适合你的场景
- 执行计划看到
Index Only Scan就是完美状态
注意:本文归作者所有,未经作者允许,不得转载