我在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。我已经为这两个列建立了索引 事件ID 和 parent_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上运行类似查询时,性能要好得多。
在此非常感谢!
打一个索引几十万次都不免费。 哈希连接实际上可能比这快。
你这里最慢的一步是根据时间戳获取行。 也许一个索引在 (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中的速度更快并不能帮助我们,除非你能告诉我们那里使用的计划。