首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >postgres min()慢于group by的min()

postgres min()慢于group by的min()
EN

Database Administration用户
提问于 2022-10-13 08:34:42
回答 1查看 200关注 0票数 0

我使用Postgres 12.10 AWS RDS。我使用组by查找分钟日期的查询要比该日期上的常规分钟更快。我希望常规的最小值能够保持同样的速度,但不确定我是否放错了指数,或者我需要调优另一个参数。

我有张桌子

代码语言:javascript
运行
复制
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)
)

指数:

代码语言:javascript
运行
复制
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分钟:

代码语言:javascript
运行
复制
select min(d_date)
from ed
where e_id = '62e2032b029b036ba25c73cf';

为查询解释分析:

代码语言:javascript
运行
复制
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秒钟:

代码语言:javascript
运行
复制
select min(d_date)
from ed
where e_id in ('62e2032b029b036ba25c73cf')
group by e_id;

解释分析:

代码语言:javascript
运行
复制
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的性能?

EN

回答 1

Database Administration用户

回答已采纳

发布于 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就不会错误地选择错误的索引。

票数 3
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/318165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档