Какие факторы могут привести к низкой производительности базы данных Postgres?

Привет всем! <br/> Прошу помощи в анализе причин низкой производительности базы данных, связанной с большим количеством sharelock. <br/> У нас имеется высоконагруженная система с примерно 5000 активными пользователями. <br/> В часы пиковой нагрузки количество sharelock резко увеличивается — обычно до 12k, а сегодня достигло 21k, что приводит к снижению производительности системы. В то время как при уменьшении числа пользователей ситуация восстанавливается. При количестве sharelock до 4k система функционирует стабильно. <br/> Мы пробовали изменить параметр max_connections, начиная с 500 и увеличивая до 700 с шагом 100, но это не дало заметных результатов. <br/> <br/> Вот график sharelocks: <br/>
  • 3 февраля 2025 г. 9:14
Ответы на вопрос 2
Низкая производительность базы данных PostgreSQL, особенно в контексте большого количества `SHARE LOCK`, может быть обусловлена несколькими факторами. Рассмотрим основные из них:

1. **Конкуренция за блокировки**: Если у вас много параллельных транзакций, которые ожидают `SHARE LOCK`, это может привести к блокировке и ожиданию, что, в свою очередь, уменьшает производительность. Изучите, какие запросы часто запрашивают блокировки и как они могут зависеть друг от друга.

2. **Неоптимальные запросы**: Иногда неэффективные запросы могут вызывать множество блокировок. Используйте `EXPLAIN ANALYZE` для анализа медленных запросов и выявления неэффективных мест, которые можно оптимизировать.

3. **Индексы**: Недостаток индексов или использование неправильно выбранных индексов может привести к полному сканированию таблиц, что увеличивает время выполнения запросов и приводит к блокировкам. Убедитесь, что у вас есть соответствующие индексы на столбцах, используемых в условиях WHERE и JOIN.

4. **Параметры конфигурации**: Вы упомянули, что изменяли `max_connections`. Также стоит обратить внимание на другие параметры конфигурации, такие как `work_mem`, `shared_buffers`, и `effective_cache_size`. Неправильные настройки могут привести к плохой производительности.

5. **Долгие транзакции**: Если в вашей системе есть длительные транзакции, они могут удерживать блокировки, тем самым блокируя другие запросы. Следует отслеживать транзакции и вычислить их длительность.

6. **Наименование блокировок**: Проверьте, сколько времени запросы находятся в состоянии ожидания, используя представление `pg_stat_activity` и `pg_locks`, чтобы понять, какие блокировки вызывают задержки.

7. **Рост нагрузки**: Возможно, причиной роста числа блокировок является рост нагрузки в часы пик. Оцените возможность горизонтального масштабирования или использования кэша для снижения нагрузки на базу данных.

8. **Параллелизм**: Если возможно, используйте параллелизм для выполнения запросов. Убедитесь, что у PostgreSQL достаточно ресурсов (системных и программных), чтобы справляться с большим количеством параллельных операций.

9. **Мониторинг и диагностика**: Установите инструменты мониторинга, такие как `pgBadger`, `pg_stat_statements`, или другие, чтобы более глубоко проанализировать производительность и выявить узкие места.

Попробуйте проанализировать приведённые аспекты, чтобы выявить конкретные точки, которые могут быть причиной увеличения количества `SHARE LOCK` и низкой производительности вашей базы данных.
Вы смотрите на совершенно бесполезный график. Смотрите на полезные. 

Если у вас табличка с 10 индексами и к ней select * from foo where id = ? - то это минимум 11 AccessShareLock. Совершенно логично, что чем больше параллельно нагрузки - тем больше вы увидите AccessShareLock. И дальше куда с этим? Вот и получается совершенно бесполезный график. А задирание max_connections сделает только хуже.

Посмотрите график CPU, есть ли в принципе CPU свободный (помним что у вас наверняка есть HT, значит 100% утилизации недостижимы, реальный потолок окажется где-то в районе 70-90%)
Посмотрите графики латентности IO. Если проседает латентность чтения или записи под нагрузкой - то это будет причина замедления. СУБД очень чувствительны к латентности.
Дальше графики pg_stat_activity с разбивкой по state. Если растут idle in transaction - проверять как дела на приложении, а так же сеть.
Конечно, графики по pg_stat_statements. top5 запросов по времени выполнения, для начала.
И проверить наличие корреляции с графиком длительности самой старой транзакции.
Похожие вопросы