惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
量子位
腾讯CDC
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
B
Blog
S
SegmentFault 最新的问题
P
Privacy & Cybersecurity Law Blog
T
Threatpost
博客园 - 聂微东
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
C
Check Point Blog
N
Netflix TechBlog - Medium
D
DataBreaches.Net
爱范儿
爱范儿
IT之家
IT之家
S
Secure Thoughts
M
MIT News - Artificial intelligence
NISL@THU
NISL@THU
C
Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
有赞技术团队
有赞技术团队
A
Arctic Wolf
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
Schneier on Security
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
G
GRAHAM CLULEY
雷峰网
雷峰网
Project Zero
Project Zero
博客园 - Franky
H
Heimdal Security Blog
A
About on SuperTechFans
Security Latest
Security Latest
Webroot Blog
Webroot Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Как мы тестируем Tantor Postgres для 1С от нагрузочных тестов до оптимизаций планировщика
Tantor · 2026-06-24 · via Все публикации подряд на Хабре

Tantor Postgres 18 - масштабный релиз СУБД, за которым стоят месяцы тестирования, сотни часов нагрузочных прогонов и десятки исправлений, о которых пользователь никогда не узнает просто потому, что они были найдены и устранены до выхода версии. Александр Симонов, руководитель направления развития 1С в "Тантор Лабс", рассказывает, как устроен процесс тестирования изнутри, почему одного "эталонного" прогона недостаточно, что делать, когда ванильный PostgreSQL 18 ломает собственные оптимизации, и как Tantor Postgres приближается к той планке, которую MS SQL Server держал годами.

Процесс тестирования релизов

Расскажите в целом, как выглядит процесс тестирования нового релиза Tantor Postgres перед выпуском?

А.С. - Все начинается задолго до выпуска - мы тестируем фичи, которые войдут в 18 версию, на версии предыдущей. Разработчик берет последний релиз 17 версии, накатывает на него тестируемую фичу, и отдает нам в центр экспертизы 1С на тест. Например, управление моделью оценки кардинальности мы начали тестировать еще прошлым летом. Изначально у нас было целых четыре модели для сравнения. Ранний старт тестов позволил нам провести тщательный анализ того, где хорошо, а где плохо показывает себя каждая модель оценки кардинальности, и в итоге до финального релиза дошло только две (а две другие модели показали на реальных базах 1С нестабильные результаты и были исключены). Таким образом, мы на 17 версии проверили примерно половину фич, который вошли в версию 18. Это значительно упрощает тестирование 18 версии, ведь часть работы уже проделана.

Следующий этап - тестирование alpha-версии 18й версии. Это самый ответственный этап, ведь на поведение планировщика могут влиять изменения в ванильной версии, и нередко это происходит не в лучшую сторону. Здесь мы новую версию стабилизируем: находим ошибки и проблемы планировщика, исправляем их, чтобы убедиться что все корректно работает. Также тестируем новые фичи, которые не протестировали на 17 версии, и тестируем всё вместе, чтобы исключить конфликты и обеспечить оптимальную работу. 

Затем выходит beta-версия 18, по сути релиз-кандидат. Как правило, alpha- и beta-версии выходят как разные минорные релизы. Мы делаем финальные прогоны нагрузочных тестов. Цель - проверить на качество и производительность, исключить ошибки при включении всех фич и при различных вариантах настроек, убедиться, что не осталось ключевых операций, которые бы не ускорились, а замедлились. Качество и производительность мы проверяем на всех этапах.

Какие именно нагрузочные тесты вы запускаете? Что за конфигурации 1С, какое железо, сколько пользователей?

Наш нагрузочный стенд и некоторые тесты уже мелькали в наших статьях по 1С. Если говорить более подробно, то тестовый стенд специально выделен только под тестирование Tantor Postgres под 1С:

Роль сервера

Количество

OC

Версия ПО

Кол-во CPU

Кол-во RAM (Гб)

Сервер лицензирования 1С

1

Astra Linux 1.7.5

1С Предприятие 8.3.27.1719

4

16

Сервер приложений 1С

3

Astra Linux 1.7.5

1С Предприятие 8.3.27.1719

32

126 

Терминальный сервер 

10

Astra Linux 1.7.5

1С Предприятие 8.3.27.1719

16

64

Сервер СУБД

1

Astra Linux 1.8.1

Tantor SE 1C 18.x

48

512

Мониторинг

1

Astra Linux 1.7.5

Платформа Tantor 6.x

4

16

