Пока два алхимика выясняют, какая магия опаснее, инженер ставит эксперимент.
Пока два алхимика выясняют, какая магия опаснее, инженер ставит эксперимент.

⚠️Официальное предупреждение (дисклеймер)⚠️

Настоящая статья подготовлена с использованием технологий искусственного интеллекта.

В частности:

— экспериментальные данные обработаны и проанализированы нейросетью;

— иллюстративный материал, сопутствующие слоганы, а также предисловие и послесловие сгенерированы нейросетью;

— макет статьи редактировался и корректировался нейросетью.

Лицам, придерживающимся позиции «ИИ-веганства» (испытывающим устойчивый страх, неприязнь или психологический дискомфорт по отношению к нейросетевым системам), настоятельно не рекомендуется ознакомление с содержанием данной публикации, равно как и участие в её обсуждении, во избежание возможного нанесения вреда психологическому благополучию.


Max: PG_EXPECTO

GitHub - Комплекс pg_expecto для статистического анализа производительности и нагрузочного тестирования СУБД PostgreSQL

GitFlic - pg_expecto - статистический анализ производительности и ожиданий СУБД PostgreSQL

Глоссарий терминов | Postgres DBA | Дзен

В ходе исследования влияния ошибочной конфигурации СУБД PostgreSQL (применение OLAP-параметров в OLTP-среде и OLTP-параметров в OLAP-среде) выявлена проблема современных нейронных сетей: при идентичном запросе двум ИИ-моделям получены противоположные выводы о критичности указанных настроек. Данный факт свидетельствует, что попытка однозначной оценки без учёта архитектурных особенностей и эмпирической проверки неизбежно приводит к противоречивым заключениям.


Содержание


1. Пролог.

"Ask Postgres"

Компания Postgres Professional представила участникам конференции PGConf.СПб нового интеллектуального помощника Ask Postgres, созданного на базе технологий искусственного интеллекта для работы с опенсорс-продуктом PostgreSQL и коммерческими продуктами семейства Postgres Pro. Чат-бот умеет быстро находить нужную информацию в массивах документации PostgreSQL и Postgres Pro и упрощает работу с базами данных, переводя запросы с естественного языка в SQL. Решение имеет удобный веб-интерфейс и функциональность.

В отличие от открытых решений по работе с документацией PostgreSQL, Ask Postgres интегрирует ИИ в коммерческий продукт Postgres Pro, а также поддерживает методологию MCP (Model Context Protocol). Подобных решений с такой глубокой интеграцией и возможностью реальной работы с базами данных на российском рынке пока не существует. Это делает Ask Postgres одним из первых интеллектуальных ассистентов в области управления данными, ориентированным на практическое применение.

Postgres Professional представила нового ИИ-помощника Ask Postgres

"DeepSeek"

▼Что такое DeepSeek?

DeepSeek — продвинутый AI-ассистент на базе передовых моделей глубокого обучения. Даёт умные ответы для диалогов, кода, письма, анализа и многого другого — с мощным рассуждением и пониманием контекста.

▼Чем DeepSeek отличается?

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

DeepSeek в действии

2. Преамбула - вопрос нейросети

Какая ошибка в определении профиля нагрузки влечет большее влияние на снижение производительности СУБД - конфигурационные параметры СУБД рекомендованные для OLAP для профиля нагрузки OLTP или конфигурационные параметры СУБД рекомендованные для OLTP для профиля OLAP ?

3. Ответ нейросети "Ask Postgres"

Использование настроек OLAP для профиля OLTP влечет значительно большее негативное влияние на производительность и корректность работы СУБД, чем обратная ситуация.

Полный ответ "Ask Postgres":

Ask Postgres - OLAP или OLTP | Postgres DBA | Дзен

4. Ответ нейросети "DeepSeek"

