Разница в производительности Postgres и плане запросов при переходе на новую версию

#postgresql #postgresql-9.6 #postgresql-13

Вопрос:

Мы обновляем базу данных с Postgres 9.6 до 13.4. Во время обновления мы наблюдали гораздо более низкую производительность запросов в новом экземпляре postgres 13.4.

Имеет некоторый смысл, что производительность в новом экземпляре будет ниже — однако мы видим, что запросы выполняются с существенно различными планами запросов (схемы БД и индексы, конечно, одинаковы).

Мы пытаемся понять причину различных планов запросов. Например, у нас есть запрос, который выполняется на порядки медленнее в новой версии 13.4 (например, 26 секунд против 200 мс).

Существует ли стандартный шаг в процессе миграции «обновление версии», которого нам не хватает, который помог бы объяснить более низкую производительность и значительно отличающиеся планы запросов?

Изменить: Пример запроса и различные планы запросов в Postgres 9.6 и 13.4

Запрос

 EXPLAIN ANALYZE
SELECT
    *
FROM
    "my_table"
WHERE
    "foo" = TRUE
    AND "bar" = FALSE
    AND("baz" > '2021-09-16 18:58:42.311 00'
        OR("baz" = '2021-09-16 18:58:42.311 00'
            AND "id" > 81353542))
ORDER BY
    "baz" ASC,
    "id" ASC
LIMIT 1;
 

План запросов Postgres 9.6:

 Limit  (cost=548886.22..548886.22 rows=1 width=152) (actual time=1232.777..1232.778 rows=1 loops=1)
  ->  Sort  (cost=548886.22..549884.61 rows=1996789 width=152) (actual time=1232.776..1232.776 rows=1 loops=1)
        Sort Key: baz, id
        Sort Method: top-N heapsort  Memory: 25kB
        ->  Bitmap Heap Scan on my_table  (cost=30571.88..546889.43 rows=1996789 width=152) (actual time=531.993..1014.384 rows=1914762 loops=1)
              Recheck Cond: ((foo AND (NOT bar) AND (baz > '2021-09-16 18:58:42.311 00'::timestamp with time zone)) OR (foo AND (NOT bar) AND (baz = '2021-09-16 18:58:42.311 00'::timestamp with time zone) AND (id > 81353542)))"
              Filter: (foo AND (NOT bar))
              Heap Blocks: exact=83762
              ->  BitmapOr  (cost=30571.88..30571.88 rows=1996789 width=0) (actual time=512.609..512.609 rows=0 loops=1)
                    ->  Bitmap Index Scan on my_table_foo_bar_ts_id  (cost=0.00..30370.08 rows=1996789 width=0) (actual time=512.588..512.588 rows=2704908 loops=1)
                          Index Cond: ((foo = true) AND (bar = false) AND (baz > '2021-09-16 18:58:42.311 00'::timestamp with time zone))"
                    ->  Bitmap Index Scan on my_table_foo_bar_ts_id  (cost=0.00..2.12 rows=1 width=0) (actual time=0.020..0.020 rows=0 loops=1)
                          Index Cond: ((foo = true) AND (bar = false) AND (baz = '2021-09-16 18:58:42.311 00'::timestamp with time zone) AND (id > 21153592))"
Planning time: 0.181 ms
Execution time: 1233.303 ms

 

Postgres 13.4 План запросов:

 Limit  (cost=0.11..0.64 rows=1 width=152) (actual time=32871.675..32871.677 rows=1 loops=1)
  ->  Index Scan using my_table_foo_bar_ts_id on my_table  (cost=0.11..1040476.82 rows=1962741 width=152) (actual time=32871.673..32871.674 rows=1 loops=1)
        Index Cond: ((foo = true) AND (bar = false))
        Filter: ((baz > '2021-09-16 18:58:42.311 00'::timestamp with time zone) OR ((baz = '2021-09-16 18:58:42.311 00'::timestamp with time zone) AND (id > 81353542)))"
        Rows Removed by Filter: 18745951
Planning Time: 0.182 ms
Execution Time: 32871.705 ms
 

Комментарии:

1. Вы бежали ANALYZE; после обновления? (Еще лучше: VACUUM ANALYZE; ) См.: dba.stackexchange.com/a/187981/3684

2. Мы не знаем, что вы сделали, поэтому не знаем, пропустили ли вы что-то «стандартное». Если очистка и анализ базы данных не устраняют проблему, то покажите EXPLAIN (ANALYZE, BUFFERS) для запроса для каждой версии и покажите все настройки конфигурации, отличные от настроек по умолчанию.

3. @ErwinBrandstetter мы запустили оба, результат не изменился. Я добавил образец запроса и планы запросов

4. @jjanes Я добавил пример запроса и различные планы запросов. Могу ли я предоставить какую-либо дополнительную информацию, которая могла бы помочь диагностировать происходящее?

5. work_mem Установлено одинаковое значение в обеих установках?

Ответ №1:

вот мои мысли.

postgresql не использует сканирование растрового индекса, потому что он сильно переоценил количество записей, которые, как он думал, вернутся, и решил выполнить «комбинированное сканирование индекса», а вместо этого просто один раз прочитать таблицу.

поэтому я предлагаю «проанализировать», чтобы убедиться, что ваша статистика актуальна, а также, возможно, ваши непристойности повреждены, поэтому попробуйте переиндексировать и повторите попытку

 vaccume analyze;
analyze [table];
reindex;