Кластер серверов 1С состоит из четырех серверов: сервер лицензирования, один центральный и два рабочих. Клиенты нагрузочного теста запускаются на десяти терминальных серверах. Эти ресурсы, само собой, целиком задейстсованы не всегда, на некоторых тестах достаточно одного сервера приложений и двух терминальных. А если запускаем тест на 2-3 тысячи пользователей, то здесь уже используем все ресурсы. Со стороны СУБД у нас один сервер, реплика подключается в том случае, когда в ней есть необходимость, допустим, хотим проверить что-то связанное с репликацией или работой механизма копий баз данных 1С. 

Нагрузочных тестов у нас несколько:

Конфигурация

Размер базы (Гб)

Количество пользователей

Продолжительность теста (ч)

ERP 2.5

646

349

1 час

ERP 2.5

646

1 (Закрытие месяца/расчет себестоимости)

2 часа

ERP 2.5

1273

3200

10 часов

Документооборот 2.1

210

362

3 часа

ЗУП 3.1

50

276

2 часа

Почему так много тестов? Разве недостаточно одного эталонного прогона?

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

Тест "Закрытие месяца" отличается тем, что в нем в рамках одного соединения с СУБД постоянно создается огромное количество временных таблиц и большое разнообразие запросов к ним. На этом тесте очень показательно тестировать оптимизации, связанные с временными таблицами, например, их параллелизм.

Первые два теста проходят на одной и той же базе, затем переходим к более длительным тестам - ЗУП и Документооборот (ДО). В ЗУП нас встречают регистры расчета, которых нет в других тестируемых конфигурациях, а в ДО активно используются бизнес-процессы. 

Последний нагрузочный тест - опять на ERP, но уже на другой базе. Здесь мы задействуем все серверы тестового стенда, чтобы проверить работу нескольких тысяч пользователей. Его, как правило, запускаем на ночь или в выходные, а с утра анализируем результаты. 

Полный цикл тестирования мажорного релиза занимает у нас 2-3 месяца, а минорного - 2-4 недели. Таким образом, ситуация, когда клиент обновился на новый релиз Tantor Postgres и 1С-система у него начала деградировать, для нас априори исключена.

Как мы разбираем, что изменилось

Как вы обнаруживаете, что какая-то операция стала работать медленнее? Что является "сигналом тревоги"?

Все просто: сравниваем 2 результата нагрузочного теста, так сказать, "до" и "после", и находим в этом сравнении операции, которые деградировали. Например:

Как видите, среднее время всех ключевых операций стало лучше на 3,1%, но это не значит, что все хорошо. Красным выделены ключевые операции, время выполнения которых замедлилось, а зеленым - которых ускорилось.

На корректность сравнения также влияют еще несколько факторов:

  1. Не было ли в ходе нагрузочного теста узким местом оборудование. Например, если CPU на сервере приложений или СУБД был утилизирован на 80–90% или наблюдались кратковременные пики до 100%, результаты такого теста сравнивать некорректно: среднее время многих операций окажется хуже эталонного не по вине СУБД, а из-за банальной нехватки ресурсов - смежной нагрузки на хосте виртуализации или других внешних факторов. Такие результаты мы не засчитываем, разбираемся в их причинах и повторяем тест.

  2. Ключевая операция должна выполниться в ходе теста не менее ста раз. Если операция выполнялась редко, её среднее время сильно подвержено случайным выбросам: одно-два аномально долгих выполнения могут существенно исказить итоговую цифру. При 100+ выполнениях такие выбросы сглаживаются, и среднее становится статистически значимым.

Как выглядит процесс разбора конкретной деградации от момента обнаружения до решения?

Здесь процесс одинаков независимо от того, ищем ли мы деградацию или ускорение. 

  1. На входе у нас - исследуемая ключевая операция.

  2. Включаем логирование: сбор планов запросов более 100 мс, и сбор запросов в технологическом журнале с такой же длительностью.

  3. Выполняем ключевую операцию в однопользовательском режиме в окружениях "до" и "после". В примере выше это будет на SE 1C 17.7 и SE 1C 18.1.

  4. Анализируем лог, начинаем смотреть тот, где ключевая операция выполнялась дольше, ищем самые длительные по времени запросы.

  5. Сравниваем их с логом, где ключевая операция выполнялась быстрее - таким образом находим запросы, скорость выполнения которых изменилась.

  6. Сравниваем планы этого запроса при разном окружении - здесь уже понимаем причины, почему запрос стал выполняться дольше/быстрее. В большинстве случаев причины видны уже на этом шаге, но иногда планы идентичны. Тогда анализируем события ожидания и профиль выполнения глубже.

  7. Если поведение ожидаемое, т.е. мы ожидали ускорение, то на этом расследование заканчивается - мы понимаем, что запрос ускорился благодаря конкретной фиче.

  8. Если же запрос деградировал, то ставим задачу на разработку СУБД разобраться, какие изменения в исходном коде Tantor Postgres повлияли. Готовим разработчику мини-дамп базы, чтобы он мог воспроизвести данный запрос в своей среде разработки, а не на тестовом сервере.

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

