我使用Postgres 12.10 AWS RDS。我使用组by查找分钟日期的查询要比该日期上的常规分钟更快。我希望常规的最小值能够保持同样的速度,但不确定我是否放错了指数,或者我需要调优另一个参数。
我有张桌子
CREATE TABLE IF NOT EXISTS public.ed
(
isd character varying(90) COLLATE pg_catalog."default" NOT NULL,
e_id character varying(32) COLLATE pg_catalog."default" NOT NULL,
d_date timestamp with time zone NOT NULL,
CONSTRAINT ed_pkey PRIMARY KEY (isd, e_id)
)指数:
CREATE INDEX IF NOT EXISTS ix_ed_d_date
ON public.ed USING btree
(d_date ASC NULLS LAST)
TABLESPACE pg_default;
CREATE INDEX IF NOT EXISTS ix_ed_e_id
ON public.ed USING btree
(e_id COLLATE pg_catalog."default" ASC NULLS LAST)
TABLESPACE pg_default;不需要min的查询需要3分钟:
select min(d_date)
from ed
where e_id = '62e2032b029b036ba25c73cf';为查询解释分析:
Result (cost=171.70..171.71 rows=1 width=8) (actual time=186940.968..186941.463 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Limit (cost=0.56..171.70 rows=1 width=8) (actual time=186940.963..186940.964 rows=1 loops=1)
-> Index Scan using ix_ed_d_date on ed (cost=0.56..2214942.25 rows=12943 width=8) (actual time=186940.961..186940.962 rows=1 loops=1)
Index Cond: (d_date IS NOT NULL)
Filter: ((e_id)::text = '62e2032b029b036ba25c73cf'::text)
Rows Removed by Filter: 30539883
Planning Time: 0.195 ms
Execution Time: 186941.491 ms而使用group by的查询所花费的时间不到1秒钟:
select min(d_date)
from ed
where e_id in ('62e2032b029b036ba25c73cf')
group by e_id;解释分析:
GroupAggregate (cost=0.56..5365.73 rows=2319 width=33) (actual time=92.093..92.095 rows=1 loops=1)
Group Key: e_id
-> Index Scan using ix_ed_e_id on ed (cost=0.56..5277.83 rows=12943 width=33) (actual time=6.753..90.622 rows=6698 loops=1)
Index Cond: ((e_id)::text = '62e2032b029b036ba25c73cf'::text)
Planning Time: 0.098 ms
Execution Time: 92.127 ms我得到了同样的结果,但是为什么使用d_date索引的查询更简单呢?如何使不使用min(d_date)的简单group by成为使用group by的性能?
发布于 2022-10-13 08:42:47
'62e2032b029b036ba25c73cf'似乎是一个常见的e_id,因此PostgreSQL认为它可以通过查看按d_date顺序排列的行来获胜,直到找到具有正确e_id的行为止。不幸的是,使用e_id = '62e2032b029b036ba25c73cf'的所有行都具有较高的d_date,而PostgreSQL必须跳过3000万行,直到找到命中为止。
如果使用PostgreSQL,可以防止min(d_date + INTERVAL '0')使用索引。那么第一个查询应该和第二个查询一样快。
在(e_id, d_date)上创建一个复合索引将是解决这个问题的完美解决方案,那么PostgreSQL就不会错误地选择错误的索引。
https://dba.stackexchange.com/questions/318165
复制相似问题