简体   繁体   English

如何为条件日期查询构建高效的 PostgreSQL 索引?

[英]How to construct an efficient PostgreSQL index for a conditional date query?

I'm trying to query a large database of ~10 million rows, to find all rows with a timestamp above a certain date and with a boolean flag set to false, like:我正在尝试查询约 1000 万行的大型数据库,以查找时间戳高于某个日期且 boolean 标志设置为 false 的所有行,例如:

SELECT COUNT(id) FROM mytable WHERE (NOT fresh OR created IS NULL OR created <= '2021-1-1');

This query was taking an hour to run, but isn't too complex, so I tried creating an index for it like:这个查询需要一个小时才能运行,但并不太复杂,所以我尝试为它创建一个索引,例如:

CREATE INDEX CONCURRENTLY mytable_fresh_created ON mytable (fresh, created ASC) WHERE fresh = false;

but this has made virtually no improvement on performance.但这对性能几乎没有任何改善。 And running EXPLAIN shows a sequential scan:运行EXPLAIN显示顺序扫描:

 Finalize Aggregate  (cost=18641642.51..18641642.52 rows=1 width=8)
   ->  Gather  (cost=18641642.29..18641642.50 rows=2 width=8)
         Workers Planned: 2
         ->  Partial Aggregate  (cost=18640642.29..18640642.30 rows=1 width=8)
               ->  Parallel Seq Scan on mytable  (cost=0.00..18629381.98 rows=4504126 width=4)
                     Filter: ((NOT fresh) OR (created IS NULL) OR (created <= '2021-1-1'::timestamp with time zone))

so it doesn't even look like the index is even being used.所以看起来甚至没有使用索引。

How do I construct a better index for this type of query?如何为此类查询构建更好的索引?

When you are using OR then indexes not using.当您使用OR时,索引不使用。 I recommended using UNION ALL .我建议使用UNION ALL Example:例子:

SELECT *
FROM mytable 
WHERE (created <= '2021-01-01'::date)
union all 
SELECT *
FROM mytable 
WHERE (created IS NULL)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM