解释Postgres中解释分析的结果

时间:2019-05-27 15:45:59

标签: sql postgresql postgresql-10

最近一次查询大约需要9分钟才能完成。为了确定原因,我使用了EXPLAIN ANALYZE来解决问题。从输出看,似乎所有内容都具有适当的索引,这只需要花费很长时间。

我将查询和结果放在下面。是否由于数据量而花费这么长时间?还是我做错了什么。我的查询是否需要从根本上进行更改以提高性能?

其他信息:PostgreSQL 10.6。 Xeon @ 3.4Ghz上的系统,具有SSD和24GB内存,因此它是相当不错的台式机规格。

SELECT      s.start_date, s.end_date, s.resources, s.activity_index, r.resource_id, sa.usedresourceset 
FROM        rm_o_resource_usage_instance_splits_new s 
INNER JOIN  rm_o_resource_usage r ON s.usage_id = r.id 
INNER JOIN  scheduledactivities sa ON s.activity_index = sa.activity_index 
    AND r.schedule_id = sa.solution_id 
    and s.solution = sa.solution_id 
WHERE       r.schedule_id = 14349 
ORDER BY   r.resource_id, s.start_date
----------------------------------------------------------------
"Sort  (cost=18.01..18.01 rows=1 width=86) (actual time=541075.198..541099.504 rows=65354 loops=1)"
"  Sort Key: r.resource_id, s.start_date"
"  Sort Method: external merge  Disk: 8016kB"
"  ->  Nested Loop  (cost=0.85..18.00 rows=1 width=86) (actual time=6.946..540671.934 rows=65354 loops=1)"
"        Join Filter: (s.activity_index = sa.activity_index)"
"        Rows Removed by Join Filter: 3550029280"
"        ->  Nested Loop  (cost=0.42..12.93 rows=1 width=98) (actual time=0.074..1795.054 rows=65354 loops=1)"
"              Join Filter: (s.usage_id = r.id)"
"              Rows Removed by Join Filter: 248018"
"              ->  Index Scan using rm_o_resource_usage_instance_splits_new_solution_idx on rm_o_resource_usage_instance_splits_new s  (cost=0.42..4.76 rows=1 width=69) (actual time=0.032..36.395 rows=65354 loops=1)"
"                    Index Cond: (solution = 14349)"
"              ->  Seq Scan on rm_o_resource_usage r  (cost=0.00..8.15 rows=2 width=45) (actual time=0.018..0.019 rows=5 loops=65354)"
"                    Filter: (schedule_id = 14349)"
"                    Rows Removed by Filter: 332"
"        ->  Index Scan using scheduled_activities_idx on scheduledactivities sa  (cost=0.42..5.06 rows=1 width=16) (actual time=0.007..4.937 rows=54321 loops=65354)"
"              Index Cond: (solution_id = 14349)"
"Planning time: 1.547 ms"
"Execution time: 541104.491 ms"

1 个答案:

答案 0 :(得分:2)

查看您的查询执行计划会花费大量时间进行排序

    "Sort  (cost=18.01..18.01 rows=1 width=86) (actual time=541075.198..541099.504 rows=65354 loops=1)"
"  Sort Key: r.resource_id, s.start_date"
"  Sort Method: external merge  Disk: 8016kB"

我建议您按照work_mem所述为PostgreSQL增加here 参数

  

如果您执行许多复杂的排序并且有很多内存,那么增加work_mem参数可以使PostgreSQL做更大的事情   毫无疑问,内存中的排序将比基于磁盘的排序更快   等价物。

     

此大小适用于每个用户完成的每种排序,并且   复杂的查询可以使用多个工作内存排序缓冲区。设置它   到50MB,并有30个用户提交查询,您很快就会使用   1.5GB的实际内存。此外,如果查询涉及对8个表进行合并排序,则需要8倍work_mem。你需要   考虑设置max_connections的大小   参数正确。这是数据仓库系统的设置,   用户提交非常大的查询时,可以随时使用   许多GB的内存。

     

log_temp_files可用于记录排序,哈希和临时文件,   在确定是否将各种数据溢出到磁盘而不是磁盘上时很有用   适合内存。您可以使用EXPLAIN看到排序溢出到磁盘   以及分析计划。例如,如果您看到类似“排序”的行   方法:外部合并磁盘:EXPLAIN ANALYZE的输出中的7526kB,   至少8MB的work_mem会将中间数据保留在内存中   并可能会缩短查询响应时间(尽管可能会花费一些时间   超过8MB的空间完全作为数据存储在内存中   在磁盘上以更紧凑的格式存储。)