Postgres EXPLAIN ANALYZE подсчитывает количество строк, значительно превышающее фактическое количество строк. Нет пылесосить? - PullRequest
0 голосов
/ 03 июля 2018

У меня есть база данных Postgres 9.4.18, запущенная на Heroku в проекте Django. Я заметил, что запросы становятся все более медленными, поэтому я запустил «EXPLAIN ANALYZE» для одного запроса и заметил, что для одного узла оценка строки была значительно выше, чем фактическое число строк:

->  Seq Scan on listings_listing u1  (cost=0.00..1536692.01 rows=5030003 width=8) (actual time=0.811..11263.410 rows=173537 loops=1)

Затем я запустил «VACUUM FULL ANALYZE» для таблицы, а затем повторно применил «EXPLAIN ANALYZE» к запросу и получил:

->  Seq Scan on listings_listing u1  (cost=0.00..23554.61 rows=173537 width=8) (actual time=0.001..33.884 rows=173537 loops=1)

Время выполнения теперь в 100 раз быстрее.

Итак, два вопроса: а) не должна ли автоматическая очистка пылесоса предотвращать это? (как я могу проверить, включено ли это?) B) как это получилось при условии, что пылесос не выполняется?

--------------------------------- Обновление

Я нашел эту команду от heroku, которая выдает статистику по автовакууму, и вот вывод (к сожалению, я выполнил ее после своего ручного вакуума.

heroku pg:vacuum_stats DATABASE_URL

schema |                  table                  | last_vacuum | last_autovacuum  |    rowcount    | dead_rowcount  | autovacuum_threshold | expect_autovacuum 
--------+-----------------------------------------+-------------+------------------+----------------+----------------+----------------------+-------------------
 public | listings_listing                        |             | 2018-06-27 15:36 |        173,537 |              0 |         34,757       | 

Казалось бы, указанный порог должен был привести к тому, что он давным-давно опустился.

Кроме того, вот страница Heroku с документацией по настройке вакуумирования: https://devcenter.heroku.com/articles/managing-vacuum-on-heroku-postgres

Ответы [ 2 ]

0 голосов
/ 12 июля 2018

Ответ Лоренца Альбе отлично подходит для объяснения того, что случилось с автоматической очисткой пылесосом, но теперь я хотел бы ответить на то, что я позже узнал о том, почему мой счет мертвых кортежей увеличивался.

В основном из-за ошибки в моем коде я обновлял каждую строку в базе данных каждые 15 минут, а не только те, которые соответствуют фильтру. Каждое обновление создавало мертвый кортеж, и оно вздулось так быстро, что пылесос не мог идти в ногу. Мне потребовалось некоторое время, чтобы найти ошибку, потому что я смотрел только на удаления в коде, а не на обновления, поскольку я не осознавал (в то время), что они тоже создают мертвые кортежи.

После исправления того, что не нужно было менять какие-либо настройки автоматического вакуумирования. Увеличение вздутия было нормальным.

0 голосов
/ 03 июля 2018

Чтобы узнать, включен ли автовакуум в порядке, запустите

SHOW autovacuum;

Чтобы узнать, отключен ли автовакуум для вашей конкретной таблицы, выполните команду

SELECT reloptions FROM pg_class WHERE relname = 'listings_listing';

Ответ на Б) прост:

Если автоочистка не работает, каждый UPDATE или DELETE создаст & ldquo; мертвый кортеж & rdquo; (или & ldquo; версия мертвой строки & rdquo;) в таблице. Они никогда не будут очищены до тех пор, пока вы не запустите VACUUM вручную, и это приведет к росту таблицы и замедлению последовательного сканирования.

Ответ на А) сложнее:

Есть несколько вещей, которые могут помешать работе автовакуума:

  • Скорость изменений в этой таблице может быть настолько высокой, что автовакуум, который работает медленно, по умолчанию, так что он не нарушает нормальную активность, не может идти в ногу.

    В этом случае вам следует настроить автовакуум, чтобы быть более агрессивным для этого стола:

    ALTER TABLE listings_listing SET (
       autovacuum_vacuum_cost_limit = 1000,
       toast.autovacuum_vacuum_cost_limit = 1000
    );
    

    Если этого недостаточно, вы можете

    ALTER TABLE listings_listing SET (
       autovacuum_vacuum_cost_delay = 0,
       toast.autovacuum_vacuum_cost_delay = 0
    );
    
  • Есть параллельные длинные транзакции.

    Autovacuum может удалять только мертвые кортежи, которые старше самой старой запущенной транзакции, поэтому длинные транзакции могут помешать ему выполнить свою работу.

    Есть еще одна история; прочитайте этот пост .

    Однако это также не позволит VACUUM (FULL) выполнять свою работу, так что, возможно, это не ваша проблема.

  • Таблица часто блокируется с помощью SHARE UPDATE EXCLUSIVE или более сильных блокировок, например, с помощью & ldquo; LOCK listings_listing & rdquo;.

    Когда автовакуум сталкивается с такой блокировкой, он отступает, а не блокирует активность пользователя.

Полезный способ определить, что происходит, - запросить pg_stat_user_tables следующим образом:

SELECT n_live_tup, n_dead_tup, last_vacuum, last_autovacuum
FROM pg_stat_user_tables
WHERE relname = 'listings_listing';

Но это доказательство, вероятно, уничтожено теперь, когда вы запустили VACUUM (FULL).

Еще одна полезная вещь - установить log_autovacuum_min_duration на что-то другое, чем -1, и время от времени заглядывать в журнал.

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