[PostgreSQL, Администрирование баз данных] PostgreSQL. Плохие запросы, примеры и их поиск

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
04-Фев-2021 12:32

При поиске проблем в RDBMs разработчик обычно подозревает медленные запросы. А что, если дело не в них? О том, какого типа запросы дают нагрузку на базу данных, не позволяя вашему приложению работать должным образом, рассказал в своем докладе на конференции Saint HighLoad++ Online 2020 администратор баз данных Data Egret Андрей Сальников. Он поделился тем, как backend-разработчику определять такие запросы, и каким инструментом для этого лучше воспользоваться. Особенно эти знания пригодятся в случае, если нужно найти проблемы в работающей системе здесь и сейчас, когда дорога каждая минута, а работа приложения с базой данных тормозит.
До момента всеобщей изоляции на поддержке Data Egret был сервис, на котором мастер-база держала где-то 50 тысяч транзакций в секунду.
Когда наступила изоляция, и онлайн-сервисы обрели особенную популярность, на этой базе данных компания уперлась в процессорный потолок, после чего появилось решение переехать на новое оборудование. Количество транзакций, обрабатываемых базой данных, после переезда скакнуло выше 100 тысяч в секунду, и это только на Master Server.
Что было сделано
  • Переезд базы данных и приложений на более мощные сервера, у которых больше процессоров и памяти; 
  • Увеличение количества приложений, потому что нужно обслуживать более мощную онлайн-нагрузку.
Казалось бы, все работает хорошо: конечная онлайн-нагрузка, которая идет к сервису, на тот момент увеличилась в три раза. Но увеличение транзакций вдвое выглядело подозрительным. Дело в том, что читающая нагрузка на базу данных распределена между несколькими, поэтому пишущая нагрузка, характерная для Master Server БД, растет слабо при большом росте онлайна на сервисе.В этой статье пойдет речь о том, в чем причина увеличения транзакций, и какую проблему нашли специалисты Data Egret после переезда базы данных. В первую очередь в компании обратились к данным мониторинга:
  • Среднее время выполнения запросов уменьшилось на 10 мс по сравнению с предыдущим оборудованием и предыдущей нагрузкой;
  • Сетевой трафик почти не изменился;
  • Количество запросов стало больше. Использование ресурсов трудно оценить, потому что изменилось оборудование, и однозначной оценки, больше или меньше ресурсов используется, в такой ситуации дать сложно;
  • Не получилось оценить и изменение параметров сервера. 
Вроде бы, все хорошо. Но проблема осталась не решенной. Так как речь идет о базе данных, нужно было посмотреть, что изменилось с профилем нагрузки на БД, и что случилось с запросами. Мониторинг результатов не дал. Но есть и другие инструменты. Например, pgstatstatements. В  Data Egret этот инструмент используется постоянно, так как в нем есть три приятных бонуса:
  • Отчеты за прошлые периоды обновляются каждые сутки;
  • pgstatstatements логирует абсолютно все, в том числе, частые запросы. В отличие от pgBadger, который зависит от настроек;
  • Можно оценить влияние запросов на серверные ресурсы и соответственно на базу данных, потому что БД использует серверные ресурсы (дисковая память и процессорное время).
Что же удалось обнаружить в pgstatstatements?До того, как в компании начала расти нагрузка, стандартный отчет, который формируется на основании pgstatstatements, выглядел так:
Есть общая нагрузка по количеству запросов, которая прилетела в база данных за сутки. Здесь это total queries: 3,555,539,206 (unique: 2,268).Есть специальная позиция other, в которую группируются запросы, не дающие существенную нагрузку на БД: calls: 1,977,858,485 (43.42%) avg_time: 0.06ms (IO: 33.3%).В отчете есть запросы, которые дают существенную нагрузку на базу данных, и запросы, которые несравнимо малы по сравнению с остальными. Последних почти 2 млрд. То есть больше половины запросов не дают существенную нагрузку. Эта картинка была до того, как начался режим самоизоляции. Все остальные запросы в отчете выглядят примерно так: SELECT field1, field2 FROM table1 WHERE field3 = ? and field4 between ? and ?Они несложные: какая-то выборка по простым условиям, иногда 1-2 join’а — ничего сверхъестественного, что могло бы вредить базе данных и требует нашего разбирательства.После того, как вырос онлайн, отчет изменился:
Что изменилось после начала самоизоляции
  • Время на запросы уменьшилось

В отчетах есть общее время, за которое база данных потратила больше ресурсов на выполнение запросов. В старом на это ушло 90 часов, в новом — 60. Получается, что база данных стала проводить меньше времени в запросах. На эту цифру можно ориентироваться. Почему стало лучше, понятно: изменился сервер,  стало больше памяти и меньше походов на диск. 
  • Количество запросов выросло

Общее количество запросов, которые прилетели в базу данных, стало существенно больше (примерно в 1,5 раза). Это видно на графиках.
  • Отсутствие пропорций
