Продолжаю делиться своими размышлениями в поисках оптимального решения разных проблем производительности ИТ-систем в рамках рубрики «Мысли вслух». Напомню, размышления пока сугубо теоретические и практических подтверждений могут как иметь, так и не иметь. Но поскольку исследования проводятся, часть из них, несомненно, войдёт в будущие практические решения, часть так и останется теорией.
Хочу поднять проблему как объективно посчитать размер потребляемой оперативной памяти конкретным запросом в PostgreSQL. И предлагаю использовать для этого автоматическое нагрузочное тестирование. Такая вот сегодня постановка задачи.
В ходе недавних исследований я столкнулся с явной нехваткой стандартных инструментов для мониторинга потребления оперативной памяти запросами. На тестовой среде я моделировал сценарии с избыточным свопированием, при которых данные выгружаются из оперативной памяти на диск для освобождения ресурсов для новых процессов и данных. Это приводило к значительной деградации производительности и даже к полной остановке сервера из-за нехватки дискового пространства для свопа, что в некоторых случаях составляло сотни гигабайт.
При анализе данных мониторинга производительности я не обнаружил параметров, которые бы явно коррелировали с объемом потребляемой памяти. Это побудило меня поднять вопрос о том, как можно улучшить идентификацию "тяжелых" и "опасных" запросов для системы на основе данных мониторинга. В статье я предлагаю одно из возможных решений этой актуальной практической задачи и призываю читателей поделиться своими наблюдениями, идеями и опытом в этой области.
Если актуальная информация по данному вопросу отсутствует, но существует потенциал для решения, я предлагаю рассмотреть возможность моего финансирования исследований, оформленных в виде короткой статьи с примерами, которые можно проверить на практике.
Теперь перейду к подробному описанию ситуации, которая подтолкнула меня к выводу о том, что игнорировать данную проблему недопустимо и необходимо разработать эффективное решение.
Описание идеи
Недавно наша команда провела нагрузочные тесты распределённого вычислительного кластера, и результаты оказались весьма обнадеживающими. Однако, когда я приступил к анализу данных мониторинга производительности, то столкнулся с несколькими, на мой взгляд, критически важными проблемами.
Во время нагрузочных тестов, при увеличении интенсивности генерации запросов за счет роста числа виртуальных пользователей, мы наблюдали активное свопирование, что, в свою очередь, приводило к резкому ухудшению производительности.

Как только счетчик Swap Usage начал расти (выделен желтым), сразу видна деградация по остальным счетчикам: CPU, Кол-во запросов в секунду, очереди к диску.
Первоначально мне показалось, что запросы потребляют слишком много оперативной памяти, и я решил более внимательно изучить их. Однако, проанализировав данные мониторинга, включая метрики API от PostgreSQL и Linux, я не обнаружил явной корреляции между запросами и поведением системы. Все сценарии и запросы были известны, и система не была загружена другими процессами. Как человек, знакомый с экспериментальной физикой, я стремился к более четким зависимостям между экспериментом и его результатами. С практической точки зрения, мне хотелось научиться предсказывать поведение системы на основе данных мониторинга, поскольку полноценные нагрузочные тесты в реальных высоконагруженных системах крайне редки, если не сказать невозможны.
При более детальном рассмотрении данных мониторинга я выделил единственного кандидата на роль "виновника" проблем в плане выполнения запроса.

