Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Postgres na nvme proizvoditelnost i konvergentsiya tranzaktsiy i analitiki
Dev48

© 2026 · All rights reserved.

Postgres на NVMe: производительность и конвергенция транзакций и аналитики

Источник: ClickHouse

Postgres на NVMe: производительность и конвергенция транзакций и аналитики

Источник: ClickHouse

Узнайте, как локальные NVMe-накопители меняют производительность транзакций в Po tgre и почему ClickHou e остается незаменимым для быстрой аналитики по мере масштабирования рабочих нагрузок.

25 сентября 2026 г.

В начале этого месяца я принял участие в вебинаре с инженерной командой Moniepoint, чтобы обсудить то, о чем я размышлял еще со времен PeerDB: что меняется, когда Postgres работает на локальных NVMe, а что остается прежним?

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

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

Эта статья — сжатая версия той беседы.

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

Я постоянно наблюдаю одни и те же пять проблем:

  • Замедление загрузки данных: задачи UPDATE и UPSERT, которые раньше занимали секунды, начинают занимать минуты или часы.
  • Нестабильность чтения: попадания в кэш остаются быстрыми, но промахи — нет, и задержки p95/p99 могут вырасти с миллисекунд до секунд.
  • Отставание VACUUM: «мертвые» кортежи (dead tuples) накапливаются быстрее, чем autovacuum успевает их очищать.
  • Нагрузка от контрольных точек (checkpoints): операции записи и fsync конкурируют с приложением за I/O.
  • Отставание логической репликации: декодер не справляется, слоты растут, а подчиненные системы начинают отставать.

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

У этих проблем разные симптомы, но общая первопричина: рабочий набор данных перерастает объем оперативной памяти, и излишки данных попадают на диск.

Индексы, которые больше не помещаются в памяти, требуют больше дисковых операций чтения. Промахи кэша делают задержки чтения менее предсказуемыми. VACUUM приходится считывать и очищать больше страниц. Контрольные точки создают нагрузку на запись и fsync. Логическое декодирование может приводить к сбросу данных на диск.

На уровне хоста картина знакома: IOPS приближаются к пределу, задержки растут, а длина очереди увеличивается.

Кэши процессора работают на наносекундах. DRAM, где находится shared_buffers, — около ста наносекунд. Сетевые SSD, такие как EBS, — от одной до десяти миллисекунд. Локальные NVMe находятся посередине: десятки микросекунд. Это на два порядка медленнее RAM, но примерно в сто раз быстрее EBS.

Сокращение времени промаха кэша с миллисекунд до микросекунд заставляет систему вести себя так, будто у нее больше оперативной памяти, чем есть на самом деле. Хвостовые задержки (tail latencies) улучшаются, потому что «холодные» чтения, вызывающие их, становятся дешевыми. WAL fsync перестает доминировать в задержках фиксации транзакций. VACUUM становится процессорно-зависимым и предсказуемым.

Мы развернули восемь идентичных кластеров, где единственной переменной был тип хранилища для тома данных: m6id.4xlarge (16 vCPU, 64 ГБ RAM), сборка Postgres 18.3 из исходного кода, shared_buffers = 16 ГБ, включенные контрольные суммы. Четыре кластера использовали локальные NVMe, четыре — EBS gp3 с базовым уровнем 3000 IOPS. Набор данных — pgbench с коэффициентом масштабирования 33 000: 482 ГБ кучи, 3,3 миллиарда строк, что примерно в 30 раз больше объема оперативной памяти. Именно так выглядит «взрослый» Postgres, и это гораздо более репрезентативно, чем бенчмарк, помещающийся в кэш.

Рабочая нагрузка составляла 64 клиента на 16 потоках в течение пяти минут, каждая транзакция обновляла случайную строку из 3,3 миллиарда, при этом все восемь хостов работали параллельно с непрерывным профилированием (Parca с eBPF, pg_stat_activity с частотой 1 Гц) на каждом хосте.

Результат: в 9,2 раза выше пропускная способность на NVMe, медиана 16 030 TPS против 1 734 на EBS. Число, которое меня волнует больше — это задержка: 4,0 мс на UPDATE на NVMe против 36,9 мс на EBS. Это разница между предсказуемой работой и потоком тикетов «некоторые пользователи жалуются на медленную работу», которые трудно воспроизвести.

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