Если сравнивать позицию по запросам, которые не оказывают существенного влияния на БД, то тут рост не такой пропорциональный:
Казалось бы, должно быть 3 млрд запросов, но на самом деле рост всего несколько процентов. Значит, что-то изменилось в нагрузке на базу данных, и нужно смотреть отчет дальше.Смотрим вглубьПросматривая отчет, мы долистали до 17 позиции и увидели запрос, который вызывается 1,5 млрд раз и выглядит как SELECT 1:
По сути дела это пинг коннекта к базе данных, который отправляется прежде, чем приложение или пулер отправит туда запрос. Казалось бы, запрос почти не тратит ресурсов, только чуть-чуть процессорного времени. Но на самом деле он может сыграть плохую роль. На время этого пинга, мы забираем коннект от базы данных и не шлем туда полезную информацию, которая может обслуживать наш бэкенд (допустим, небольшую выборку, отрисовку веб-формы и т.д).
В итоге SELECT 1, являясь стандартным пингом коннекта, и, в то же время, приводит к негативным результатам. Ведь на время этого пинга мы:
  • Теряем возможность использовать это соединение для действительно полезного запроса;
  • Даем  лишнюю нагрузку на CPU (серверные ресурсы БД);
  • Имеем лишнюю нагрузку на сеть, потому что нам нужно пообщаться между бэкендом приложения и БД, чтобы выяснить, что произошло и доступна ли база данных. Это бестолковая трата ресурсов.
По факту произошло следующее: при переносе приложения потерялся патч на ORM, который немного срезал такие пинги.После правокДавайте посмотрим на график по количеству транзакций, после того, как были внесены правки в ORM:
Выглядит не очень впечатляюще. Подумаешь, стало на 20 тысяч транзакций меньше! Но с точки зрения процессорного времени на баунсерах, после выкатки патча стало гораздо лучше.
Можно отследить результат и по общей нагрузке:
До 4 апреля в приложении был не патченный ORM. После этого пика в 100 тысяч транзакций больше не было. База отдана только под полезные запросы, которые необходимо выполнять.Какова здесь мораль? Плохой запрос не всегда кажется таким, и не сразу можно увидеть негативный эффект с точки зрения повышенной нагрузки на дисковую и процессорную систему, или на сеть. Однако он есть.На стороне приложения это может выливаться в то, что оно не сможет отправить нужные запросы. Приложение ждет, пока проскочат все пинги. Особенно в случае, если у вас повышенная нагрузка, и она приходит волнами. Сначала прошла волна пингов, потом вы уже пустили нормальный запрос.SELECT 1 — реальный случай. На его месте могут быть более простые запросы. Например, в ситуации, когда для отрисовки веб-формы необходимо вычитывать справочники. Не смотря на то, что они дают полезную информацию, она никогда не меняется. Желательно кэшировать ее на стороне бэкенда, а не ходить за ней в базу данных.Маленькие запросы могут принести большие проблемы, которые  можно сразу не разглядеть. Мы поговорили о быстрых запросах. Теперь перейдем к мертвым.Быстрый и МертвыйВ какой-то момент на сервере базы данных резко стало использоваться много процессорного времени. Этот вариант более тривиальный с точки зрения расследования — далеко копать не надо:
План действий тот же самый:
  • Изучаем мониторинг;
  • Смотрим статистику в pgstatstatements;
  • Чиним;
  • Говорим об обнаруженной проблеме разработчикам.
Как выглядит отчет теперь?
В самой топовой позиции дается самая большая нагрузка. Исключение — other, там аккумулируется вся оставшаяся нагрузка, которая не является топовой. Он может находиться в любой позиции отчета.Сразу видим pos:1  total time: 02:05:26 (20.3%, CPU: 38.6%, IO: 2.0%). База данных тратит на этот запрос 38% процессорного времени. Допустим, мы с определенной частотой ищем в платежной системе последние транзакции, созданные по каждому платежному сервису отдельно:select distinct on (paymentsystem), * from transactions order by createdat desc;В этой ситуации запрос виден сразу, и не приходится, как в прошлом примере, листать отчет. Обычно проблема в простых запросах, которые не вызывают подозрений и на код-ревью могут  быть пропущенными в продакшн ответственным лицом.Починка будет выглядеть так:
Из маленького запроса, который работает 1 с, мы получаем большой запрос на 2 мс. Идем в комнату к разработчикам и просим их переписать запрос. Деплоим, и ситуация возвращается в привычное русло.
Отчет pgstatstatements позволяет довольно быстро находить запросы, которые портят нам жизнь. ИнструментыДавайте рассмотрим плюсы и минусы инструментов, с помощью которых мы можем существенно облегчить себе жизнь.pgBadgerПлюсы:
  • Полная информация обо всех запросах;
  • Красивые картинки. 
Посмотреть на работу pgBadger можно на тестовой странице.Минусы:
  • Специальный конфиг для логов;
  • Дополнительная нагрузка на диски, потому что количество пишущихся логов резко возрастает;
  • Анализ запросов постфактум;
  • Для pgBadger нужно большое количество места.