Как видно, используется хэш-соединение, которое, безусловно, потребляет оперативную память (но есть вероятность, что необходимый план выполнения не попал в мониторинг). Однако значение в 1,4 ГБ не соответствовало моим вычислениям. Можно было бы предположить, что вся память, выделенная под запрос, не освобождается до окончания транзакции, но это не имеет смысла. Часть памяти, возможно, не освобождается, но явно не та большая доля, которая выделяется для ускорения расчетов и хранения хэш-агрегатов. Даже в этом случае общая картина потребления памяти и запуск процессов активного свопирования не складывалась.
В результате всех этих раздумий у меня возник план практического решения этой задачи. Предположим, что мы не можем точно рассчитать объем реально потребляемой памяти и предсказать, когда она закончится, и начнется свопирование. Однако, возможно, мы можем автоматизировать этот процесс и научиться предугадывать его.
Идея заключается в следующем: с помощью мониторинга выявлять потенциально опасные запросы и затем автоматически воспроизводить их на тестовом стенде, где отсутствуют внешние факторы. Это позволит провести точные исследования и, что важно, сделать это полностью автоматизировано, своего рода нагрузочные тесты.
Формулируем более конкретную задачу: необходимо понять потребление памяти запросом. Зачем нам это? Это необходимо, чтобы знать, когда память закончится и начнутся деструктивные процессы деградации (или, в худшем случае, полная остановка системы из-за исчерпания физической памяти). Можно также задать вопрос: сколько одновременно может выполняться "опасных" запросов на сервере, прежде чем начнется свопирование? Это значение можно условно назвать "Счетчиком оценки памяти запроса Сердюка". Хотя это и шутка, но идея в том, что этот счетчик имеет конкретный физический и практический смысл.
Разумеется, есть нюансы. Эксперимент было бы некорректно проводить, если бы в PostgreSQL были механизмы оптимизации, использующие результаты ранее выполненных запросов. Проведем мысленный эксперимент: предположим, мы выполняем тяжелый запрос и получаем набор данных. Если через час мы запускаем тот же запрос, и в БД ничего не изменилось, мы можем моментально вернуть результат. Однако подобные практики оптимизации не имеют ничего общего с реальной жизнью, поэтому мы можем уверенно утверждать, что выполняя один и тот же запрос одновременно, он будет выполняться каждый раз с самого начала до конца. Единственное, что меняется, — это прогревка страниц памяти, и они после первого запроса попадут с диска в память, но это в целом не имеет значения.
Важно также понимать, что тестовый сервер может отличаться от рабочего. Более того, он и должен отличаться, поскольку это дорого и бессмысленно. Например, если на рабочем сервере установлен терабайт оперативной памяти, то в некоторых случаях потребуется запустить много запросов одновременно, чтобы достичь свопирования. Мы можем уменьшить объем оперативной памяти на тестовом стенде и затем аппроксимировать результаты.
Реализация идеи
Теперь перейдем к практической части и рассмотрим, каким образом можно реализовать эту идею. К счастью, у нашей компании уже имеются все наработки. В первую очередь нужен мониторинг для идентификации потенциально опасных запросов по их сигнатуре. Также у нас готова технология прокси, которая, хотя и вызывает небольшую просадку производительности (несколько процентов), может быть включена автоматически и опционально для захвата необходимых запросов, после чего будет отключена.
Прокси не просто фиксирует запросы, но и записывает все временные таблицы, используемые в запросе, что позволяет сохранить все сущности, необходимые для полного воспроизведения. Затем мы восстанавливаем бэкап рабочей базы данных на тестовом стенде на момент выполнения опасного запроса. После этого по заранее установленному графику запускаем N запросов на тестовом сервере (как в транзакциях, так и без них, по выбору). Далее мы постепенно увеличиваем количество запросов: N+x, N+2x и так далее, до тех пор, пока не начнется свопирование.
Мониторинг на тестовом стенде будет непрерывно отслеживать производительность и остановит процесс нагрузочного тестирования на значении N+kx, которое и станет искомым счетчиком предельного потребления памяти (Сердюка). Исходя из объема оперативной памяти на стенде, можно будет приблизительно разделить это значение на показания счетчика и получить оценку того, сколько оперативной памяти потребляет каждый запрос. Однако стоит отметить, что это значение является приблизительным, так как запрос может изменить план оптимизации и перейти в режим вложенных циклов с повышенным потреблением ЦПУ вместо памяти. Поэтому лучше рассматривать это в более широком смысле: при выполнении более чем N+kx запросов одновременно на сервере с объемом памяти Y происходит свопирование.
В результате мы получим список опасных запросов, которые могут привести к деградации производительности, без значительных трудозатрат. Кроме того, аналогичным образом можно оценивать утилизацию ЦПУ. Конечно, возможно провести все исследования вручную, но это требует значительных временных затрат, компетенции и аккуратности в исследовательской работе. В критических ситуациях, когда время идет на часы, быстро решить проблему не удается. Главное, что с помощью этих механизмов мы сможем предсказывать и предотвращать катастрофические проблемы в ИТ-системах.
Данный пример автоматизации представляет собой автоматизированный нагрузочный тест. Однако полной автоматизации в этой области мне не встречалось. Мне интересно мнение читателей: насколько это востребовано? Если это действительно интересно, то, полагаю, в течение полугода мы можем запустить эту инициативу в рамках нашего продукта мониторинга производительности.
Комментарии (51)
rampler
05.02.2025 14:05Мне интересно мнение читателей: насколько это востребовано?
Востребовано. В рамках работ по теме "черного ящика" для СУБД были некоторые этюды по сохранению истории утилизации RAM процессами postgres. Но дальше эскизных тестов тема не пошла. Пока отложено в долгий ящик.
remoteadmiral Автор
05.02.2025 14:05Я бы был готов даже инвестировать в исследования по этой теме, ну можно в партнерстве если есть наработки(может есть еще у кого). Меня пока, что текущее описание моделей поведения СУБД(потребления памяти), и главное предсказательная теория прям совсем не устраивают. Пишу провокационно, понимаю, ну так давайте устроим дебаты, кидайте ссылки и т.п. Только в споре рождается истина)
rampler
05.02.2025 14:05В настоящее время ведутся работы по теме анализа производительности СУБД.
Идея в следующем :
1) определяем что производительность снизилась
2) анализ причин - определение SQL запроса оказывающего максимальное влияние на деградацию производительности
3) анализ проблемного SQL запроса
4) исправление проблемы .
———
Методика, описанная в статье, начнется на шаге 3 и 4. Так, что , поживём увидим. Может и "можно в партнерстве если есть наработки".
Статья сохранена в закладках.
remoteadmiral Автор
05.02.2025 14:05Ну обращайтесь если что, так то конечно у меня например гораздо больший опыт в МSSQL, хотя там тоже много "черных ящиков", а исходников нет. Но я уже написал в другом посте свое мнение по поводу исходников, это не всегда имеет определяющее значение.
DX28
05.02.2025 14:05postgres ведь открытое по, есть код, можно скачать и подумать над ним.
remoteadmiral Автор
05.02.2025 14:05Это большое заблуждение что в открытом ПО, не может быть закладок, что оно лучше описано чем коммерческое и т.п. Найдите мне спеца по С, который мог бы читать чужой код описывать его, знает СУБД и алгоритмы оптимизации. Кто умеет хотя бы проводить эксперименты правильные. В большинстве случаев эффективней не читать код а начинать с экспериментов и потом уже включать механизмы отладки и т.п.
PorcoRosso
05.02.2025 14:05Хотелось бы видеть полный план запроса, но если речь идет о свопе скорее нужно смотреть на "temp wtitten" и "temp read". Ведь "shared hit" - это данные которые запрос нашел в кэше.
В pg_stat_statements так же можно найти полезную информацию.
remoteadmiral Автор
05.02.2025 14:05Так там она и искалась в том числе. Не получается по этой информации спрогнозировать поведение системы. Есть идеи следующую статью оформить в виде скриптов которые будут заполнять таблицы, формировать запросы и затем разобрать детальней все параметры. Но самостоятельно я это делал и не раз.
Uranic2
05.02.2025 14:05Со всем уважением, но мне кажется, автор не совсем понимает как работает posgtresql.
И начинает исследовать как ему кажется "черный ящик", и делать выводы.Все давно расписано в документации раздел "Потребление ресурсов"
https://postgrespro.ru/docs/postgresql/17/runtime-config-resourceИ настоятельно рекомендую для начала исследований
прочитать книгу "PostgreSQL 17 изнутри"
https://postgrespro.ru/education/books/internalsВсе в свободном доступе и бесплатно.
После прочтения можно вернуться к теме мониторинга с совсем другим взглядом.
Uranic2
05.02.2025 14:05Ах да, совсем забыл упомянуть PGTUNE
https://pgtune.leopard.in.ua/
или какое-нибудь зеркало типа: https://pgtune.fariton.ru/Но не забывайте, что pgtune это совсем не панацея.
Uranic2
05.02.2025 14:05И еще огорчу автора.
Боюсь что технологию, которую вы изобрели под названием "прокси, которая фиксирует запросы во временные таблицы" это вновь изобретенный велосипед на тему pg_stat_statements.
Читать здесь: https://postgrespro.ru/docs/postgresql/17/pgstatstatements
Ну а после того изучите pg_stat_statement вам откроется мир с десятком утилит и расширений которые анализируют pg_stat_statement и десятки других представлений.Пример одной из утилит: https://habr.com/ru/articles/494162/
А ребята из postgrespro уже вплотную приблизились к базовому функционалу из Oracle Enterprise Manager 15-ти летней давности: https://postgrespro.ru/products/PPEM
remoteadmiral Автор
05.02.2025 14:05Не стал я базовые вещи расписывать , дабы статью не уводить дальше от темы. Вы мне накидали ссылок, зачем? Все это не по теме. Давайте я вам приведу пример а потом задам вопрос и просьба ответьте на него конкретно а не про сферического коня в вакуме. https://postgrespro.ru/docs/postgresql/17/pgstatstatements и тому подобное могу получить интересующий нас запрос но воспроизвести в большинстве случаев его не получится. Приведу пример, 1С формирует запросы с использование временных таблиц. То есть заполняется временная таблица как правило на 1000-и записей и потом она или они используются в запросе. С помощью прокси я могу сохранить сам запрос и состояние временных таблиц и потом воспроизвести на тестовом сервере. Вопрос к вам конкретный ,приведите мне утилиту которая могла бы сохранить и затем воспроизвести полностью интересуемый запрос? Я таких не знаю, поэтому и предлагаю решение. И просьба сначала на этот вопрос ответить а потом я готов подискутировать как я не умею определять тяжелые запросы и все остальное)
Uranic2
05.02.2025 14:05Мне кажется что ЭТО ВЫ уходите от изначальной темы.
Вы просили инструменты мониторинга, я дал вам ссылки на инструменты и подходы которыми пользуются при мониторинге производительности postgresql.
При чем здесь временные таблицы?
В статье вы пишите "При анализе данных мониторинга производительности я не обнаружил параметров, которые бы явно коррелировали с объемом потребляемой памяти."
Я вам привел конкретный раздел настроек postgresql который влияет на объем оперативной памяти.
Вы пишите "Это побудило меня поднять вопрос о том, как можно улучшить идентификацию "тяжелых" и "опасных" запросов для системы на основе данных мониторинга."
Ну так pg_stat_statement и выдаст вам такую ифомрацию. Именно самые тяжелые запросы по CPU, можно по IO, можно по временным файлам, по времени выполнения и т.п.
В статье вы пишете, что делаете нагрузочное тестирование. В чем проблема повторить при нагрузочном тестировании запросы? Непонятно.
Если вы вы хотите подсмотреть запрос с параметрами, то log_statement = all in postgresql.conf
Если у вас меняются сильно планы в зависимости от параметров запроса, но есть расширение pg_stat_plans.
В статье у вас очень все поверхностно, и в комментариях вместо мониторинга нагрузки, вы уже пишете про захват и воспроизведение нагрузки (правда я не уверен что правильно вас понял).
remoteadmiral Автор
05.02.2025 14:05Мне кажется вы статью вообще не читали. Хочется универсализма. Я предложил один из подходов. Предположим есть у вас данные мониторинга. Есть запрос потребляющий память. Есть сервер с памятью Х, Сможете ли вы расчитать на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно пока не начнется свопирование? Если сможете, просьба конкретные параметры и алгоритмы в студию.
rampler
05.02.2025 14:05pg_stat_statement и выдаст вам такую ифомрацию. Именно самые тяжелые запросы по CPU
pg_stat_statements не позволяет получить отчет по утилизации CPU. только по total_exec_time .
Uranic2
05.02.2025 14:05Хм, а если так?
total_exec_time - blk_read_time - blk_write_time
И считать в процентах от общего числа...
Могу и запрос весь скинутьUranic2
05.02.2025 14:05with s AS (SELECT sum(total_exec_time) AS t, sum(blk_read_time + blk_write_time) AS iot, sum(total_exec_time - blk_read_time - blk_write_time) AS cput, sum(calls) AS s, sum(ROWS) AS r FROM pg_stat_statements WHERE TRUE), _pg_stat_statements AS ( SELECT dbid, regexp_replace(query, E'\\?(, ?\\?)+', '?') AS query, sum(total_exec_time) AS total_exec_time, sum(blk_read_time) AS blk_read_time, sum(blk_write_time) AS blk_write_time, sum(calls) AS calls, sum(ROWS) AS rows FROM pg_stat_statements WHERE TRUE GROUP BY dbid, query ) /* END WITH*/ --- запрос по основным показателям SELECT (100*total_exec_time/(SELECT t FROM s))::numeric(20, 2) AS time_percent, (100*(blk_read_time+blk_write_time)/(SELECT iot FROM s))::numeric(20, 2) AS iotime_percent, (100*(total_exec_time-blk_read_time-blk_write_time)/(SELECT cput FROM s))::numeric(20, 2) AS cputime_percent, (total_exec_time/1000)*'1 second'::interval as total_time, ((total_exec_time-blk_read_time-blk_write_time)*1000/calls)::numeric(20, 2) AS avg_cpu_time_microsecond, ((blk_read_time+blk_write_time)*1000/calls)::numeric(20, 2) AS avg_io_time_microsecond, calls, (100*calls/(SELECT s FROM s))::numeric(20, 2) AS calls_percent, rows, (100*rows/(SELECT r from s))::numeric(20, 2) AS row_percent, (select datname from pg_database where oid=dbid) as database, query FROM _pg_stat_statements WHERE (total_exec_time-blk_read_time-blk_write_time)/(SELECT cput FROM s)>= 0.05 UNION all SELECT (100*sum(total_exec_time)/(SELECT t FROM s))::numeric(20, 2) AS time_percent, (100*sum(blk_read_time+blk_write_time)/(SELECT iot FROM s))::numeric(20, 2) AS iotime_percent, (100*sum(total_exec_time-blk_read_time-blk_write_time)/(SELECT cput FROM s))::numeric(20, 2) AS cputime_percent, (sum(total_exec_time)/1000)*'1 second'::interval, (sum(total_exec_time-blk_read_time-blk_write_time)*1000/sum(calls))::numeric(10, 3) AS avg_cpu_time_microsecond, (sum(blk_read_time+blk_write_time)*1000/sum(calls))::numeric(10, 3) AS avg_io_time_microsecond, sum(calls), (100*sum(calls)/(SELECT s FROM s))::numeric(20, 2) AS calls_percent, sum(rows), (100*sum(rows)/(SELECT r from s))::numeric(20, 2) AS row_percent, 'all' as database, 'other' AS query FROM _pg_stat_statements WHERE (total_exec_time-blk_read_time-blk_write_time)/(SELECT cput FROM s)< 0.05
По желанию можно добавить остальные показатели, типа временных блоков, для себя написал утилитку, периодически борюсь с проблемными запросами в топах
rampler
05.02.2025 14:05Да хоть как. Вот эта формула точно к CPU вообще никакого отношения не имеет. Пальцем небо.
Если нужны точные данные для анализа, а не для отчетности юзерам то:
Тип
pgpro_stats_rusage
exec_rusage
pgpro_stats_rusage Статистика использования ресурсов при выполнении оператора.Расширение pgpro_stats.
Может быть еще где-то есть, я использую этот инструмент.
Хотя в последний раз когда смотрел утилизацию CPU и не помню. Потому, что как правило производительность СУБД и утилизация CPU никак не связаны.
Вернее, более строго
если производительность не снижается, а CPU растет , то это не инцидент.
если производительность снижается , а CPU растет , то это инцидент.
Uranic2
05.02.2025 14:05Да хоть как. Вот эта формула точно к CPU вообще никакого отношения не имеет. Пальцем небо.
Ну прям таки никакого?
Если время уходит не работу с диском, то на что оно уходит?
Да я знаю, что есть еще блокировки которые наверное CPU не кушают, а только "total_exec_time
". А какое еще значимое время может быть спрятано воtotal_exec_time
?Конечно можно этот показатель и переобозвать не "CPU" а назвать "other time" :)
Если нужны точные данные для анализа, а не для отчетности юзерам то:
Тип
pgpro_stats_rusage
На это я могу только облизываться. Бедны мои клиенты, не все могут позволить себе Postgres Pro Enterprise...
:(
rampler
05.02.2025 14:05Делать выводы и анализ на основании недостоверных данных - это ваш личный выбор.
Kilor
05.02.2025 14:05Как видно, используется хэш-соединение, которое, безусловно, потребляет оперативную память (но есть вероятность, что необходимый план выполнения не попал в мониторинг). Однако значение в 1,4 ГБ не соответствовало моим вычислениям. Можно было бы предположить, что вся память, выделенная под запрос, не освобождается до окончания транзакции ...
Как было сказано в соседних комментариях, вы ловите не то и "не там".
shared hit
- фактически, это "трафик" по страницам памяти, которые были прочитаны на всех итерациях по данному узлу - то есть если 100 раз прочитать одни и те же 10 страниц из памяти, то суммарно получится 1000 страниц. То есть "много читать нехорошо даже из памяти, но зато это быстро" (см. подробнее тут).
Ваша же проблема лежит ровно рядом на плане вtemp written/read
на узлеHashAggregate
- это именно внутренний "свап" PostgreSQL на диск, когда выделенной памяти не хватает на обработку данных конкретного узла. И если вы посмотрите весь план целиком, слева от этого узла будет рекомендация типа "попробуйте увеличить значениеwork_mem
".remoteadmiral Автор
05.02.2025 14:05Повторюсь.... Хочется универсализма. Я предложил один из подходов. Предположим есть у вас данные мониторинга. Есть запрос потребляющий память. Есть сервер с памятью Х, Сможете ли вы рассчитать на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно пока не начнется свопирование? Если сможете, просьба конкретные параметры и алгоритмы в студию.
Kilor
05.02.2025 14:05Проблема ровно в том, что у вас не "Есть запрос потребляющий память." Точнее, конкретно этот план не принадлежит такому запросу.
Но для решения задачи в поставленном виде "на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно" вообще не надо знать ничего про запросы. Достаточно знать, что один запрос в PG "базово" занимает все ресурсы конкретного процесса, обслуживающего соединение, а при использовании параллелизма - возможно, и несколько соседних.
То есть запускаем нагрузку в режиме 1x, снимаем пиковый занятый процессами объем памяти (
proc
), и дальше линейно масштабируем на кол-во клиентов.remoteadmiral Автор
05.02.2025 14:05Пробовал , так не работает. Там даже вопросы связанные с временным выделением памяти в очень тяжелых запросах стоят особняком. Например когда она освобождается? Вопросы с разделяемой памятью, как ее считать? Но и заметьте вы предлагаете похоже ,что и я. Проведите аккуратно эксперимент - 1х, это важно(без воздействия среды, иначе как с повторяемостью экспериментов и результатов). Но я боюсь даже в этом случае замеры и дальнейшая аппроксимация могут привести к неправильным выводам. Я же предлагаю автоматизированный практический тест.
Kilor
05.02.2025 14:05Сможете ли вы рассчитать на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно
Собственно, а каков смысл "предсказывания" результатов теста?
Если надо "убедиться, что система держит X пользователей" - тогда делаем тест эмулирующий профиль на X клиентах.
Если "проверить, какой максимум может выдержать система" - тогда делаем пошаговое увеличение X под нагрузкой, пока не начнем отлавливать деградацию любого вида.
remoteadmiral Автор
05.02.2025 14:05Нагрузочные тесты дорогие и у нас их не ценят.(мое субьективное мнение) А еще они не отображают часто динамически изменяемую нагрузку в процессе эволюции ит системы. Часто в продакшн выпускается какие то критичные обновления мимо системы нагрузочного тестирования.
remoteadmiral Автор
05.02.2025 14:05поэтому и предлагаю один из "дешевых" универсальных подходов. Смотря потом на средства мониторинга и зная что этот запрос приводил к свопирования в Х раз(одновременных запусков), а этот Х/100 - я буду четко понимать приоритеты оптимизации. Кому хватит времени и усердия проводить качественно такие эксперименты?
Kilor
05.02.2025 14:05А зачем тогда вам все эти эксперименты, если они не могут ничего доказать или опровергнуть? Вам нужен нормальный мониторинг с адекватным анализом, типа такого, если это касается PG.
remoteadmiral Автор
05.02.2025 14:05Эксперимент должен воспроизводится, это раз! Зная данные этих экспериментов выполненных системой на тестовой среде я могу сделать очень далеко идущие выводы. Доказать они могут - буквально выполненные одновременно(миниально) Х запросов (типа -Z) приводят к свопированию. Можно ли на основании этого делать вывод о потреблении памяти - ну это слишком просто(разделить и все, ну я писал), но выводы практические вполне.
Хочется иногда железобетонных гарантий)
Kilor
05.02.2025 14:05Как-то ваши утверждения про воспроизводимость экспериментов и динамически изменяющуюся нагрузку и эволюцию системы "мимо тестов" не бьются между собой.
Вы сначала определитесь, что именно вам нужно и в каких условиях.
Если "тест косвенно соотносящийся с реальной системой" - это одно, если анализ проблем на реальной системе - другое. Почти всегда эти вещи связаны не очень сильно.
Банально, представьте, что на реальной базе вам не накатили критичный индекс, а в тестовом контуре он есть - и?..
remoteadmiral Автор
05.02.2025 14:05Система меняется, нагрузочные тесты не успевают. Многопоточная, высоконагруженная система. Что в этих условиях мерять? Я предлагаю некоторые подходы которые помогают ввести какие то метрики, ничего больше. Мы с реальной системы собираем все(потенциально опасные) запросы. Воспроизводим автоматизированно на тестовой среде, без влияния других факторов. И получаем приоритезацию по их потенциальному влиянию на работу системы. Если на основании данных мониторинга это можно рассчитывать, то мои все рассуждения имеют сугубо теоретический характер.(но докажите мне, на простых примерах)
Kilor
05.02.2025 14:05Система меняется, нагрузочные тесты не успевают. Многопоточная, высоконагруженная система. Что в этих условиях мерять?
Вроде ответ скрыт в вопросе - анализировать надо саму целевую систему, а не производные от нее.
Выше я приводил ссылку на демо нашей системы анализа нагрузки в PG - можно легко понять, кто из запросов "ест диск", как часто каждый стартует, heatmap времени выполнения, ...
remoteadmiral Автор
05.02.2025 14:05Есть в математике простые вопросы типа большой теоремы ферма. Простые в формулировке, но ответить на них сложно.. Я предлагаю один из тестов по которому можно оценить практически систему мониторинга, ее оценку. Один из универсальных тестов. Не сердитесь, я в этой теме тоже разбираюсь, мое мнение отличается от мнения компании. Мне интересен вопрос с научной точки зрения. Поднимаю дискуссию, никому не хочу ничего доказывать.
remoteadmiral Автор
05.02.2025 14:05повторюсь, если на основании какой то системы мониторинга подобные вопросы можно оценивать, все мои рассуждения сводятся к нулю. Но я готов потерпеть поражение ради знаний!) ЦПУ, там более менее понятно, а с памятью много вопросов. Буду готов признать свою неправоту.
remoteadmiral Автор
05.02.2025 14:05Если вы можете на основании средств мониторинга решить эту практическую задачу(ок, пускай гипотетическую), простой универсальный эксперимент. Скажите как, я готов заплатить, ради истины даже если вы потерпите неудачу.
Kilor
05.02.2025 14:05Если под задачей понимается "мы провели какие-то тесты в одном месте, предскажите, какая будет нагрузка в других условиях в другом месте", то вряд ли кто-то ее сможет решить, кроме крайне малого количества крайних случаев.
remoteadmiral Автор
05.02.2025 14:05Ну в моем случае я уже расписывал, что неразумно делать тестовый стенд аналогичный рабочему серверу. Можно значительно уменьшить размер памяти, провести тесты и потом сделать аппроксимацию. Я надеюсь на это. Многие эксперименты я проводил на MSSQL, сознательно ограничивая память до минимума, гротеска , там было попроще. Здесь за счет виртуализации можно управлять.
remoteadmiral Автор
05.02.2025 14:05Коллеги, не обессудьте. Мне хотелось бы поднять дебаты. Я рад что идет обсуждение. ЦПУ более менее понятно как считать. Не понятно как посчитать память используемую запросом? Философски даже, в каких попугаях мерять? Я предложил методику, критикуйте , предлагайте свои подходы. Но в целом вопрос стоит- как на высоконагруженных системах научится предугадывать когда настанут критические ситуации? С памятью мне не понятно, я ж писал, готов предложить написать статью и профинансировать , кто готов вложить свое время в полноценные исследования.
Kilor
05.02.2025 14:05Если очень грубо, то на сервере у вас три лимитирующих ресурса: производительность CPU, объем RAM, пропускная способность носителя HDD/SSD (иногда еще пропускная способность сети, но очень уж нечасто).
Для предсказания нагрузки от линейного масштабирования одних и тех же "в среднем" запросов вам вообще не требуется знать, что там внутри у PG - просто измеряете %cpu, delta(proc), IOps.
К сожалению, проблемы начинаются (и сложности в предсказании) обычно из-за нелинейности масштабирования. Например:
CPU не на "железе", а на гипервизоре, который начал "душить" не в меру активного потребителя троттлингом
у диска при линейном росте IOps экспоненциально растет latency, и все ваши запросы тоже начинают дружно "тормозить"
rampler
05.02.2025 14:05Но в целом вопрос стоит- как на высоконагруженных системах научится предугадывать когда настанут критические ситуации?
Мое личное мнение на основе анализа и наблюдений за прошедшие 5 лет - предсказать невозможно.
1) СУБД по сути своей есть стохастическая система
2) СУБД в облачной инфраструктуре(сейчас самый распространенный вариант) - подвержена влиянию массы случайных и непредсказуемых факторов со стороны виртуализации
3)Современные разработчики вообще темой нагрузочного тестирования не заморачиваются, что в очередной раз вылезет со стороны приложения или backend - предсказать невозможно
4)Нагрузка и характер действий конечных пользователей непредсказуем в принципе
remoteadmiral Автор
05.02.2025 14:05Со всеми пунктами согласен. Но верю что есть способы увеличить вероятность оценок. Вот и предлагаю универсальные новые подходы, пускай меня и критикуют. Что то срабатывает, что то нет. Напоминаю , эта статья родилась после серии нагрузочных тестов.
cmyser
05.02.2025 14:05Поздравляю, вы придумали трейсинг )
remoteadmiral Автор
05.02.2025 14:05А что это такое?) хотя я уже вроде описывал ситуацию. Дайте утилиту, которая по сигнатуре запроса будет собирать запрос, и самое главное все связанные структуры заполненные ранее, типа временных таблиц. и потом будет воспроизводить. Этого нет, буду рад ошибаться
JGooLaaR
05.02.2025 14:05БД с какого вида нагрузкой вообще? Олап или олтп? Процесс модет не отдать память после завершения работы запроса. Борьба за память на постгрес многогранная и одним анализом запросов не ограничивается. Предсказывать сколько памяти зохавает запрос сложно, но можно. Не очень понятно зачем понимание сколько запросов можно сунуть. Нагрузка так сильно однородна?
remoteadmiral Автор
05.02.2025 14:05ОЛТП, система. Но с другой стороны в ОЛТП системах видел запросы Dynamic SQL по 4 GB текст запроса) Понятно что транзакционная модель с сериализацией обязывает "держать в уме" какое то количество памяти. Транзакции смотрел, закрываются. но в моменте может быть N открытых транзакций. Но идея в другом, хочется некоторых универсальных подходов. Про разделяемую память в постгри это отдельная история, специально не стал начинать с этого обсуждение иначе холивар был бы обеспечен.
ky0
Своп на сервере с Постгресом - последнее убежище неправильной настройки. Конечно, оно будет работать медленно.
remoteadmiral Автор
Ну в нагрузочных тестах бывает одна из задач найти предел работы системы(сервера). А с вашим утверждением согласен на 100 , когда своп это плохо и деградация. Но только вот иногда настройки ну совсем не причем, могут запросы быть неоптимальными, памяти тупо мало - никакими настройками это не решите. Хотя если вы под настройками понимаете в том числе неоптимальные запросы - ну тогда наверное да.