Выше вы говорили, что изменения из ванильного PostgreSQL 18 сделали что-то хуже в контексте 1С. Можете привести конкретные примеры? 

Да, здесь было несколько примеров. При первом тесте на базе ERP длительностью 1 час мы увидели несколько ключевых операций, которые стали выполняться дольше, при этом, на общий APDEX это почти не повлияло. А вот на другом нагрузочном тесте на базе ERP длительностью 10 часов мы уже получили APDEX на 15% хуже, чем на 17 версии Tantor Postgres. Повлияло в ванили вот что. У планировщика запросов есть такое понятие как RTEKind - это внутренняя "метка" в PostgreSQL, которая говорит планировщику, с чем именно он сейчас работает в запросе. Разбирая SQL-запрос, он встречает разные "источники данных" - это может быть обычная таблица, подзапрос, CTE (WITH-выражение), результат JOIN-а и так далее. Каждому такому источнику присваивается тип - это и есть RTEKind (Range Table Entry Kind, то есть "тип записи в таблице диапазонов"). В 18 версии появился новый RTEKind -  RTE_GROUP. Наши оптимизации об этом ничего не знали, в результате планировщик воспринимал RTE_GROUP как независимое отношение и считал предикаты некоррелированными, стал сильно ошибаться с оценкой количества строк и выбирать неоптимальные планы.

Исправление на первый взгляд оказалось простым, но найти корень проблемы потребовало времени: добавить RTE_GROUP в ту же проверку, где обрабатываются подзапросы и прочие «нетабличные» отношения. После этого планировщик снова стал корректно учитывать корреляцию и выбирать оптимальный план.

Следующий случай был связан с io_method, который появился в 18 версии. Его можно установить в значение sync, т.е. также как было в версии 17, но запрос последовательного сканирования большой таблицы (20+ млн записей) стал выполняться на 10% медленнее. Анализ собранных утилитой perf данных показал, что в 18 версии синхронное чтение работает медленнее из-за того, что появился дополнительный оверхед нового AIO-слоя (staging, управление структурами io_uring/AIO). При этом если включить асинхронное чтение (io_method = worker), то последовательное чтение такой таблицы выполняется быстрее, чем на 17 версии.

Также мы портировали из 19 версии оптимизацию eager aggregate. Мы постоянно смотрим "по сторонам", чтобы найти какие-то интересные оптимизации планировщика, которые позволят сделать нашу СУБД лучше. В ходе тестирования выяснили, что модель оценки стоимости этой оптимизации требует доработки под 1С, т.к. она использовалась в том числе там, где ее использование было неоправданным. Проблема проявлялась в запросах, где планировщик до этого выбирал оптимальный индекс и читал минимальное количество записей. После включения оптимизации он начинал использовать менее подходящий индекс и вычитывать значительно больше записей, рассчитывая сократить итоговую выборку за счёт eager aggregate, но в итоге получая обратный эффект.

В итоге после доработок APDEX вернулся на уровень 17 версии. Важно понимать, что это лишь один из этапов тестирования, на котором мы оцениваем влияние изменений ванильного PostgreSQL на наши оптимизации под 1С и устраняем возникшие проблемы.

А есть изменения из ванильного PostgreSQL 18 которые сделали что-то лучше?

Да, такие примеры тоже есть. Index Skip Scan ускоряет запросы, в которых пропущен предикат по одному из первых полей индекса. Вместо полного сканирования индекса планировщик итеративно находит возможные значения пропущенного поля и использует их как дополнительное условие, фактически перепрыгивая через незаданный предикат. В 1С такие запросы встречаются часто, и эффект может быть очень заметным: на наших тестах один из запросов ускорился в 250 раз - с 3 секунд до 13 мс - на том же индексе и без каких-либо изменений в самом запросе. Однако у этой оптимизации есть указанный в исходном коде недостаток: она исходит из пессимистического сценария и предполагает, что естественной корреляции между столбцами не существует, что для 1С не всегда хорошо. На нагрузочных тестах мы нашли один запрос, который из-за этого стал выполняться дольше. Пока оставили как есть, поставив задачу на анализ и доработку.