Конфигурационные параметры СУБД, рекомендованные для OLTP, при профиле нагрузки OLAP (второй вариант) влекут за собой, как правило, более серьезное влияние на снижение производительности, вплоть до полной невозможности выполнения запросов.

Полный ответ "DeepSeek":

DeepSeek - OLAP или OLTP | Postgres DBA | Дзен

5. Часть-1: Постановка эксперимента

Имитация профилей нагрузки OLTP-OLAP в ходе нагрузочного тестирования

PG_EXPECTO v.7+DeepSeek: Статистическая обработка данных и формирование сравнительных отчетов OLTP vs OLAP. | Postgres DBA | Дзен

Нагрузка на СУБД

6. Подготовка конфигурационных параметров СУБД для заданного профиля нагрузки:

pgpro_tune : утилита командной строки для автоматической настройки. Оптимальные значения различных параметров конфигурации Postgres Pro зависят от оборудования. Утилита pgpro_tune собирает информацию о системе и преобразует её в набор параметров, записываемых в файл конфигурации.

Подготовка конфигурации рекомендованной для OLTP

Вопрос нейросети "Ask Postgres"

Подготовь инструкцию по применению pgpro_tune по следующим входным данным : CPU = 8 , RAM = 8GB , Тип нагрузки = OLTP , Платформа = Linux , Диски=SSD , Версия PostgreSQL = 17.

Ответ нейросети:

Запустите утилиту с указанием каталога данных и предустановки по умолчанию:

pgpro_tune -D /var/lib/postgresql/17/main

Конфигурация рекомендованная для OLTP

#OLTP… | Postgres DBA | Дзен

Подготовка конфигурации рекомендованной для OLAP

Вопрос нейросети "Ask Postgres"

Подготовь инструкцию по применению pgpro_tune по следующим входным данным : CPU = 8 , RAM = 8GB , Тип нагрузки = OLAP , Платформа = Linux , Диски=SSD , Версия PostgreSQL = 17.

Ответ нейросети:

Поскольку pgpro_tune не имеет встроенных пресетов для OLAP, необходимо создать кастомный пресет с учетом рекомендаций для аналитических систем.

Создание кастомного пресета olap.tune

Создайте файл olap.tune в директории, например /opt/postgrespro/presets/:

mkdir -p /opt/postgrespro/presets

nano /opt/postgrespro/presets/olap.tune

Применение пресета

pg_ctl stop -D /path/to/your/data/directory

pgpro_tune \

--pgdata /path/to/your/data/directory \

--preset /opt/postgrespro/presets/olap.tune \

--no-default

pg_ctl start -D /path/to/your/data/directory

Конфигурация рекомендованная для OLAP

# OLAP workload preset for Postgres Pro 17 # System: 8 CPU, 8GB RAM, SSD… | Postgres DBA | Дзен

7. Эксперимент-1: профиль нагрузки, имитирующий OLTP.

Сценарии нагрузочного тестирования

Сценарий-1(SELECT)
-- scenario1.sql OLTP SELECT
CREATE OR REPLACE FUNCTION scenario1() RETURNS integer AS $$
DECLARE
 test_rec record ;
 min_i bigint ;
 max_i bigint ;
 current_aid bigint ;
 current_tid bigint ;
 current_bid bigint ;
 current_delta bigint ;
 counter bigint;
BEGIN
---------------------------------------------------
--СЦЕНАРИЙ 1 - SELECT
min_i = 1 ;
SELECT MAX(aid) INTO max_i FROM pgbench_accounts ;
current_aid = floor(random() * (max_i - min_i + 1)) + min_i ;
select br.bbalance
into test_rec
from pgbench_branches br
join pgbench_accounts acc on (br.bid = acc.bid )
where acc.aid = current_aid ;
--СЦЕНАРИЙ 1 - SELECT ONLY
---------------------------------------------------
return 0 ;
END
$$ LANGUAGE plpgsql;
Сценарий-2(INSERT)
-- scenario2.sql OLTP INSERT
CREATE OR REPLACE FUNCTION scenario2() RETURNS integer AS $$
DECLARE
 min_i bigint ;
 max_i_aid bigint ;
 max_i_tid bigint ;
 max_i_bid bigint ;
 current_aid bigint ;
 current_tid bigint ;
 current_bid bigint ;
 counter integer ;
