Привет, Хабр! Пишет эту статью Александра Лысенко — вчера я была студенткой, а сегодня как инженер-программист Nexign спешу поделиться приобретенным опытом.
Мой первый проект для реального бизнеса был связан с миграцией с Oracle на PostgreSQL. Сегодня расскажу, как внедрение диапазонного типа данных при переходе между СУБД позволило не просто сохранить производительность, но и превзойти исходные показатели. Если вы тоже только начинаете свой карьерный путь — надеюсь, этот материал вам поможет.
Импортозамещение: не просто тренд, а необходимость.
С 2022 года импортозамещение в ИТ перестало быть абстрактной концепцией — оно стало необходимостью. Уход зарубежных вендоров и требования законодательства (в т.ч. указ Президента РФ № 166) подтолкнули Nexign и многие другие компании к переходу на отечественное ПО.

Особенно заметен рост числа решений на базе PostgreSQL: по данным независимого исследования ЛАНИТ, около 60 % отечественных СУБД используют именно эту платформу — речь идёт о российских системах управления базами данных, большинство из которых представляют собой доработанные версии открытого PostgreSQL. При этом миграция на такие решения — это не просто перенос бизнес‑логики и оперируемых данных: различия в архитектуре, диалектах SQL и поддерживаемых типах данных могут сыграть злую шутку.
Если производительность упала после миграции.
Моя команда столкнулась с проблемой при переносе биллинговой системы оператора связи с Oracle 19 на PostgreSQL 15.
На старте логическая и физическая структуры БД были идентичны — хотели получить «чистые» замеры. Для нагрузочного тестирования использовали Apache JMeter.
Условия теста:
10 пользователей;
5 категорий запросов (выборка актуальных тарифных планов, исторических данных и т. д.);
объём данных — 2 ГБ (на основе реальных обезличенных данных);
длительность теста — 60 секунд нагрузки, цикл повторялся 100 раз.

Первые результаты нас не порадовали:
среднее время выполнения запросов в PostgreSQL было сопоставимо с Oracle;
максимальное время выполнения выросло в 3–5 раз;
разброс значений времени выполнения запроса значительно увеличился.
Вывод был очевиден: прямая миграция без адаптации структуры базы данных приводит к деградации производительности.

Причина снижения производительности: работа с временными интервалами.
Биллинговые системы для поддержания рыночных бизнес-процессов оперируют хронологическими данными:
хранят исторические данные с периодами актуальности;
поддерживают ретарификацию (корректировку) прошлых периодов;
обрабатывают архивные тарифы для поддержания лояльности клиентов.
Традиционный подход в Oracle — хранить период актуальности в двух столбцах:
start_date (дата начала);
end_date (дата окончания).
Для выборки используют оператор BETWEEN и ограничения целостности (CONSTRAINT), что:
усложняет запросы;
повышает риск логических ошибок;
возлагает всю ответственность на разработчика.
Решение: диапазонный тип данных PostgreSQL.
В PostgreSQL (начиная с версии 9.2) есть диапазонные типы (range types) — они позволяют хранить интервал как единое значение.
Ключевые преимущества:
встроенная поддержка операций с интервалами (пересечение, включение и т. д.);
возможность индексации (в т. ч. с помощью GIST-индексов);
поддержка бесконечности (∞) и исключённых границ;
операции основаны на интервальной алгебре Аллена.
При модификации физической модели БД:
Заменили столбцы с периодом актуальности записи (start_date, end_date) на столбец диапазонного типа (validity).
Создали GIST‑индекс для нового столбца для оптимизации запросов с фильтрацией данных по диапазонам.

Результат: производительность выросла в 2 раза
После внедрения диапазонных типов и GIST‑индексов провели повторное нагрузочное тестирование.
На выходе получили:
среднее время выполнения запросов сократилось в 2 раза;
разброс времени выполнения запросов значительно уменьшился;
показатели PostgreSQL превзошли результаты Oracle.
Почему так произошло:
Упрощение запросов. Вместо сложных условий с BETWEEN и проверками границ — простые операции с диапазонами (например, @> для проверки включения).
Эффективная индексация. GIST‑индекс ускоряет поиск по временным интервалам.
Встроенные проверки. PostgreSQL автоматически контролирует корректность диапазонов (например, не допускает start_date > end_date).

Выводы и рекомендации для тех, кто на старте:
Не копируйте структуру «один в один». Миграция — повод пересмотреть архитектуру БД.
Используйте сильные стороны целевой СУБД. В PostgreSQL диапазонные типы — мощный инструмент для работы с хронологическими данными.
Тестируйте производительность. Нагрузочное тестирование до и после изменений — единственный способ оценить эффект.
Индексируйте разумно. GIST‑индексы отлично подходят для диапазонов, но требуют тестирования в контексте вашей нагрузки.
Учитывайте специфику домена. В биллинге временные интервалы — ключевой элемент, и их оптимизация даёт значительный выигрыш.
Итог: внедрение диапазонных типов данных — не просто «фишка» PostgreSQL, а реальный инструмент для повышения производительности. Если вы мигрируете с Oracle на PostgreSQL и работаете с хронологическими данными, обязательно рассмотрите этот подход. Он сэкономит вам время, нервы и ресурсы сервера.
Конечно, переход на диапазонные типы — не единственное архитектурное изменение, которое пришлось осуществить при смене СУБД. Мы столкнулись с массой других проблем, таких как: отсутствие пакетов процедур; отсутствие поддержки транзакций в функциях; массивов, индексируемых строками; logon триггеров; синонимов... Кажется, что этот список можно продолжать бесконечно, а как мы с этим боролись — предмет уже следующих статей :)
А как проходил ваш первый опыт оптимизации PostgreSQL? Делитесь в комментариях!
Комментарии (5)

baldr
26.06.2026 11:50объём данных — 2 ГБ (на основе реальных обезличенных данных);
В смысле вся база 2 ГБ? И запрос выполнялся 5 секунд? У меня возникают очевидные вопросы и получаются нехорошие выводы.

PAL_habr
26.06.2026 11:50Хотел спросить про то как делали и делали ли секционирование на этом добре, но 2гб пожалуй снимают вопрос. :)

degvit
26.06.2026 11:50По православному НТ проводить не менее 4 часов, а лучше длинным циклом 24-48 часов. Так вы сможете отследить не только SLA по выполняемым запросам, но и оценить утечки памяти и нагрузку на CPU.
В целом статья про конкретную проблему в процессе миграции и ее решение. Не рокет сайнс, но новичкам и любопытным будет полезно

ptr128
26.06.2026 11:50Самое непонятное, как же gist мог оказаться быстрей btree при работе с обычными диапазонами. Впрочем, так как в статье нет ни примера кода, ни результатов его модификации, ни бенчмарков, то речь может идти о каком-то хитром частном случае или кривых запросах из ORM.
Akina
Не, ну рассказ в стиле "автомобиль съехал с горки не быстрее велосипеда, а потом мы завелись...". Как по мне - вообще ни о чём, чисто ради плюсадина в публикации.