【发布时间】:2019-06-12 00:47:34
【问题描述】:
以下查询在 PostgreSQL 11.1 中耗时超过 7 分钟:
SELECT
'2019-01-19' as date,
'2019-01-19'::date - generate_series(first_observed, last_observed, interval '1 day')::date as days_to_date,
ROUND(AVG(price)) as price,
area_id
FROM
table_example
GROUP BY
days_to_date, area_id;
table_example 大约有 1500 万行。
有什么方法可以优化吗?我已经添加了以下索引:
CREATE INDEX ON table_example (first_observed, last_observed);
CREATE INDEX ON table_example (area_id);
这是EXPLAIN (ANALYZE,BUFFERS)的输出:
GroupAggregate (cost=3235559683.68..3377398628.68 rows=1418000 width=72) (actual time=334933.966..440096.869 rows=21688 loops=1)
Group Key: (('2019-01-19'::date - ((generate_series((first_observed)::timestamp with time zone, (last_observed)::timestamp with time zone, '1 day'::interval)))::date)), area_id
Buffers: local read=118167 dirtied=118167 written=117143, temp read=1634631 written=1635058
-> Sort (cost=3235559683.68..3271009671.18 rows=14179995000 width=40) (actual time=334923.933..391690.184 rows=380203171 loops=1)
Sort Key: (('2019-01-19'::date - ((generate_series((first_observed)::timestamp with time zone, (last_observed)::timestamp with time zone, '1 day'::interval)))::date)), area_id
Sort Method: external merge Disk: 9187584kB
Buffers: local read=118167 dirtied=118167 written=117143, temp read=1634631 written=1635058
-> Result (cost=0.00..390387079.39 rows=14179995000 width=40) (actual time=214.798..171717.941 rows=380203171 loops=1)
Buffers: local read=118167 dirtied=118167 written=117143
-> ProjectSet (cost=0.00..71337191.89 rows=14179995000 width=44) (actual time=214.796..102823.749 rows=380203171 loops=1)
Buffers: local read=118167 dirtied=118167 written=117143
-> Seq Scan on table_example (cost=0.00..259966.95 rows=14179995 width=44) (actual time=0.031..2449.511 rows=14179995 loops=1)
Buffers: local read=118167 dirtied=118167 written=117143
Planning Time: 0.409 ms
JIT:
Functions: 18
Options: Inlining true, Optimization true, Expressions true, Deforming true
Timing: Generation 5.034 ms, Inlining 13.010 ms, Optimization 121.440 ms, Emission 79.996 ms, Total 219.480 ms
Execution Time: 441133.410 ms
这就是 table_example 的样子:
column name data type
'house_pk' 'integer'
'date_in' 'date'
'first_observed' 'date'
'last_observed' 'date'
'price' 'numeric'
'area_id' 'integer'
有 60 个不同的 area_id。
查询正在具有 128 GB 内存的多核机器(24 核)上运行。但是,设置可能不是最佳的。
【问题讨论】:
-
数据量很大——而且查询中没有过滤器。我怀疑你能否得到很大的改进。
-
表定义会有所帮助 -
CREATE TABLE带有数据类型和约束的语句。加上EXPLAIN (ANALYZE, BUFFERS)的输出。请参阅:stackoverflow.com/tags/postgresql-performance/info 您是否需要同时获得所有日期和所有区域的结果?您是否有一个area表,每个相关area_id有 1 行?有多少不同的area_id?first_observed和last_observed- min/max/avg 之间有多少天? -
@ErwinBrandstetter 1) 我现在添加了
EXPLAIN (ANALYZE, BUFFERS)的信息。 2)我确实需要一次所有日子的结果。我可以对区域进行多次查询,但这需要进行 60 次查询而不是 1 次。 3)我不确定你的意思。我确实有一个包含 area_ids 的表,每个 area_id 一行。你是这个意思吗? 4) 60 area_ids, 5) min = 0, max=335, avg=25.8 -
完整的
CREATE TABLE声明是披露有关您的表的信息的方式。示例:stackoverflow.com/questions/9789736/… 各种客户端(包括 pgAdmin3 和 pgAdmin4)显示反向工程语句。
标签: sql postgresql postgresql-performance generate-series set-returning-functions