BEGIN
min_i = 1 ;
SELECT MAX(aid) INTO max_i_aid FROM pgbench_accounts ;
SELECT MAX(tid) INTO max_i_tid FROM pgbench_tellers ;
SELECT MAX(bid) INTO max_i_bid FROM pgbench_branches ;
FOR counter IN 1..10
LOOP
current_aid = floor(random() * (max_i_aid - min_i + 1)) + min_i ;
current_tid = floor(random() * (max_i_tid - min_i + 1)) + min_i ;
current_bid = floor(random() * (max_i_bid - min_i + 1)) + min_i ;
INSERT INTO pgbench_history (
tid,
bid,
aid,
delta,
mtime ,
filler ,
random_fill )
VALUES (
current_tid ,
current_bid ,
current_aid ,
random() * 1000.0 ,
CURRENT_TIMESTAMP ,
'1234567890123456789000',
random() * 1000.0 );
END LOOP ;
 return 0 ;
END
$$ LANGUAGE plpgsql;
Сценарий-3(UPDATE)
-- scenario3.sql OLTP UPDATE
CREATE OR REPLACE FUNCTION scenario3() RETURNS integer AS $$
DECLARE
 min_i bigint ;
 max_i bigint ;
 current_aid bigint ;
 current_delta bigint ;
 counter integer;
BEGIN
  -- Атомарный выбор и блокировка одной строки с пропуском заблокированных
  -- Используем LIMIT 1 и FOR UPDATE SKIP LOCKED для выбора одной доступной строки
min_i = 1 ;
SELECT MAX(aid) INTO max_i FROM pgbench_accounts ;
FOR counter IN 1..10
LOOP
-- Генерация случайного сдвига
current_delta := (ROUND(RANDOM())::BIGINT) * 10 + 1;
current_aid = floor(random() * (max_i - min_i + 1)) + min_i ;
SELECT aid INTO current_aid
FROM pgbench_accounts
WHERE aid = current_aid
FOR UPDATE SKIP LOCKED;
-- Если строка найдена — обновляем её
IF current_aid IS NOT NULL THEN
UPDATE pgbench_accounts
SET abalance = abalance + current_delta
WHERE aid = current_aid;
END IF;
END LOOP;
 return 0 ;
END
$$ LANGUAGE plpgsql;

Операционная скорость СУБД

Рис.1 - сравнительный график изменения операционной скорости СУБД в ходе нагрузочного тестирования.

Средняя разница операционной скорости составила ≈1%(максимальная разница ≈3%).

Ожидания СУБД

Рис.2 - сравнительный график изменения ожиданий СУБД в ходе нагрузочного тестирования.

️Средняя разница ожиданий СУБД составило ≈2%.

Итог

Предполагаемое несоответствие профиля нагрузки OLTP и рекомендуемой конфигурации СУБД, в целом не оказало существенного влияния на производительность СУБД, в ходе данного эксперимента .

8. Эксперимент-2: профиль нагрузки, имитирующий OLAP.

Сценарии нагрузочного тестирования

Сценарий-1(SELECT)
-- scenario1.sql OLAP SELECT
CREATE OR REPLACE FUNCTION scenario1() RETURNS integer AS $$
DECLARE
 test_rec record ;