На EBS 29 из 64 бэкендов на хост (45%) в любой момент времени находились в состоянии IO:DataFileRead, и ни один не был на процессоре без ожидания. На NVMe 9 бэкендов (14%) были в IO:DataFileRead, а 13 были на процессоре, выполняя реальную работу. Остальные в обоих случаях были в основном в LWLock:WALWrite — это одинаковая работа на стороне CPU в обоих случаях.

Контринтуитивная часть проявилась в профилях CPU. Можно подумать, что EBS недогружен и более умная конвейеризация могла бы сократить разрыв. Это не так. Хосты с NVMe потратили около 2 253 процессорных секунд за время выполнения (примерно 9,4 занятых ядра) по сравнению с 251 на EBS (около одного ядра). Доля CPU на функцию выглядит выше на EBS, но это пропорция, а не пропускная способность. Postgres выполняет одну и ту же работу в обоих случаях; на EBS он тратит 89% времени вне процессора, ожидая I/O. EBS не занят. Он заблокирован.

Другие подсистемы подтвердили ту же историю. Очистка 10 ГБ «раздутых» данных с помощью VACUUM заняла 366 с на NVMe против 964 с на EBS (в 2,6 раза), при этом ожидание I/O сократилось с 387 с до 3 с. Логическое декодирование слота размером ~10 ГБ выполнялось со скоростью 89 МБ/с против 52 МБ/с — всего в 1,7 раза быстрее, так как декодер однопоточный и читает WAL последовательно.

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

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

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

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

Один из строительных блоков — синхронная потоковая репликация между зонами доступности (AZ). Топология может включать первичный узел и два резервных, каждый с локальным NVMe, распределенных по разным AZ. Кворумную синхронную репликацию PostgreSQL можно настроить с помощью synchronous_standby_names = 'ANY 1 (standby1, standby2)'.

Фиксация транзакции ожидает подтверждения от самого быстрого резервного узла, а не от самого медленного, и вы можете потерять узел или целую зону доступности, не потеряв подтвержденные транзакции. Переключение при сбое — решенная проблема с помощью таких инструментов, как Patroni или repmgr.

Вы переносите репликацию со слоя хранилища в Postgres, который понимает LSN и транзакции и справляется с этой задачей лучше.

Второй строительный блок — непрерывное архивирование WAL.

Периодические базовые резервные копии плюс каждый сегмент WAL, отправляемый в S3 в режиме реального времени с помощью WAL-G. RPO в секундах, одиннадцать девяток надежности и архив, который живет вне вашего парка вычислительных мощностей и переживает потерю узла, зоны доступности и даже региона. Том NVMe становится кэшем состояния, который всегда можно восстановить: потеряли узел — развернули архив. Тот же архив дает вам PITR, реплики для чтения, которые никогда не касаются первичного узла, и ветвления от любого LSN.

Если локальные NVMe устраняют так много ожиданий I/O, почему бы просто не запускать все на очень быстром Postgres? Потому что задержка хранилища — это лишь часть проблемы. NVMe делает случайный доступ значительно дешевле. Но он не превращает строковое хранилище в колоночное. Транзакционные и аналитические нагрузки требуют принципиально разных подходов от движка хранения.

Postgres хранит полные строки на страницах размером 8 КБ. Точечное чтение затрагивает одну страницу, MVCC сохраняет версии строк на месте, поэтому пишущие процессы никогда не блокируют читающие, а B-tree индексы делают выборочный поиск недорогим. Обратная сторона заключается в том, что агрегация по миллиарду строк считывает каждую страницу каждой строки, независимо от того, нужны ли эти столбцы. Запрос sum(amount) GROUP BY country по-прежнему загружает целые строки, даже если каждая страница возвращается за микросекунды.

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

Что изменилось, так это момент, когда команды сталкиваются с этим ограничением. Раньше рост с 10 ГБ до 100 ГБ занимал 12–18 месяцев; теперь это занимает от одного до трех. AI-продукты регистрируют логи вывода и запуски агентов с первого дня и нуждаются в аналитике по ним с самого начала. Платформы безопасности принимают потоки событий только для добавления и быстро достигают терабайтов данных. SaaS-решения для продуктовой аналитики продают дашборды клиентам, а 30-секундный дашборд — это дашборд, которому никто не доверяет.

Паттерн, который я постоянно наблюдаю на практике, прост. Приложение продолжает писать в Postgres: транзакции, ACID, точечный поиск — все остается без изменений. Change Data Capture (CDC) передает каждую вставку, обновление и удаление в ClickHouse с задержкой в несколько секунд. А pg_clickhouse, open-source расширение для Postgres, позволяет приложению запрашивать копию в ClickHouse через существующее соединение с Postgres, поэтому ClickHouse ведет себя почти как аналитическая реплика для чтения.

