如何在 Postgres 中优化此查询
Posted
技术标签:
【中文标题】如何在 Postgres 中优化此查询【英文标题】:How can I optimize this query in Postgres 【发布时间】:2021-02-12 14:19:23 【问题描述】:以下查询需要更多时间来运行。如何优化以下查询以运行更多记录?我已经为这个查询运行了Explain Analyze
。附上相同的输出。
这是作为视图创建的现有查询,需要很长时间(超过几个小时)才能返回结果。
我已经对这两张表进行了清理、分析和重新索引,但没有运气。
select st_tr.step_trail_id,
st_tr.test_id,
st_tr.trail_id,
st_tr.step_name,
filter.regular_expression as filter_expression,
filter.order_of_occurrence as filter_order,
filter.match_type as filter_match_type,
null as begins_with,
null as ends_with,
null as input_source,
null as pattern_expression,
null as pattern_matched,
null as pattern_status,
null as pattern_order,
'filter' as record_type
from tab_report_step st_tr,
tab_report_filter filter
where st_tr.st_tr_id = filter.st_tr_id)
查询计划:
Hash Join (cost=446852.58..1176380.76 rows=6353676 width=489) (actual time=16641.953..47270.831 rows=6345360 loops=1)
Buffers: shared hit=1 read=451605 dirtied=5456 written=5424, temp read=154080 written=154074
-> Seq Scan on tab_report_filter filter (cost=0..24482.76 rows=6353676 width=161) (actual time=0.041..8097.233 rows=6345360 loops=1)
Buffers: shared read=179946 dirtied=4531 written=4499
-> Hash (cost=318817.7..318817.7 rows=4716070 width=89) (actual time=16627.291..16627.291 rows=4709040 loops=1)
Buffers: shared hit=1 read=271656 dirtied=925 written=925, temp written=47629
-> Seq Scan on tab_report_step st_tr (cost=0..318817.7 rows=4716070 width=89) (actual time=0.059..10215.484 rows=4709040 loops=1)
Buffers: shared hit=1 read=271656 dirtied=925 written=925
【问题讨论】:
这是一个表中的 470 万条记录和另一个表中的 640 万条记录之间的连接,您想要它们全部。它应该有多快?它每毫秒大约有 130 条记录,不是那么好,但也不是那么糟糕。你对 work_mem 的设置是什么? 感谢您的回复。 work_mem 设置为 200MB。 47 秒肯定不是“小时” 如果我在 st_tr.st_tr_id = filter.st_tr_id 上使用 join,会提高性能吗?或者有没有更好的方法来优化这个查询? 【参考方案1】:您没有在这些表上运行VACUUM
。也许是VACUUM (FULL)
,但肯定不是VACUUM
。
有两点可以改进:
确保在您阅读页面时不要弄脏或写入页面。这很可能是因为这是您第一次读取行,而 PostgreSQL 设置了 提示位。
运行VACUUM
(没有FULL
)可以解决这个问题。另外,如果你重复这个实验,你不应该再得到那些脏的和写入的缓冲区了。
通过增加work_mem
为查询提供更多内存。哈希不适合work_mem
并溢出到磁盘,这会导致额外的磁盘读取和写入,这对性能不利。
由于您连接两个没有限制WHERE
条件的大表并且有很多结果行,因此此查询永远不会很快。
【讨论】:
感谢您的回复。是的,我在两张桌子上都运行了 VACUUM FULL。将尝试使用 VACUUM。 work_mem 为 200 MB。以上是关于如何在 Postgres 中优化此查询的主要内容,如果未能解决你的问题,请参考以下文章