PostgreSQL:查询WHERE emailed_at IS NULL是否需添加索引?
在PostgreSQL中优化
WHERE IS NULL查询的索引建议 针对你的场景——数十万行的表,仅最近1天的记录emailed_at为NULL,我可以明确告诉你:非常建议为emailed_at字段添加索引,原因如下:
为什么PostgreSQL的索引能支持IS NULL查询
PostgreSQL的标准B-tree索引是包含NULL值的(这点和部分其他数据库不同),所以emailed_at IS NULL的查询完全可以利用到该字段的索引。不过索引的实际收益,核心看NULL值在表中的占比:
- 当NULL值占比极低(比如你的情况,仅最近1天数据为NULL,在数十万行里占比很小):索引能让查询直接定位到所有符合条件的行,彻底避免全表扫描,性能提升非常显著。
- 如果NULL值占比很高(比如超过30%):PostgreSQL可能会选择全表扫描,因为遍历索引再回表取数据的成本,反而比直接扫整个表更高。
你的场景下添加索引的优势
结合你的实际情况:
- 查询性能暴增:原本要扫描数十万行的全表操作,会变成直接通过索引定位少量NULL行,速度提升几个数量级都有可能。
- 写入开销可忽略:只有新插入的最近1天的记录会更新这个索引,对日常写入性能几乎没有影响。
如何创建合适的索引
最简单的方式是创建普通B-tree索引:
CREATE INDEX idx_people_emailed_at ON people (emailed_at);
如果你的查询不是每次都需要SELECT *,而是只需要特定列(比如id、name),可以创建覆盖索引,让查询直接从索引里拿数据,不需要回表查原表,进一步优化:
CREATE INDEX idx_people_emailed_at_covering ON people (emailed_at) INCLUDE (id, name);
确认索引是否生效
创建完索引后,用EXPLAIN ANALYZE命令跑一遍你的查询,就能看到索引有没有被用上:
EXPLAIN ANALYZE SELECT * FROM people WHERE emailed_at IS NULL;
如果输出里出现类似Index Scan using idx_people_emailed_at on people的内容,就说明索引已经在工作了。
内容的提问来源于stack exchange,提问作者jemminger
相关产品推荐
相关产品推荐