BEGIN
WITH
branch_summary AS (
SELECT
b.bid,
COUNT(a.aid) as account_count,
SUM(a.abalance) as total_balance,
AVG(a.abalance) as avg_balance
FROM pgbench_branches b
LEFT JOIN pgbench_accounts a ON b.bid = a.bid
GROUP BY b.bid
),
transaction_summary AS (
SELECT
h.bid,
COUNT(*) as transaction_count,
SUM(h.delta) as net_flow,
COUNT(DISTINCT h.aid) as active_accounts,
MIN(h.mtime) as first_transaction,
MAX(h.mtime) as last_transaction
FROM pgbench_history h
WHERE h.mtime > CURRENT_TIMESTAMP - INTERVAL '7 days'
GROUP BY h.bid
)
SELECT
bs.bid,
bs.account_count,
bs.total_balance,
bs.avg_balance,
COALESCE(ts.transaction_count, 0) as transaction_count,
COALESCE(ts.net_flow, 0) as net_flow,
COALESCE(ts.active_accounts, 0) as active_accounts,
EXTRACT(DAY FROM ts.last_transaction - ts.first_transaction) as activity_days,
CASE
WHEN ts.transaction_count > 0
THEN bs.total_balance / ts.transaction_count
ELSE 0
END as balance_per_transaction
INTO test_rec
FROM branch_summary bs
LEFT JOIN transaction_summary ts ON bs.bid = ts.bid
WHERE bs.total_balance > 0
ORDER BY bs.total_balance DESC
LIMIT 100;
return 0 ;
END
$$ LANGUAGE plpgsql;
Сценарий-2(INSERT)
-- scenario2.sql OLAP INSERT
CREATE OR REPLACE FUNCTION scenario2() RETURNS integer AS $$
DECLARE
 min_i bigint ;
 max_i bigint ;
 current_aid bigint ;
 current_tid bigint ;
 current_bid bigint ;
 counter integer ;
BEGIN
min_i = 1 ;
SELECT MAX(aid) INTO max_i FROM pgbench_accounts ;
current_aid = floor(random() * (max_i - min_i + 1)) + min_i ;
SELECT MAX(tid) INTO max_i FROM pgbench_tellers ;
current_tid = floor(random() * (max_i - min_i + 1)) + min_i ;
SELECT MAX(bid) INTO max_i FROM pgbench_branches ;
current_bid = floor(random() * (max_i - min_i + 1)) + min_i ;
INSERT INTO pgbench_history (
tid,
bid,
aid,
delta,
mtime ,
filler )
VALUES (
current_tid ,
current_bid ,
current_aid ,
random() * 1000.0 ,
CURRENT_TIMESTAMP ,
'1234567890123456789000');
 return 0 ;
END
$$ LANGUAGE plpgsql;
Сценарий-3(UPDATE)
-- scenario3.sql OLAP UPDATE
CREATE OR REPLACE FUNCTION scenario3() RETURNS integer AS $$
DECLARE
 min_i bigint ;
 max_i bigint ;
 current_aid bigint ;
 current_delta bigint ;
BEGIN
-- Генерация случайного сдвига
  current_delta := (ROUND(RANDOM())::BIGINT) * 10 + 1;
  -- Атомарный выбор и блокировка одной строки с пропуском заблокированных
  -- Используем LIMIT 1 и FOR UPDATE SKIP LOCKED для выбора одной доступной строки
min_i = 1 ;
SELECT MAX(aid) INTO max_i FROM pgbench_accounts ;
current_aid = floor(random() * (max_i - min_i + 1)) + min_i ;
  SELECT aid INTO current_aid
  FROM pgbench_accounts
  WHERE aid = current_aid
  FOR UPDATE SKIP LOCKED;
  -- Если строка найдена — обновляем её
  IF current_aid IS NOT NULL THEN
   UPDATE pgbench_accounts
   SET abalance = abalance + current_delta
   WHERE aid = current_aid;
  END IF;
 return 0 ;
END
$$ LANGUAGE plpgsql;

Операционная скорость СУБД

Рис.3 - сравнительный график изменения ожидания СУБД в ходе нагрузочного тестирования.

Средняя разница операционной скорости составила ≈1%.