Также изменилась логика использования узла Memoize - нагрузочные тесты показали несколько случаев, где он перестал использоваться, потому что его применение ранее было ошибочным (Hits: 0, то есть кеш не давал никакого эффекта). Отказ от такого узла ускорил часть запросов, но, что удивительно, часть замедлил. Объясняется это просто: раньше планировщик случайно выбирал более быстрый план. Теперь план стал правильным, но чуть медленнее. Мы расцениваем это как приемлемый компромисс и оставили поведение как есть - правильнее здесь работать над качеством статистики, чтобы планировщик изначально имел меньше шансов ошибиться.

Как вы разграничиваете: это баг ванильного PostgreSQL, ваша собственная проблема или баг платформы 1С?

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

От проблемы - к фиче

Как вообще рождается задача на оптимизацию? Это жалоба клиента, результат теста или что-то ещё?

Чаще всего задача исходит из разбора кейса клиента, но есть и другие инициаторы задач на оптимизацию. Я бы описал процесс такой блок-схемой:

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

Разбор результатов нагрузочных тестов - как внутренних, так и внешних с подрядчиками, - тоже помогает находить идеи, где и что можно улучшить. Например, разбирая длительные запросы нагрузочного теста на 30 тыс. пользователей, мы наткнулись на шаблон запроса, который был топ-1 по общей длительности. Оптимизировать его было довольно просто, если бы была возможность переписать текст запроса. Мы научили наш планировщик делать это, и правильность выбранного пути подтвердилась тем, что такая же техника была реализована в MS SQL и Oracle - см. материал "Оптимизация дизъюнктивных подзапросов".

Что касается идей разработчиков и R&D, то на мой взгляд, работа разработчика СУБД - это в каком-то отношении постоянное R&D, потому что PostgreSQL - сложная инженерная система, где каждое изменение должно соответствовать высоким стандартам сообщества. Чтобы добавить одну оптимизацию планировщика, нужно глубоко понимать, как взаимодействуют десятки подсистем: как строится дерево запроса, как работает оценка стоимости, как принимаются решения об использовании индексов, параллелизма, материализации. Поэтому прежде чем написать первую строчку кода по задаче, разработчик тратит время на изучение того, как устроена та или иная часть ядра, какие у неё ограничения и почему она работает именно так, изучает треды на PostgreSQL Hackers (pgsql-hackers), смотрит, не предпринималось ли попыток решить подобную задачу. В случае задач 1С - это еще более обширное R&D потому, что некоторые задачи решены в MS SQL или Oracle, и многие их решения описаны в патентах или научных статьях, которые требуется изучить. Например, идея автоматического создания статистики как раз и была получена в результате такого исследования. 

Также у нас есть выделенное R&D-подразделение, и в части 1С мы работаем с ними над рядом фундаментальных задач, но об этом отдельный разговор.

Можете привести свежий пример — от момента «что-то пошло не так» до готовой фичи в релизе?

Да, приведу пример как раз из 18 релиза. На одной из наших тестовых баз ERP при выполнении закрытия месяца воспроизводился запрос длительностью 10 минут. По плану запроса было видно, что планировщик при выборе плана не учитывает то, сколько строк ему придется отфильтровать при поиске в индексе (большое значение Rows Removed by Filter). Здесь возникает задача в Jira с примером неоптимального запроса, но в разработку ее пока не отдаем.

В ходе различных нагрузочных тестов и обращений клиентов возникают еще подобные планы запроса с такой же характерной проблемой. Мы обогащаем нашу задачу новыми примерами, чтобы подтвердить, что решается не какой-то один частный кейс, а действительно часто встречающаяся проблема. А когда у одного из клиентов обнаружился аналогичный запрос со временем выполнения 3 часа, а на MS SQL он выполнялся менее минуты - приоритет задачи вырос сам собой.

Следующий этап - это анализ задачи разработчиком, поиск решения. по сути R&D. Мы нашли решение в pgsql-hackers, опробовали его, и оно действительно решило проблему исходного запроса, но не все кейсы. К тому же, на нагрузочных тестах оно показало плохие результаты, поскольку повлекло деградацию выполнения части запросов. Во время проведения нагрузочных тестов появилась другая идея для решения этой проблемы. Мы обсудили ее с разработкой, реализовали, убедились в том, что она решает все кейсы, описанные в исходной задаче, и не приводит к деградации других запросов. Так появилась оптимизация "Изменение логики расчета стоимости операций Index/Bitmap index scan". Стоит отметить, что нагрузочные тесты позволяют подбирать оптимальные значения новых параметров планировщика - в данном случае это был cpu_filter_cost, влияющий на расчёт стоимости плана запроса.