Эту конструкцию поддерживают три столпа. CDC на основе WAL: мы используем PeerDB (open source; ClickPipes — управляемое предложение), который реплицирует порядка 200 ТБ в месяц в продакшене, применяя обновления и удаления в ReplacingMergeTree с минимальным влиянием на основной узел. Pushdown запросов: расширение должно глубоко понимать запросы, переписывая планы Postgres в SQL для ClickHouse (например, синтаксис JOIN отличается), и покрытие pushdown — это то, что нужно тщательно оценивать. Синхронизация схемы: DDL проходит через тот же конвейер, что и данные, поэтому столбец, добавленный в Postgres, появляется в ClickHouse.

Новинка: WalShadow для репликации из Postgres в ClickHouse с задержкой менее секунды

С момента записи этого вебинара мы представили WalShadow, open-source движок репликации, который теперь доступен в рамках Private Preview с ClickHouse Managed Postgres. В отличие от логического CDC через PeerDB или ClickPipes, WalShadow считывает данные напрямую из физического WAL Postgres и преобразует изменения в блоки, нативные для ClickHouse. Это обеспечивает репликацию с задержкой менее секунды без использования слотов логической репликации, сохраняя синхронизацию вставок, обновлений, удалений и поддерживаемых изменений схемы.

Практический результат заключается в том, что вам больше не нужно масштабировать Postgres для хранения терабайтов аналитической истории. Держите небольшой быстрый Postgres для «горячего» транзакционного пути, а тяжелые запросы на сканирование направляйте в ClickHouse.

Быстрый OLTP — это проблема хранения. Локальный NVMe меняет константы: микросекундные промахи кэша, дешевые fsync, предсказуемый VACUUM. С кворумной репликацией и архивацией WAL вы получаете отказоустойчивость уровня сетевых хранилищ без задержек, присущих сети.

Быстрый OLAP — это проблема архитектуры. Никакое устройство хранения не сделает строковое хранилище эффективным при сканировании миллиарда строк; это делает поколоночная структура. CDC в сочетании с колоночным хранилищем меняет ситуацию.

Все здесь представленное является open source: Postgres, WAL-G, repmgr, PeerDB, pg_clickhouse и ClickHouse. Вы можете запустить весь стек на ноутбуке. А если вы не хотите заниматься этим самостоятельно, это именно тот стек, который мы внедряем в управляемый Postgres от ClickHouse с помощью ClickPipes CDC.

← Все статьи

Ещё в разделе «Данные и аналитика»

Все →
Databricks покупает Row Zero и ищет другие стартапы для поглощенияПресса
Databricks

Databricks покупает Row Zero и ищет другие стартапы для поглощения

Официальный SDK FastAPI Redis уже доступен
Redis

Официальный SDK FastAPI Redis уже доступен

Dynatrace получила сертификат ISO/IEC 42001
Dynatrace

Dynatrace получила сертификат ISO/IEC 42001

Знакомьтесь, AvisLoader: загрузчик для Windows, созданный, чтобы пережить блокировку
Varonis

Знакомьтесь, AvisLoader: загрузчик для Windows, созданный, чтобы пережить блокировку

От инсайтов к инновациям: как Kiro Crew, Dynatrace и AWS помогают командам достигать большего
Dynatrace

От инсайтов к инновациям: как Kiro Crew, Dynatrace и AWS помогают командам достигать большего

Релиз ClickHouse 26.9
ClickHouse

Релиз ClickHouse 26.9

Ещё от ClickHouse

Релиз ClickHouse 26.9
ClickHouse

Релиз ClickHouse 26.9

ClickHouse назначает Майка Скарпелли, бывшего финансового директора Snowflake и ServiceNow, в совет директоров
ClickHouse

ClickHouse назначает Майка Скарпелли, бывшего финансового директора Snowflake и ServiceNow, в совет директоров

Как Fountain перестроила свой уровень данных на ClickHouse Cloud для поддержки Cue, системы Frontline Superintelligence
ClickHouse

Как Fountain перестроила свой уровень данных на ClickHouse Cloud для поддержки Cue, системы Frontline Superintelligence

Неделя Postgres в Нидерландах: PGDay Lowlands и Percona Live 2026
ClickHouse

Неделя Postgres в Нидерландах: PGDay Lowlands и Percona Live 2026