Интерпретация результатов анализа объяснения в Postgres - PullRequest
1 голос
/ 27 мая 2019

Недавно выполнил запрос, который занял около 9 минут.Пытаясь определить причину, я использовал EXPLAIN ANALYZE, чтобы помочь решить проблему.Исходя из результатов, все выглядит так, как будто все имеют соответствующие индексы, просто это занимает очень много времени.

Я поставил запрос и результаты ниже.Это просто так долго из-за объема данных?Или есть что-то, что я делаю не так.Должен ли мой запрос кардинально измениться, чтобы повысить производительность?

Дополнительная информация: PostgreSQL 10.6.Система в Xeon @ 3.4Ghz, с SSD и 24 ГБ памяти, так что это довольно хороший рабочий стол.

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 Ответ

2 голосов
/ 27 мая 2019

Глядя на ваш план запроса exec, много времени уходит на сортировку

    "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 param для PostgreSQL, как описано здесь

Если вы выполняете много сложных сортировок и имеете много памяти, то увеличение параметра work_mem позволяет PostgreSQL делать больше сортировка в памяти, что неудивительно, что будет быстрее, чем на диске эквиваленты.

Этот размер применяется к каждому виду, выполняемому каждым пользователем, и сложные запросы могут использовать несколько рабочих буферов сортировки памяти. Установить его до 50 МБ, и 30 пользователей отправляют запросы, и вы скоро используете 1,5 ГБ реальной памяти. Кроме того, если запрос включает в себя слияние 8 таблиц, для этого требуется 8 раз work_mem. Вам нужно рассмотреть, что вы установили max_connections для того, чтобы измерить это параметр правильно. Это установка, где системы хранилищ данных, где пользователи отправляют очень большие запросы, могут легко использовать много гигабайт памяти.

log_temp_files можно использовать для регистрации сортировок, хэшей и временных файлов, которые может быть полезно для выяснения, проливают ли виды на диск вместо вписывается в память. Вы можете увидеть, как сливаются на диск с помощью EXPLAIN АНАЛИЗ планов также. Например, если вы видите строку вроде Sort Метод: внешний диск слияния: 7526kB на выходе EXPLAIN ANALYZE, work_mem размером не менее 8 МБ будет хранить промежуточные данные в памяти и, вероятно, улучшить время ответа на запрос (хотя это может занять существенно больше, чем 8 МБ, чтобы сделать сортировку полностью в памяти, как данные на диске хранится в более компактном формате).

...