Изменения плана запроса во время выполнения в postgres - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть две простые таблицы:

Profile (20M entries)
----------------------------
pId | fail 
123 | 0
234 | 2
345 | 0

Work (50M entries)
-----------------
pId
123
234
123
345
123
345

Я просто хочу пометить fail как 1 в Profile таблице для записей, которые имеют более высокий порог pId записей в Work Таблица. pId в Profile таблица проиндексирована, и я не хочу касаться строк, в которых fail не 0.

Запрос, который я сейчас использую:

UPDATE Profile 
SET fail = 1 
WHERE pId IN 
    (
      SELECT pId 
      FROM Work 
      GROUP BY pId 
      HAVING COUNT(*) > 2
    )
AND Profile.fail = 0;

В pgAdmin я получаю план объяснения, как показано ниже:

"Update on Profile a  (cost=1134492.79..1559750.23 rows=5180 width=1014)"
"  ->  Hash Join  (cost=1134492.79..1559750.23 rows=5180 width=1014)"
"        Hash Cond: (a.pId = b.pId)"
"        ->  Seq Scan on Profile a  (cost=0.00..425216.00 rows=15462 width=976)"
"              Filter: (fail = 0)"
"        ->  Hash  (cost=1134491.95..1134491.95 rows=67 width=32)"
"              ->  Subquery Scan on b  (cost=1134488.78..1134491.95 rows=67 width=32)"
"                    ->  HashAggregate  (cost=1134488.78..1134491.28 rows=67 width=4)"
"                          Group Key: Work.pId"
"                          Filter: (count(*) > 5)"
"                          ->  Seq Scan on Work  (cost=0.00..894341.52 rows=48029452 width=4)"

Для запуска требуется несколько минут.

Теперь, когда эти две таблицы создаются во время выполнения с одними и теми же данными, план запроса изменяется на:

"Update on Profile  (cost=1250747.42..1251317.47 rows=67 width=386)"
"  ->  Nested Loop  (cost=1250747.42..1251317.47 rows=67 width=386)"
"        ->  Subquery Scan on "ANY_subquery"  (cost=1250746.98..1250750.15 rows=67 width=32)"
"              ->  HashAggregate  (cost=1250746.98..1250749.48 rows=67 width=4)"
"                    Group Key: Work.pId"
"                    Filter: (count(*) > 5)"
"                    ->  Seq Scan on Work  (cost=0.00..985990.32 rows=52951332 width=4)"
"        ->  Index Scan using Profile_idx on Profile  (cost=0.44..8.46 rows=1 width=348)"
"              Index Cond: (pId = "ANY_subquery".pId)"
"              Filter: (fail = 0)"

Для выполнения которого требуется час. Я даже пытался переключиться с подзапроса на объединение, но он все еще дает тот же результат. Любая помощь будет оценена.

1 Ответ

1 голос
/ 04 февраля 2020

Вероятно, ключ к вашей проблеме:

Теперь, когда эти две таблицы создаются во время выполнения с одинаковыми данными, план запроса меняется на [худшее]

PostgreSQL автоматически собирает статистику таблицы, но для автоматического анализа требуется короткое время.

Все запросы, которые выполняются между массовой модификацией данных и временем завершения автоанализа, вероятно, будут иметь плохое выполнение планы.

Хорошей идеей будет явный запуск ANALYZE для таблиц в конце массовых изменений данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...