Ожидания СУБД

Рис.4 - сравнительный график изменения ожиданий СУБД в ходе нагрузочного тестирования.

Средняя разница ожиданий СУБД составила ≈2%.

Итог

Предполагаемое несоответствие профиля нагрузки OLAP и рекомендуемой конфигурации СУБД, в целом не оказало существенного влияния на производительность СУБД, в ходе данного эксперимента .

9. Общий вывод

В экспериментах установлено, что применение конфигурационных параметров СУБД, оптимизированных для OLAP, в OLTP-среде, а также параметров OLTP в OLAP-среде, для условий данного эксперимента- не приводит к существенному снижению производительности: отклонения операционной скорости и времени ожидания в обоих случаях не превысили 3%, что опровергает исходные предположения о критическом влиянии ошибочного выбора профиля нагрузки на эффективность работы PostgreSQL.

10. Часть-2: Цена умозрительности

️Представленные результаты интересны не только с точки зрения практического администрирования PostgreSQL. За сухими цифрами экспериментов скрывается более глубокая, фундаментальная проблема, лежащая на стыке инженерии данных и современных методов искусственного интеллекта.

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

Две модели, «Ask Postgres» и «DeepSeek», вынесли диаметрально противоположные вердикты. Одна утверждает, что фатальным является навязывание OLAP-настроек OLTP-нагрузке, другая настаивает на критичности обратной ситуации.

🔴С точки зрения формальной логики, обе модели не могут быть правы одновременно.

🔴С точки зрения инженерной практики, ни одна из них не была права изначально.

Почему это произошло? Потому что нейросеть, в отличие от квалифицированного эксперта-инженера или DBA, не обладает критической функцией «отказа от экспертизы» в условиях неполноты данных.

Или другими словами, поставленная задача - классический пример задачи о сферическом коне в вакууме.

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

Инженер, перед которым поставлен вопрос о выборе профиля конфигурации, будет действовать по протоколу научного метода:

1. Фиксация неопределенности: «Неизвестны параметры окружения, версия ядра, характеристики СХД, специфика нагрузки ...».

2. Отказ от спекуляций: «Без натурных испытаний и нагрузочного тестирования, на вашем конкретном оборудовании , вашей конкретной схеме данных и вашем конкретном профиле нагрузке - дать однозначную оценку невозможно».

3. Эмпирическая проверка: запуск нагрузки и получение метрик производительности и ожиданий СУБД. Анализ результатов , формирование и проверка гипотез.

Нейросеть же, архитектурно стремясь к кооперативности и завершенности ответа, вынуждена дать ответ. У нее нет права сказать «Я не знаю» в том смысле, как это делает человек, осознающий свою ответственность за последствия применения рекомендации. Она генерирует наиболее ➡вероятную⬅ комбинацию слов, основанную на обучающей выборке, где зачастую перемешаны форумные домыслы, устаревшие руководства для версий 9.x и узкоспециализированные кейсы.

Проведенные эксперименты — это классический «инженерный тест Тьюринга».

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

Вывод, который следует из этой работы, выходит за рамки особенностей конфигурирования OLAP и OLTP:

Пока мы имеем дело с системами, где цена ошибки высока (целостность данных, время простоя), использование «чистого» ИИ без жесткого контроля со стороны инженера не просто бесполезно — оно опасно💥. Фундаментальная проблема и принципиальное ограничение нейросети в том, что нейросеть не способна оценить полноту или недостаточность вводных данных.

Там, где эксперт скажет: «Подождите, я не вижу половины переменных, давайте-ка проведем нагрузочное тестирование», — нейросеть даст красивый, уверенный, но потенциально разрушительный для производительности СУБД ответ.

Cтатья ценна именно как демонстрация победы эмпирики над умозрительностью.

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

11. Часть-3: Как минимизировать риски при использовании нейросетей для настройки СУБД

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

