Продолжаю делиться своими размышлениями в поисках оптимального решения разных проблем производительности ИТ-систем в рамках рубрики «Мысли вслух». Напомню, размышления пока сугубо теоретические и практических подтверждений могут как иметь, так и не иметь. Но поскольку исследования проводятся, часть из них, несомненно, войдёт в будущие практические решения, часть так и останется теорией.

Хочу поднять проблему как объективно посчитать размер потребляемой оперативной памяти конкретным запросом в PostgreSQL. И предлагаю использовать для этого автоматическое нагрузочное тестирование. Такая вот сегодня постановка задачи.

В ходе недавних исследований я столкнулся с явной нехваткой стандартных инструментов для мониторинга потребления оперативной памяти запросами. На тестовой среде я моделировал сценарии с избыточным свопированием, при которых данные выгружаются из оперативной памяти на диск для освобождения ресурсов для новых процессов и данных. Это приводило к значительной деградации производительности и даже к полной остановке сервера из-за нехватки дискового пространства для свопа, что в некоторых случаях составляло сотни гигабайт.

При анализе данных мониторинга производительности я не обнаружил параметров, которые бы явно коррелировали с объемом потребляемой памяти. Это побудило меня поднять вопрос о том, как можно улучшить идентификацию "тяжелых" и "опасных" запросов для системы на основе данных мониторинга. В статье я предлагаю одно из возможных решений этой актуальной практической задачи и призываю читателей поделиться своими наблюдениями, идеями и опытом в этой области.

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

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

Описание идеи

Недавно наша команда провела нагрузочные тесты распределённого вычислительного кластера, и результаты оказались весьма обнадеживающими. Однако, когда я приступил к анализу данных мониторинга производительности, то столкнулся с несколькими, на мой взгляд, критически важными проблемами.

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

Как только счетчик Swap Usage начал расти (выделен желтым), сразу видна деградация по остальным счетчикам: CPU, Кол-во запросов в секунду, очереди к диску.

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

При более детальном рассмотрении данных мониторинга я выделил единственного кандидата на роль "виновника" проблем в плане выполнения запроса.

Как видно, используется хэш-соединение, которое, безусловно, потребляет оперативную память (но есть вероятность, что необходимый план выполнения не попал в мониторинг). Однако значение в 1,4 ГБ не соответствовало моим вычислениям. Можно было бы предположить, что вся память, выделенная под запрос, не освобождается до окончания транзакции, но это не имеет смысла. Часть памяти, возможно, не освобождается, но явно не та большая доля, которая выделяется для ускорения расчетов и хранения хэш-агрегатов. Даже в этом случае общая картина потребления памяти и запуск процессов активного свопирования не складывалась.

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

Идея заключается в следующем: с помощью мониторинга выявлять потенциально опасные запросы и затем автоматически воспроизводить их на тестовом стенде, где отсутствуют внешние факторы. Это позволит провести точные исследования и, что важно, сделать это полностью автоматизировано, своего рода нагрузочные тесты.

Формулируем более конкретную задачу: необходимо понять потребление памяти запросом. Зачем нам это? Это необходимо, чтобы знать, когда память закончится и начнутся деструктивные процессы деградации (или, в худшем случае, полная остановка системы из-за исчерпания физической памяти). Можно также задать вопрос: сколько одновременно может выполняться "опасных" запросов на сервере, прежде чем начнется свопирование? Это значение можно условно назвать "Счетчиком оценки памяти запроса Сердюка". Хотя это и шутка, но идея в том, что этот счетчик имеет конкретный физический и практический смысл.

Разумеется, есть нюансы. Эксперимент было бы некорректно проводить, если бы в PostgreSQL были механизмы оптимизации, использующие результаты ранее выполненных запросов. Проведем мысленный эксперимент: предположим, мы выполняем тяжелый запрос и получаем набор данных. Если через час мы запускаем тот же запрос, и в БД ничего не изменилось, мы можем моментально вернуть результат. Однако подобные практики оптимизации не имеют ничего общего с реальной жизнью, поэтому мы можем уверенно утверждать, что выполняя один и тот же запрос одновременно, он будет выполняться каждый раз с самого начала до конца. Единственное, что меняется, — это прогревка страниц памяти, и они после первого запроса попадут с диска в память, но это в целом не имеет значения.

Важно также понимать, что тестовый сервер может отличаться от рабочего. Более того, он и должен отличаться, поскольку это дорого и бессмысленно. Например, если на рабочем сервере установлен терабайт оперативной памяти, то в некоторых случаях потребуется запустить много запросов одновременно, чтобы достичь свопирования. Мы можем уменьшить объем оперативной памяти на тестовом стенде и затем аппроксимировать результаты.

Реализация идеи

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

Прокси не просто фиксирует запросы, но и записывает все временные таблицы, используемые в запросе, что позволяет сохранить все сущности, необходимые для полного воспроизведения. Затем мы восстанавливаем бэкап рабочей базы данных на тестовом стенде на момент выполнения опасного запроса. После этого по заранее установленному графику запускаем N запросов на тестовом сервере (как в транзакциях, так и без них, по выбору). Далее мы постепенно увеличиваем количество запросов: N+x, N+2x и так далее, до тех пор, пока не начнется свопирование.

Мониторинг на тестовом стенде будет непрерывно отслеживать производительность и остановит процесс нагрузочного тестирования на значении N+kx, которое и станет искомым счетчиком предельного потребления памяти (Сердюка). Исходя из объема оперативной памяти на стенде, можно будет приблизительно разделить это значение на показания счетчика и получить оценку того, сколько оперативной памяти потребляет каждый запрос. Однако стоит отметить, что это значение является приблизительным, так как запрос может изменить план оптимизации и перейти в режим вложенных циклов с повышенным потреблением ЦПУ вместо памяти. Поэтому лучше рассматривать это в более широком смысле: при выполнении более чем N+kx запросов одновременно на сервере с объемом памяти Y происходит свопирование.

В результате мы получим список опасных запросов, которые могут привести к деградации производительности, без значительных трудозатрат. Кроме того, аналогичным образом можно оценивать утилизацию ЦПУ. Конечно, возможно провести все исследования вручную, но это требует значительных временных затрат, компетенции и аккуратности в исследовательской работе. В критических ситуациях, когда время идет на часы, быстро решить проблему не удается. Главное, что с помощью этих механизмов мы сможем предсказывать и предотвращать катастрофические проблемы в ИТ-системах.

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

Комментарии (31)


  1. ky0
    05.02.2025 14:05

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


    1. remoteadmiral Автор
      05.02.2025 14:05

      Ну в нагрузочных тестах бывает одна из задач найти предел работы системы(сервера). А с вашим утверждением согласен на 100 , когда своп это плохо и деградация. Но только вот иногда настройки ну совсем не причем, могут запросы быть неоптимальными, памяти тупо мало - никакими настройками это не решите. Хотя если вы под настройками понимаете в том числе неоптимальные запросы - ну тогда наверное да.


  1. rampler
    05.02.2025 14:05

    Мне интересно мнение читателей: насколько это востребовано? 

    Востребовано. В рамках работ по теме "черного ящика" для СУБД были некоторые этюды по сохранению истории утилизации RAM процессами postgres. Но дальше эскизных тестов тема не пошла. Пока отложено в долгий ящик.


    1. remoteadmiral Автор
      05.02.2025 14:05

      Я бы был готов даже инвестировать в исследования по этой теме, ну можно в партнерстве если есть наработки(может есть еще у кого). Меня пока, что текущее описание моделей поведения СУБД(потребления памяти), и главное предсказательная теория прям совсем не устраивают. Пишу провокационно, понимаю, ну так давайте устроим дебаты, кидайте ссылки и т.п. Только в споре рождается истина)


      1. rampler
        05.02.2025 14:05

        В настоящее время ведутся работы по теме анализа производительности СУБД.

        Идея в следующем :

        1) определяем что производительность снизилась

        2) анализ причин - определение SQL запроса оказывающего максимальное влияние на деградацию производительности

        3) анализ проблемного SQL запроса

        4) исправление проблемы .

        ———

        Методика, описанная в статье, начнется на шаге 3 и 4. Так, что , поживём увидим. Может и "можно в партнерстве если есть наработки".

        Статья сохранена в закладках.


        1. remoteadmiral Автор
          05.02.2025 14:05

          Ну обращайтесь если что, так то конечно у меня например гораздо больший опыт в МSSQL, хотя там тоже много "черных ящиков", а исходников нет. Но я уже написал в другом посте свое мнение по поводу исходников, это не всегда имеет определяющее значение.


      1. DX28
        05.02.2025 14:05

        postgres ведь открытое по, есть код, можно скачать и подумать над ним.


        1. remoteadmiral Автор
          05.02.2025 14:05

          Это большое заблуждение что в открытом ПО, не может быть закладок, что оно лучше описано чем коммерческое и т.п. Найдите мне спеца по С, который мог бы читать чужой код описывать его, знает СУБД и алгоритмы оптимизации. Кто умеет хотя бы проводить эксперименты правильные. В большинстве случаев эффективней не читать код а начинать с экспериментов и потом уже включать механизмы отладки и т.п.


  1. PorcoRosso
    05.02.2025 14:05

    Хотелось бы видеть полный план запроса, но если речь идет о свопе скорее нужно смотреть на "temp wtitten" и "temp read". Ведь "shared hit" - это данные которые запрос нашел в кэше.

    В pg_stat_statements так же можно найти полезную информацию.


    1. remoteadmiral Автор
      05.02.2025 14:05

      Так там она и искалась в том числе. Не получается по этой информации спрогнозировать поведение системы. Есть идеи следующую статью оформить в виде скриптов которые будут заполнять таблицы, формировать запросы и затем разобрать детальней все параметры. Но самостоятельно я это делал и не раз.


  1. Uranic2
    05.02.2025 14:05

    Со всем уважением, но мне кажется, автор не совсем понимает как работает posgtresql.
    И начинает исследовать как ему кажется "черный ящик", и делать выводы.

    Все давно расписано в документации раздел "Потребление ресурсов"
    https://postgrespro.ru/docs/postgresql/17/runtime-config-resource

    И настоятельно рекомендую для начала исследований
    прочитать книгу "PostgreSQL 17 изнутри"
    https://postgrespro.ru/education/books/internals

    Все в свободном доступе и бесплатно.

    После прочтения можно вернуться к теме мониторинга с совсем другим взглядом.


    1. Uranic2
      05.02.2025 14:05

      Ах да, совсем забыл упомянуть PGTUNE
      https://pgtune.leopard.in.ua/
      или какое-нибудь зеркало типа: https://pgtune.fariton.ru/

      Но не забывайте, что pgtune это совсем не панацея.


  1. 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


    1. remoteadmiral Автор
      05.02.2025 14:05

      Не стал я базовые вещи расписывать , дабы статью не уводить дальше от темы. Вы мне накидали ссылок, зачем? Все это не по теме. Давайте я вам приведу пример а потом задам вопрос и просьба ответьте на него конкретно а не про сферического коня в вакуме. https://postgrespro.ru/docs/postgresql/17/pgstatstatements и тому подобное могу получить интересующий нас запрос но воспроизвести в большинстве случаев его не получится. Приведу пример, 1С формирует запросы с использование временных таблиц. То есть заполняется временная таблица как правило на 1000-и записей и потом она или они используются в запросе. С помощью прокси я могу сохранить сам запрос и состояние временных таблиц и потом воспроизвести на тестовом сервере. Вопрос к вам конкретный ,приведите мне утилиту которая могла бы сохранить и затем воспроизвести полностью интересуемый запрос? Я таких не знаю, поэтому и предлагаю решение. И просьба сначала на этот вопрос ответить а потом я готов подискутировать как я не умею определять тяжелые запросы и все остальное)


      1. Uranic2
        05.02.2025 14:05

        Мне кажется что ЭТО ВЫ уходите от изначальной темы.

        Вы просили инструменты мониторинга, я дал вам ссылки на инструменты и подходы которыми пользуются при мониторинге производительности postgresql.

        При чем здесь временные таблицы?

        В статье вы пишите "При анализе данных мониторинга производительности я не обнаружил параметров, которые бы явно коррелировали с объемом потребляемой памяти."

        Я вам привел конкретный раздел настроек postgresql который влияет на объем оперативной памяти.

        Вы пишите "Это побудило меня поднять вопрос о том, как можно улучшить идентификацию "тяжелых" и "опасных" запросов для системы на основе данных мониторинга."

        Ну так pg_stat_statement и выдаст вам такую ифомрацию. Именно самые тяжелые запросы по CPU, можно по IO, можно по временным файлам, по времени выполнения и т.п.

        В статье вы пишете, что делаете нагрузочное тестирование. В чем проблема повторить при нагрузочном тестировании запросы? Непонятно.

        Если вы вы хотите подсмотреть запрос с параметрами, то log_statement = all in postgresql.conf

        Если у вас меняются сильно планы в зависимости от параметров запроса, но есть расширение pg_stat_plans.

        В статье у вас очень все поверхностно, и в комментариях вместо мониторинга нагрузки, вы уже пишете про захват и воспроизведение нагрузки (правда я не уверен что правильно вас понял).




        1. remoteadmiral Автор
          05.02.2025 14:05

          Мне кажется вы статью вообще не читали. Хочется универсализма. Я предложил один из подходов. Предположим есть у вас данные мониторинга. Есть запрос потребляющий память. Есть сервер с памятью Х, Сможете ли вы расчитать на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно пока не начнется свопирование? Если сможете, просьба конкретные параметры и алгоритмы в студию.


        1. rampler
          05.02.2025 14:05

          pg_stat_statement и выдаст вам такую ифомрацию. Именно самые тяжелые запросы по CPU

          pg_stat_statements не позволяет получить отчет по утилизации CPU. только по total_exec_time .


          1. Uranic2
            05.02.2025 14:05

            Хм, а если так?
            total_exec_time - blk_read_time - blk_write_time

            И считать в процентах от общего числа...
            Могу и запрос весь скинуть


            1. Uranic2
              05.02.2025 14:05

              Да я понимаю, что это не совсем точно CPU , но для оценки в % вполне подойдет.


              1. rampler
                05.02.2025 14:05

                в DBA нужна точность, математика и цифры полученные и подтвержденные экспериментально, а не гадания на кофейной гуще.


            1. Uranic2
              05.02.2025 14:05

              with 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
              
              
              

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


            1. rampler
              05.02.2025 14:05

              Да хоть как. Вот эта формула точно к CPU вообще никакого отношения не имеет. Пальцем небо.

              Если нужны точные данные для анализа, а не для отчетности юзерам то:

              Тип pgpro_stats_rusage 

              exec_rusagepgpro_stats_rusage Статистика использования ресурсов при выполнении оператора.

              Расширение pgpro_stats.

              Может быть еще где-то есть, я использую этот инструмент.

              Хотя в последний раз когда смотрел утилизацию CPU и не помню. Потому, что как правило производительность СУБД и утилизация CPU никак не связаны.

              Вернее, более строго

              • если производительность не снижается, а CPU растет , то это не инцидент.

              • если производительность снижается , а CPU растет , то это инцидент.


              1. Uranic2
                05.02.2025 14:05

                Да хоть как. Вот эта формула точно к CPU вообще никакого отношения не имеет. Пальцем небо.

                Ну прям таки никакого?
                Если время уходит не работу с диском, то на что оно уходит?

                Да я знаю, что есть еще блокировки которые наверное CPU не кушают, а только "total_exec_time". А какое еще значимое время может быть спрятано во total_exec_time?

                Конечно можно этот показатель и переобозвать не "CPU" а назвать "other time" :)

                Если нужны точные данные для анализа, а не для отчетности юзерам то:

                Тип pgpro_stats_rusage 

                На это я могу только облизываться. Бедны мои клиенты, не все могут позволить себе Postgres Pro Enterprise...

                :(


                1. rampler
                  05.02.2025 14:05

                  Делать выводы и анализ на основании недостоверных данных - это ваш личный выбор.


  1. Kilor
    05.02.2025 14:05

    Как видно, используется хэш-соединение, которое, безусловно, потребляет оперативную память (но есть вероятность, что необходимый план выполнения не попал в мониторинг). Однако значение в 1,4 ГБ не соответствовало моим вычислениям. Можно было бы предположить, что вся память, выделенная под запрос, не освобождается до окончания транзакции ...

    Как было сказано в соседних комментариях, вы ловите не то и "не там".

    shared hit - фактически, это "трафик" по страницам памяти, которые были прочитаны на всех итерациях по данному узлу - то есть если 100 раз прочитать одни и те же 10 страниц из памяти, то суммарно получится 1000 страниц. То есть "много читать нехорошо даже из памяти, но зато это быстро" (см. подробнее тут).
    Ваша же проблема лежит ровно рядом на плане в temp written/read на узле HashAggregate - это именно внутренний "свап" PostgreSQL на диск, когда выделенной памяти не хватает на обработку данных конкретного узла. И если вы посмотрите весь план целиком, слева от этого узла будет рекомендация типа "попробуйте увеличить значение work_mem".


    1. remoteadmiral Автор
      05.02.2025 14:05

      Повторюсь.... Хочется универсализма. Я предложил один из подходов. Предположим есть у вас данные мониторинга. Есть запрос потребляющий память. Есть сервер с памятью Х, Сможете ли вы рассчитать на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно пока не начнется свопирование? Если сможете, просьба конкретные параметры и алгоритмы в студию.


      1. Kilor
        05.02.2025 14:05

        Проблема ровно в том, что у вас не "Есть запрос потребляющий память." Точнее, конкретно этот план не принадлежит такому запросу.

        Но для решения задачи в поставленном виде "на основании данных мониторинга плюс минус сколько таких запросов можно выполнить одновременно" вообще не надо знать ничего про запросы. Достаточно знать, что один запрос в PG "базово" занимает все ресурсы конкретного процесса, обслуживающего соединение, а при использовании параллелизма - возможно, и несколько соседних.

        То есть запускаем нагрузку в режиме 1x, снимаем пиковый занятый процессами объем памяти (proc), и дальше линейно масштабируем на кол-во клиентов.


        1. Uranic2
          05.02.2025 14:05

          О! многоуважаемый @Kilor подтянулся. Но боюсь автору даже он не сможет помочь :)


  1. remoteadmiral Автор
    05.02.2025 14:05

    Коллеги, не обессудьте. Мне хотелось бы поднять дебаты. Я рад что идет обсуждение. ЦПУ более менее понятно как считать. Не понятно как посчитать память используемую запросом? Философски даже, в каких попугаях мерять? Я предложил методику, критикуйте , предлагайте свои подходы. Но в целом вопрос стоит- как на высоконагруженных системах научится предугадывать когда настанут критические ситуации? С памятью мне не понятно, я ж писал, готов предложить написать статью и профинансировать , кто готов вложить свое время в полноценные исследования.


    1. Kilor
      05.02.2025 14:05

      Если очень грубо, то на сервере у вас три лимитирующих ресурса: производительность CPU, объем RAM, пропускная способность носителя HDD/SSD (иногда еще пропускная способность сети, но очень уж нечасто).

      Для предсказания нагрузки от линейного масштабирования одних и тех же "в среднем" запросов вам вообще не требуется знать, что там внутри у PG - просто измеряете %cpu, delta(proc), IOps.

      К сожалению, проблемы начинаются (и сложности в предсказании) обычно из-за нелинейности масштабирования. Например:

      • CPU не на "железе", а на гипервизоре, который начал "душить" не в меру активного потребителя троттлингом

      • у диска при линейном росте IOps экспоненциально растет latency, и все ваши запросы тоже начинают дружно "тормозить"


    1. rampler
      05.02.2025 14:05

      Но в целом вопрос стоит- как на высоконагруженных системах научится предугадывать когда настанут критические ситуации?

      Мое личное мнение на основе анализа и наблюдений за прошедшие 5 лет - предсказать невозможно.

      1) СУБД по сути своей есть стохастическая система

      2) СУБД в облачной инфраструктуре(сейчас самый распространенный вариант) - подвержена влиянию массы случайных и непредсказуемых факторов со стороны виртуализации

      3)Современные разработчики вообще темой нагрузочного тестирования не заморачиваются, что в очередной раз вылезет со стороны приложения или backend - предсказать невозможно

      4)Нагрузка и характер действий конечных пользователей непредсказуем в принципе