Как вы решаете, что оптимизацию нужно реализовывать в СУБД, а не советовать клиенту переписать запрос или перенастроить 1С?

Базовый принцип - клиент не должен подстраиваться под СУБД. Если запрос корректен с точки зрения логики 1С и на MS SQL работал быстро, то просить клиента переписывать его означает перекладывать на него нашу работу. Поэтому мы всегда сначала ищем решение на стороне СУБД, и только если запрос объективно написан плохо, даём рекомендации по его улучшению. Всё остальное зависит от конкретной ситуации: если видим, что SQL-запрос написан явно неоптимально, то запрашиваем у клиента текст запроса на языке 1С и даём рекомендации, как его переписать. Если же в запросе переписывать нечего, например, конфигурация типовая и находится на поддержке, или на MS SQL тот же запрос работал быстро - проводим анализ, как помочь клиенту без изменения запроса. Иногда достаточно скорректировать настройки СУБД, если они не были выставлены согласно нашим рекомендациям. Но оптимальный вариант в таких случаях - получить обезличенный дамп таблиц, участвующих в запросе, воспроизвести проблему на своём стенде и проработать варианты решения. Если получить дамп невозможно - воспроизводим запрос на своих тестовых базах согласно логике плана запроса, с опытом это не составляет труда. Лично мне, в этом хорошо помогает ИИ: по некоторым планам запроса, если правильно объяснить проблематику, он неплохо справляется с генерацией тестовых данных и подготовкой сценариев воспроизведения.

Сравнение с MS SQL Server

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

Сам факт того, что MS SQL в каких-то сценариях работает быстрее - это нормально, мы не питаем иллюзий: MS SQL разрабатывается десятилетиями, и за это время его планировщик вырос до очень высокого уровня. За ним стоят годы научных исследований и сотни опубликованных работ. Однако было бы странно получить такой кейс от клиента и ничего с этим не сделать. Главная задача моего подразделения - из каждого кейса клиента генерировать вопрос "а что мы можем улучшить в нашей СУБД?" и конкретный практический ответ на него. На текущий момент по этим двум кейсам у нас в тестировании находятся оптимизации, и они попадут в следующий минорный релиз Tantor Postgres 18.x.

В чём главный принцип, к которому вы стремитесь при работе под 1С? Как он соотносится с подходом MS SQL?

Главный принцип - "настроил и забыл", то есть также как было в MS SQL. При работе с MS SQL не было такого паттерна поведения, что планировщик может быть в чем-то не прав, и требуется его доработка или изменение настроек. Конечно, если миграцию с MS SQL сопровождает эксперт 1С - проводится нагрузочное тестирование, анализируются и оптимизируются долгие запросы - то риски того, что после миграции потребуется что-то донастраивать или переписывать, значительно снижаются. Но такие миграции скорее исключение, чем правило. Поэтому мы активно дорабатываем планировщик и ядро Tantor Postgres под специфику 1С. У нас есть план задач и мы планомерно движемся к цели. Важно, что это не только наша инициатива - это стратегический приоритет компании.

Почему привязка планов запросов, использование хинтов и аналогичные инструменты - это плохой путь для 1С? 

Все эти инструменты объединяет одно: они не решают проблему, а маскируют её. Привязка плана запроса, использование хинтов, создание индексов в обход платформы 1С - все это костыли, которые работают ровно до тех пор, пока не изменится что-то вокруг них. А измениться может многое: если меняется текст запроса - меняется QueryID, и привязанный план перестаёт применяться. Добавляется новый индекс - планировщик начинает рассматривать новые варианты плана, и "зафиксированный" план или индекс может оказаться уже не оптимальным. Меняется структура таблицы - и индекс, созданный в обход платформы, удаляется. В лучшем случае запрос просто вернётся к прежней плохой производительности, в худшем - станет ещё хуже.

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

Есть ли сценарии, где MS SQL Server фундаментально лучше, и это не вопрос одного патча?

Да, такие моменты еще есть, и именно они и составляют ядро нашей долгосрочной работы. Например, задачи, связанные с планированием запросов и статистикой, за один спринт не решаются. Подробнее расскажем об этом на Tantor JAM в начале осени.