IIWAB 针对**二值标识字段(0/1)**的最优索引方案(2000万大表) - IIWAB

针对**二值标识字段(0/1)**的最优索引方案(2000万大表)

IIWAB 10小时前 ⋅ 5 阅读

针对**二值标识字段(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 = '';

这个索引强在哪里?

  1. 只索引符合你条件的极少量数据 你的查询结果为空/极少,这个索引只存满足 pdaflag='1' 且 sendread='' 的行,可能只有几十行,体积几乎可以忽略。
  2. 天然带排序 索引键直接用 fcreatetime,查询自带排序,连内存排序都省了
  3. 覆盖索引 INCLUDE(FId) 实现 Index Only Scan,完全不查原表。
  4. 二值字段的最优解 避开了二值字段区分度低的缺点,只索引你需要的那一小部分数据。

二、备选方案:常规复合索引(兼容更多场景)

如果你除了当前查询,还会用这两个标识字段做其他查询,用这个:

-- 并发创建复合索引
CREATE INDEX CONCURRENTLY idx_scancode_flag_time 
ON tk_scancoderecord (fk_pdaflag, fk_sendreadheadflag, fcreatetime)
INCLUDE (FId);

三、核心原理(为什么二值字段要这么建)

  1. 二值字段(0/1)区分度极低 单独/复合索引都会扫描大量无效数据,速度慢、体积大。
  2. 部分索引 = 精准切片 直接把 WHERE 条件写进索引定义只索引你要的那几行数据,性能碾压常规索引。
  3. 你的查询场景完美匹配 结果为空/少量数据 → 部分索引极小,查询瞬间出结果。

四、验证索引生效

执行执行计划,看到这两个标志就是最优状态:

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;

生效标志

  1. Index Only Scan using idx_scancode_partial(仅索引扫描)
  2. Rows: 极少(无全表扫描)

五、必看注意事项

  1. 生产环境必须加 CONCURRENTLY 2000万大表不加会锁表,导致业务不可用。
  2. 创建后执行统计信息更新
    ANALYZE tk_scancoderecord;
    
  3. 删除旧索引 避免索引冲突,提升优化器判断效率。

总结

  1. 二值标识字段 + 少量结果集 = 部分索引(首选)
  2. 直接用第一条 SQL 创建,速度最快、体积最小、最适合你的场景
  3. 执行计划看到 Index Only Scan 就是完美状态

全部评论: 0

    我有话说: