Продолжаю делиться своими размышлениями в поисках оптимального решения разных проблем производительности ИТ-систем в рамках рубрики «Мысли вслух». Напомню, размышления пока сугубо теоретические и практических подтверждений могут как иметь, так и не иметь. Но поскольку исследования проводятся, часть из них, несомненно, войдёт в будущие практические решения, часть так и останется теорией.
Хочу поднять проблему как объективно посчитать размер потребляемой оперативной памяти конкретным запросом в PostgreSQL. И предлагаю использовать для этого автоматическое нагрузочное тестирование. Такая вот сегодня постановка задачи.
В ходе недавних исследований я столкнулся с явной нехваткой стандартных инструментов для мониторинга потребления оперативной памяти запросами. На тестовой среде я моделировал сценарии с избыточным свопированием, при которых данные выгружаются из оперативной памяти на диск для освобождения ресурсов для новых процессов и данных. Это приводило к значительной деградации производительности и даже к полной остановке сервера из-за нехватки дискового пространства для свопа, что в некоторых случаях составляло сотни гигабайт.
При анализе данных мониторинга производительности я не обнаружил параметров, которые бы явно коррелировали с объемом потребляемой памяти. Это побудило меня поднять вопрос о том, как можно улучшить идентификацию "тяжелых" и "опасных" запросов для системы на основе данных мониторинга. В статье я предлагаю одно из возможных решений этой актуальной практической задачи и призываю читателей поделиться своими наблюдениями, идеями и опытом в этой области.
Если актуальная информация по данному вопросу отсутствует, но существует потенциал для решения, я предлагаю рассмотреть возможность моего финансирования исследований, оформленных в виде короткой статьи с примерами, которые можно проверить на практике.
Теперь перейду к подробному описанию ситуации, которая подтолкнула меня к выводу о том, что игнорировать данную проблему недопустимо и необходимо разработать эффективное решение.
Описание идеи
Недавно наша команда провела нагрузочные тесты распределённого вычислительного кластера, и результаты оказались весьма обнадеживающими. Однако, когда я приступил к анализу данных мониторинга производительности, то столкнулся с несколькими, на мой взгляд, критически важными проблемами.
Во время нагрузочных тестов, при увеличении интенсивности генерации запросов за счет роста числа виртуальных пользователей, мы наблюдали активное свопирование, что, в свою очередь, приводило к резкому ухудшению производительности.
Как только счетчик Swap Usage начал расти (выделен желтым), сразу видна деградация по остальным счетчикам: CPU, Кол-во запросов в секунду, очереди к диску.
Первоначально мне показалось, что запросы потребляют слишком много оперативной памяти, и я решил более внимательно изучить их. Однако, проанализировав данные мониторинга, включая метрики API от PostgreSQL и Linux, я не обнаружил явной корреляции между запросами и поведением системы. Все сценарии и запросы были известны, и система не была загружена другими процессами. Как человек, знакомый с экспериментальной физикой, я стремился к более четким зависимостям между экспериментом и его результатами. С практической точки зрения, мне хотелось научиться предсказывать поведение системы на основе данных мониторинга, поскольку полноценные нагрузочные тесты в реальных высоконагруженных системах крайне редки, если не сказать невозможны.
При более детальном рассмотрении данных мониторинга я выделил единственного кандидата на роль "виновника" проблем в плане выполнения запроса.
Как видно, используется хэш-соединение, которое, безусловно, потребляет оперативную память (но есть вероятность, что необходимый план выполнения не попал в мониторинг). Однако значение в 1,4 ГБ не соответствовало моим вычислениям. Можно было бы предположить, что вся память, выделенная под запрос, не освобождается до окончания транзакции, но это не имеет смысла. Часть памяти, возможно, не освобождается, но явно не та большая доля, которая выделяется для ускорения расчетов и хранения хэш-агрегатов. Даже в этом случае общая картина потребления памяти и запуск процессов активного свопирования не складывалась.
В результате всех этих раздумий у меня возник план практического решения этой задачи. Предположим, что мы не можем точно рассчитать объем реально потребляемой памяти и предсказать, когда она закончится, и начнется свопирование. Однако, возможно, мы можем автоматизировать этот процесс и научиться предугадывать его.
Идея заключается в следующем: с помощью мониторинга выявлять потенциально опасные запросы и затем автоматически воспроизводить их на тестовом стенде, где отсутствуют внешние факторы. Это позволит провести точные исследования и, что важно, сделать это полностью автоматизировано, своего рода нагрузочные тесты.
Формулируем более конкретную задачу: необходимо понять потребление памяти запросом. Зачем нам это? Это необходимо, чтобы знать, когда память закончится и начнутся деструктивные процессы деградации (или, в худшем случае, полная остановка системы из-за исчерпания физической памяти). Можно также задать вопрос: сколько одновременно может выполняться "опасных" запросов на сервере, прежде чем начнется свопирование? Это значение можно условно назвать "Счетчиком оценки памяти запроса Сердюка". Хотя это и шутка, но идея в том, что этот счетчик имеет конкретный физический и практический смысл.
Разумеется, есть нюансы. Эксперимент было бы некорректно проводить, если бы в PostgreSQL были механизмы оптимизации, использующие результаты ранее выполненных запросов. Проведем мысленный эксперимент: предположим, мы выполняем тяжелый запрос и получаем набор данных. Если через час мы запускаем тот же запрос, и в БД ничего не изменилось, мы можем моментально вернуть результат. Однако подобные практики оптимизации не имеют ничего общего с реальной жизнью, поэтому мы можем уверенно утверждать, что выполняя один и тот же запрос одновременно, он будет выполняться каждый раз с самого начала до конца. Единственное, что меняется, — это прогревка страниц памяти, и они после первого запроса попадут с диска в память, но это в целом не имеет значения.
Важно также понимать, что тестовый сервер может отличаться от рабочего. Более того, он и должен отличаться, поскольку это дорого и бессмысленно. Например, если на рабочем сервере установлен терабайт оперативной памяти, то в некоторых случаях потребуется запустить много запросов одновременно, чтобы достичь свопирования. Мы можем уменьшить объем оперативной памяти на тестовом стенде и затем аппроксимировать результаты.
Реализация идеи
Теперь перейдем к практической части и рассмотрим, каким образом можно реализовать эту идею. К счастью, у нашей компании уже имеются все наработки. В первую очередь нужен мониторинг для идентификации потенциально опасных запросов по их сигнатуре. Также у нас готова технология прокси, которая, хотя и вызывает небольшую просадку производительности (несколько процентов), может быть включена автоматически и опционально для захвата необходимых запросов, после чего будет отключена.
Прокси не просто фиксирует запросы, но и записывает все временные таблицы, используемые в запросе, что позволяет сохранить все сущности, необходимые для полного воспроизведения. Затем мы восстанавливаем бэкап рабочей базы данных на тестовом стенде на момент выполнения опасного запроса. После этого по заранее установленному графику запускаем N запросов на тестовом сервере (как в транзакциях, так и без них, по выбору). Далее мы постепенно увеличиваем количество запросов: N+x, N+2x и так далее, до тех пор, пока не начнется свопирование.
Мониторинг на тестовом стенде будет непрерывно отслеживать производительность и остановит процесс нагрузочного тестирования на значении N+kx, которое и станет искомым счетчиком предельного потребления памяти (Сердюка). Исходя из объема оперативной памяти на стенде, можно будет приблизительно разделить это значение на показания счетчика и получить оценку того, сколько оперативной памяти потребляет каждый запрос. Однако стоит отметить, что это значение является приблизительным, так как запрос может изменить план оптимизации и перейти в режим вложенных циклов с повышенным потреблением ЦПУ вместо памяти. Поэтому лучше рассматривать это в более широком смысле: при выполнении более чем N+kx запросов одновременно на сервере с объемом памяти Y происходит свопирование.
В результате мы получим список опасных запросов, которые могут привести к деградации производительности, без значительных трудозатрат. Кроме того, аналогичным образом можно оценивать утилизацию ЦПУ. Конечно, возможно провести все исследования вручную, но это требует значительных временных затрат, компетенции и аккуратности в исследовательской работе. В критических ситуациях, когда время идет на часы, быстро решить проблему не удается. Главное, что с помощью этих механизмов мы сможем предсказывать и предотвращать катастрофические проблемы в ИТ-системах.
Данный пример автоматизации представляет собой автоматизированный нагрузочный тест. Однако полной автоматизации в этой области мне не встречалось. Мне интересно мнение читателей: насколько это востребовано? Если это действительно интересно, то, полагаю, в течение полугода мы можем запустить эту инициативу в рамках нашего продукта мониторинга производительности.
Комментарии (31)
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Коллеги, не обессудьте. Мне хотелось бы поднять дебаты. Я рад что идет обсуждение. ЦПУ более менее понятно как считать. Не понятно как посчитать память используемую запросом? Философски даже, в каких попугаях мерять? Я предложил методику, критикуйте , предлагайте свои подходы. Но в целом вопрос стоит- как на высоконагруженных системах научится предугадывать когда настанут критические ситуации? С памятью мне не понятно, я ж писал, готов предложить написать статью и профинансировать , кто готов вложить свое время в полноценные исследования.
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)Нагрузка и характер действий конечных пользователей непредсказуем в принципе
ky0
Своп на сервере с Постгресом - последнее убежище неправильной настройки. Конечно, оно будет работать медленно.
remoteadmiral Автор
Ну в нагрузочных тестах бывает одна из задач найти предел работы системы(сервера). А с вашим утверждением согласен на 100 , когда своп это плохо и деградация. Но только вот иногда настройки ну совсем не причем, могут запросы быть неоптимальными, памяти тупо мало - никакими настройками это не решите. Хотя если вы под настройками понимаете в том числе неоптимальные запросы - ну тогда наверное да.