Однако последствия этой особенности можно свести к минимуму, внедрив несколько жёстких инженерных правил.

1. Запрет на «слепое» выполнение рекомендаций ИИ

Любой совет нейросети по изменению параметров СУБД (shared_buffers, work_mem, autovacuum и т.д.) должен рассматриваться исключительно как гипотеза, а не как инструкция. До применения в продуктивной среде, гипотеза в обязательном порядке должна проходит:

  • верификацию через актуальную документацию конкретной версии PostgreSQL;

  • ➡проверку на тестовом стенде с максимально идентичной нагрузкой и оборудованием.⬅

2. Использование техники «инженерного допроса» нейросети

Поскольку нейросеть не способна самостоятельно оценить полноту вводных, эту оценку должен делать человек. Перед тем как задать вопрос о конфигурации, инженер обязан явно перечислить модели известные ей неизвестные. Например: «У меня нет данных о частоте контрольных точек, размере оперативной памяти, типе дискового массива, версии PostgreSQL и характере транзакций. При таких условиях любые рекомендации будут спекулятивны. Подтверждаешь ли ты, что твой ответ не учитывает эти переменные?» Такой запрос не заставит нейросеть отказаться от ответа (из-за архитектуры ей это сложно), но переведёт диалог в режим, где модель сама начнёт оговаривать допущения — что уже снижает риск.

3. Внедрение «защитного барьера» — обязательное нагрузочное тестирование

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

4. Сегментация задач: ИИ — для разведки, человек — для ответственности

Нейросеть можно безопасно использовать для:

  • генерации первичных вариантов конфигурации «на подумать»;

  • объяснения смысла параметров (как интерактивный справочник);

  • поиска синтаксических ошибок в скриптах.

Но принятие окончательного решения о применении той или иной настройки, оценка полноты данных и «подпись» под изменением конфигурации остаются исключительно за инженером, который несёт ответственность за целостность и доступность базы данных.⚠️

От гипотезы к решению: документация → стенд → нагрузка → подпись.
От гипотезы к решению: документация → стенд → нагрузка → подпись.

12. Эпилог

Итог одной фразой: Компенсация архитектурного недостатка нейросетей (невозможности отказа от ответа при неполных данных) достигается не их доработкой, а обязательной эмпирической верификацией, без которой применение ИИ в администрировании СУБД представляет собой опасную иллюзию экспертизы, а с ней — полезный, хотя и ограниченный генератор идей.

P.S. Перекрёстный допрос или как нейросеть сама себя опровергает

Нейросеть опровергает себя: эксперимент с экспертизой | Postgres DBA | Дзен


Анонс следующей статьи

В этой статье мы разбираем реальный инцидент деградации производительности PostgreSQL 15.14: операционная скорость СУБД упала, ожидания выросли, а стандартные графики Zabbix лишь фиксировали симптомы, но не указывали на первопричину. Для расследования мы применили двухэтапную методологию: сначала системный промпт PG_EXPECTO провёл статистический корреляционный анализ метрик (vmstat, iostat, pg_stat_statements, ожидания), выявив доминирование IO-блокировок, насыщение диска vdb по IOPS и конкретный queryid, генерирующий 89% нагрузки. Затем философская инструкция Philosophical_instruction_v3.5_beta переработала полученные выводы через эпистемологический фильтр: каждый тезис прошёл проверку источником и свежестью, получил светофор уверенности (🟢🟡🔴⬛), а также процедуры CoVe, ToT, Pre-Mortem и Red Teaming — чтобы итоговый отчёт был максимально правдивым, защищённым от галлюцинаций и честно фиксировал как доказанные факты, так и области неизвестного. Результат — объективная диагностика инцидента с чёткими рекомендациями и списком недостающих данных для дальнейшей оптимизации.

PG_EXPECTO + Philosophical_instruction_v3.5_beta: двойной анализ инцидента PostgreSQL | Postgres DBA | Дзен