pgstatstatementsПлюсы:
  • Стандартное расширение PostgreSQL, идет из коробки;
Независимо от того, в какой операционной системе вы работаете, в наборе стандартных пакетов всегда найдется pgstatstatements. Его необходимо просто установить в PostgreSQL, дополнительно подключив подгрузку библиотеки pgstatstatements.
  • Собирает информацию по всем запросам;
  • Группирует одинаковые запросы;
  • Можно сбрасывать статистику;
  • Можно сделать свой отчет на основе pgstatstatements.
Минусы:
  • Оверхед на выполнение запроса 2-5%;
  • Запросы обезличенные;
Чтобы разбираться с каким-то запросом, придется все-таки включить логирование в PostgreSQL и забрать из логов запрос с параметрами, которые нужно подставлять.
  • Несущественные запросы вымываются;
  • Почти нет мониторингов, которые умеют с ним работать;
  • Не видит разницы между SELECT … и SELECT … FOR UPDATE;
  • В сыром виде данные неудобны для восприятия.
В мониторинге картинка по одному запросу выглядит следующим образом:
Такие картинки можно собирать по всем запросам, которые зафиксированы в pgstatstatements, а потом смотреть в динамике, сколько времени тратится на выполнение того или иного запроса, какие ресурсы он потребляет, как часто вызывается. Типичные проблемыКакие же проблемные запросы можно встретить на практике?Давайте рассмотрим самые распространенные из них. 
  • Результат запроса нигде не используется;
Такое может быть, если код стал неактуальным, а бэкенды забыли отключить.  Они крутятся, ходят в БД, периодически запрашивают данные по своим алгоритмам, но ничего с ними не делают. Выключив такой бэкенд, мы снизим нагрузку на базу данных.
  • Неоптимально работающий запрос;
Например, distinct. 
  • Постоянное обращение к справочникам;
Такая ситуация может возникнуть, когда мы постоянно обращаемся к справочнику пола, где у нас всего две позиции. 
  • Нехватка индексов на простеньких запросах;
Что-то задеплоили, но забыли индекс. Это можно увидеть в отчете и исправить. 
  • Смешивание нагрузки OLTP и OLAP на репликах.
Эта проблема связана с общением разработчиков с бизнес-экспертами. Последним бывает трудно объяснить, что OLAP нагрузка не может выполняться на реплике, которая отстает на 3 секунды.Если отчет выполняется 2 часа, то информация в нем уже на 2 часа устарела. Соответственно, когда одного сервера не хватает, нагрузку OLTP и OLAP нужно разделять по разным серверам.Не путайте причины проблем с запросами и с длительными транзакциями в базе данных.Когда к нам приходит разработчик и говорит, что у него тормозят запросы, дело далеко не всегда в этом. Часто речь идет о проблеме на стороне приложения: например, оно открывает долгие транзакции в базе данных.
Выглядит это так: существуют длительные транзакции, которые длятся 30-40 минут, и в это же время есть миллисекундные всплески запросов.
Если в это время посмотреть на состояние соединения в базе данных, мы увидим много простаивающих соединений (они отмечены желтым цветом):
idle in transaction — это соединение, когда приложение открыло транзакцию в БД, выполнило один запрос и ушло заниматься своими делами, забыв закрыть транзакцию. Именно это, в основном, и является первопричиной многих проблем. Как только она решается, можно заниматься тем, с чего начинается статья: искать запросы, которые мешают вам жить.Вместо заключенияОсновная цель этой статьи: донести до читателей понимание того, что мониторинг и анализ всех запросов — важная часть работы с базой данных. Правильно настроив мониторинг и проведя качественную аналитику, можно добиться хороших результатов для конечной работы сервиса. Но не стоит забывать про базовые метрики, нагрузку на cpu, диски и сеть, а также корректные настройки базы данных. Все это в совокупности даст возможность вашему проекту работать без технических проблем со стороны базы данных, а вы сможете заниматься исключительно его развитием.
Конференция HighLoad++ 2020 пройдет 20 и 21 мая 2021 года. Приобрести билеты можно уже сейчас.Хотите бесплатно получить материалы конференции мини-конференции Saint HighLoad++ 2020? Подписывайтесьна нашу рассылку.А интересующихся миром Java ждем на онлайн-митапе Luxoft TechFest #2: Java with Ontico. На нем поговорим о приватных полях-константах в Jira, неочевидных нюансах Java Reactive Stack и работе с распределенным кешем. А после своих выступлений звезды митапа ответят на самые животрепещущие из ваших вопросов. До встречи 10 февраля в 19:00 мск.

===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_postgresql, #_administrirovanie_baz_dannyh (Администрирование баз данных), #_highload++, #_postgresql, #_bazy_dannyh (базы данных), #_zaprosy (запросы), #_rdbms, #_blog_kompanii_konferentsii_olega_bunina_(ontiko) (
Блог компании Конференции Олега Бунина (Онтико)
)
, #_postgresql, #_administrirovanie_baz_dannyh (
Администрирование баз данных
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 16:14
Часовой пояс: UTC + 5