Postgresql--自连接性能不佳

问题描述 投票:1回答:1

我在SO上的第一个问题,所以提前道歉!

我的Postgresql(12.2)运行在Windows Server 2016上,在2个数值列上进行简单的自连接时,性能很差。表本身(form_content)由27列和约23,200,000行组成。该表存储的是用户使用表单的响应。每个表单都会生成多行,而且有一个重要的层次结构,例如:第5行可能是第6-10行的 "父行"(与表单中的某个部分有关),第6-10行可能与特定问题的回答有关。我对数据在这个表中的存储方式有一定的限制。每一行都有一个 "event_id "和一个 "parent_event_id"。在上面的例子中,第5行的 "event_id "将是第6-10行的 "parent_event_id"。

因此,为了提取响应,我正在运行以下查询(为了这个问题的目的,我只包括选择语句中的一些列。

select
   fc.event_id,
   fc1.result_val
from
   form_content fc
join
   form_content fc1
on
   fc.event_id = fc1.parent_event_id
where
   fc.performed_dt_tm >= '2020-06-01'::timestamp

上面的查询需要2-3分钟的时间来运行,大约有300,000行的 performed_dt_tm >= 2020-06-01。我已经为这两个列建立了索引 事件IDparent_event_id 列(以及索引。(event_id,parent_event_id)和(parent_event_id,event_id))的索引。我已经为上述查询运行了'EXPLAIN ANALYZE',看起来好像表索引没有被使用。

QUERY PLAN                                                                                                                                                                                       |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Gather  (cost=1485180.36..2252551.11 rows=933343 width=16) (actual time=222023.060..224259.345 rows=415750 loops=1)                                                                              |
  Workers Planned: 2                                                                                                                                                                             |
  Workers Launched: 2                                                                                                                                                                            |
  ->  Parallel Hash Join  (cost=1484180.36..2158216.81 rows=388893 width=16) (actual time=221939.001..223549.551 rows=138583 loops=3)                                                            |
        Hash Cond: (fc1.parent_event_id = fc.event_id)                                                                                                                                           |
        ->  Parallel Index Only Scan using idx_pf_rfg_content_parenteventid on form_content fc1  (cost=0.56..559818.60 rows=9697340 width=8) (actual time=19.702..34247.142 rows=7761647 loops=3)|
              Heap Fetches: 99129                                                                                                                                                                |
        ->  Parallel Hash  (cost=1482201.74..1482201.74 rows=120564 width=8) (actual time=174513.622..174513.624 rows=98016 loops=3)                                                             |
              Buckets: 131072  Batches: 4  Memory Usage: 4544kB                                                                                                                                  |
              ->  Parallel Seq Scan on form_content fc  (cost=0.00..1482201.74 rows=120564 width=8) (actual time=8.798..174288.343 rows=98016 loops=3)                                           |
                    Filter: (performed_dt_tm >= '2020-06-01 00:00:00'::timestamp without time zone)                                                                                              |
                    Rows Removed by Filter: 7663631                                                                                                                                              |
Planning Time: 27.449 ms                                                                                                                                                                         |
Execution Time: 224663.439 ms 

我对Postgresql比较陌生,在MSSQL上运行类似查询时,性能要好得多。

在此非常感谢!

postgresql self-join postgresql-12
1个回答
0
投票

打一个索引几十万次都不免费。 哈希连接实际上可能比这快。

你这里最慢的一步是根据时间戳获取行。 也许一个索引在 (peformed_dt_tm) 会有帮助。 更好的是,如果要获得仅有索引的扫描,可以尝试在 (performed_dt_tm, event_id).

另外,你应该VACUUM ANALYZE表。 并不是很明显的真空度很差(Heap Fetches: 99129 out of 7761647 rows is not obviously bad, but it could be better),但是在做分析工作的时候,能确定它的真空度很好,因为它多了一个未知变量。

知道它在MSSQL中的速度更快并不能帮助我们,除非你能告诉我们那里使用的计划。

© www.soinside.com 2019 - 2024. All rights reserved.