Skip to content
RiverCore
PostgreSQL 18 Skip Scan даёт ускорение в 21 раз на Aurora
PostgreSQL 18 skip scanAurora optimizationindex performancePostgreSQL skip scan composite index speedupAWS Aurora RDS query optimization

PostgreSQL 18 Skip Scan даёт ускорение в 21 раз на Aurora

21 июл 20267 мин. чтенияAlex Drover

Любой, кого будили в 3 ночи из-за того, что составной индекс перестал соответствовать шаблону WHERE, хорошо знает суть этой проблемы. PostgreSQL 18 только что сократил время выполнения типового запроса с 73,2 мс до 3,4 мс на том же железе — улучшение в 21 раз — без добавления единого нового индекса. Это главная цифра от AWS на этой неделе, и она меняет математику проектирования B-tree структур для многих команд.

Цифры

Стенд максимально прост — и именно это делает результаты достоверными. Как сообщает Amazon Web Services (AWS), бенчмарк запускался на инстансе db.r6g.large — скромном ARM-сервере, который многие команды используют на стейджинге и в небольших продакшн-тирах. Таблица содержала миллион строк в схеме customer_orders с составным индексом по (status, created_date). Столбец status имел ровно 5 различных значений. Оба запуска использовали прогретый буферный кэш, так что речь не идёт об I/O-хитростях.

На Aurora PostgreSQL 17.10 планировщик делал то, что всегда делал при отсутствии ведущего столбца в WHERE: откатывался к Parallel Seq Scan с 2 запланированными и 2 запущенными воркерами. Было прочитано 7 353 общих блока. Каждый воркер отфильтровывал 332 433 строки. Время планирования — 0,091 мс, время выполнения — 73,200 мс.

На Aurora PostgreSQL 18.4, том же инстансе, с теми же данными, при том же запросе с фильтром created_date = '2026-03-15', планировщик переключился на Bitmap Index Scan по составному индексу. Было выполнено 11 обращений к индексу — по одному на каждое уникальное значение ведущего столбца плюс накладные расходы — и прочитано 2 266 общих блоков. Время планирования — 0,065 мс. Время выполнения — 3,374 мс.

Количество блоков сократилось примерно на 69%. Время выполнения упало примерно на 95%. Это и есть тот самый коэффициент 21x — и это цифра, которая сама по себе окупает миграцию.

Подумайте, что это означает в операционном бюджете. Запрос, который выполняется 500 раз в секунду на нагруженном пути оформления заказа, только что вернул вам примерно 35 секунд процессорного времени на каждую астрономическую секунду по всему флоту. На горячем сервисе расчётов iGaming это разница между необходимостью перехода на более мощный инстанс и её отсутствием. Я видел продакшн-инциденты, когда команды преждевременно делали шардинг, потому что одно такое ограничение планировщика выглядело структурным. Им не было. До решения оставалась одна версия.

Моё мнение: деталь про 5 различных значений — это то, что нужно усвоить. Skip scan выигрывает больше всего, когда ведущие столбцы имеют низкую кардинальность. По мере роста кардинальности 11 обращений к индексу превращаются в 11 000, и математика меняется.

Что действительно нового

Четыре пункта из первой части серии AWS: оптимизация skip scan для многоколоночных B-tree индексов, расширенный вывод EXPLAIN с отображением поведения хранилища, автоматическое удаление лишних self-join'ов и улучшения vacuum/autovacuum. Вторая часть охватит изменения в безопасности, мониторинге, инструментах для разработчиков и логической репликации. Изменений много, но именно skip scan меняет подход к проектированию схем.

Вот что изменилось под капотом. В PostgreSQL 17 и ранее многоколоночный индекс по (a, b) можно было использовать только тогда, когда WHERE ссылался на a или на a и b вместе. Фильтр только по b оставлял планировщику два варианта: последовательное сканирование или создание второго индекса только по b. Команды создавали второй индекс. Потом третий. Потом приходил счёт за write amplification.

Skip scan позволяет планировщику перебирать уникальные значения ведущего столбца и обращаться к индексу для каждого из них. Документация PostgreSQL достаточно подробно описывает метод доступа B-tree, так что механизм интуитивно понятен: вместо «сканировать с ведущего ключа» планировщик делает «для каждого уникального ведущего ключа — сканировать». Одиннадцать обращений к индексу в бенчмарке AWS напрямую отражают это: 5 уникальных значений status плюс граничные зонды, необходимые исполнителю.

Расширенный вывод EXPLAIN — негромко, но второе по важности изменение. В плане версии 18 появился Index Searches: 11 как самостоятельная строка. Это именно тот сигнал, который нужен для обнаружения злоупотреблений skip scan при code review или в логе медленных запросов. Без этой видимости пришлось бы восстанавливать стратегию по количеству буферов.

Сохранение статистики оптимизатора при обновлении мажорной версии — это операционный сюрприз, который недооценивают. Кто делал мажорный апгрейд Postgres, знает ритуал: переключаемся, смотрим дашборды, ждём деградации планов из-за очистки pg_statistic, потом запускаем ANALYZE в 2 ночи и молимся, чтобы autovacuum не пошёл вразнос. Сохранение статистики после апгрейда устраняет целый класс постпереключательных инцидентов.

Автоматическое удаление self-join'ов — приятный выигрыш на уровне компилятора для SQL, генерируемого ORM. Улучшения vacuum важны для тех, кто работает с таблицами с высокой интенсивностью изменений. Ни то ни другое не так заметно, как skip scan.

Что уже учтено командами разработчиков

Большинство опытных команд, работающих с Postgres, уже предполагали, что PG18 получит skip scan. Это обсуждалось в списке рассылки -hackers годами, а у Oracle и SQL Server аналоги существуют уже десятилетие. Что учтено: фича есть, она работает на ведущих столбцах с низкой кардинальностью, на высококардинальных она не поможет. Никто разумный не выбрасывает индексы btree_gin на основании одного поста в блоге.

Что не учтено, судя по разговорам с platform lead'ами, с которыми я обменивался мнениями: масштаб возможности по очистке индексов. Многие продакшн-схемы несут два, три, четыре «про запас» одноколоночных индекса, добавленных специально потому, что составной индекс не покрывал определённый паттерн запроса. Каждый такой индекс стоит пропускной способности записи и объёма WAL при каждом INSERT и UPDATE. Skip scan позволяет часть из них удалить.

Неудобная правда: большинство команд этого не сделают. Они поставят PG18, оставят все существующие индексы и просто получат выигрыш от skip scan как бонусную производительность на запросах, которые и так работали нормально. Команды, которые проаудируют список индексов и удалят избыточные, увидят выигрыш на стороне записи — а он, как правило, за квартал оказывается больше, чем заголовочная цифра на стороне чтения.

Также стоит отметить: таймлайны Aurora и RDS на этот раз совпадают, что бывает не всегда. Оба сервиса уже поддерживают PG18. Командам на RDS не нужно ждать целый релизный цикл после Aurora.

Альтернативный взгляд

Skip scan — это инструмент, опасный в неправильных руках. В бенчмарке AWS использовалось 5 уникальных значений status — это близко к идеальному случаю. Направьте ту же оптимизацию на ведущий столбец с миллионом уникальных значений, и планировщик сожжёт CPU на обращениях к индексу там, где последовательное сканирование завершилось бы быстрее. Планировщик должен вычислять стоимость и избегать такого сценария, но модели стоимости планировщика известны своим оптимизмом на синтетических данных и пессимизмом на реальных.

Второй альтернативный угол зрения: расширенный вывод EXPLAIN породит волну тикетов «почему мой запрос стал медленнее». Команды, которые раньше не видели Index Searches в своих планах, начнут видеть большие числа и паниковать. Ожидайте всплеска вопросов на Stack Overflow и много преждевременного тюнинга индексов.

В-третьих, фича «статистика переживает мажорное обновление версии» усыпит бдительность части команд и заставит их сократить окно валидации после апгрейда. Это окно существует по причинам, выходящим за рамки pg_statistic. Не сокращайте период канареечного развёртывания только потому, что один класс регрессий стало проще избежать.

Ключевые выводы

  • Skip scan в PostgreSQL 18 превратил параллельное последовательное сканирование за 73,2 мс в bitmap index scan за 3,4 мс в бенчмарке AWS — ускорение в 21 раз на db.r6g.large с одним миллионом строк.
  • Выигрыш максимален, когда ведущий столбец составного индекса имеет низкую кардинальность. Пять уникальных значений дали 11 обращений к индексу. На ведущих столбцах с высокой кардинальностью такого результата не будет.
  • После обновления проаудируйте список индексов. Реальный выигрыш — в удалении избыточных одноколоночных индексов, добавленных исключительно для обхода старых ограничений планировщика: это снизит write amplification и объём WAL.
  • Сохранение статистики оптимизатора при обновлении мажорной версии устраняет распространённую причину деградации планов после переключения, но не используйте это как повод сокращать период канареечного развёртывания.
  • Расширенный вывод EXPLAIN теперь отображает Index Searches как метрику первого класса. Добавьте её в дашборды медленных запросов заранее, до того, как она понадобится.

Часто задаваемые вопросы

В: Когда использовать skip scan в PostgreSQL 18, а когда добавить отдельный индекс?

Skip scan выигрывает, когда ведущий столбец составного индекса имеет низкую кардинальность — грубо говоря, несколько десятков уникальных значений или меньше. Если ведущий столбец имеет тысячи или миллионы уникальных значений, отдельный одноколоночный индекс по-прежнему будет быстрее, поскольку планировщику потребовалось бы слишком много обращений к индексу для эффективной работы skip scan.

В: Требует ли обновление до PostgreSQL 18 на Aurora или RDS переиндексации?

В публикации AWS не указывается, что skip scan требует новых или пересозданных индексов. Улучшение в 21 раз было достигнуто на том же составном индексе, который существовал в тесте с PostgreSQL 17. Стандартные процедуры обновления мажорной версии по-прежнему применимы, а статистика оптимизатора теперь сохраняется при обновлении в PostgreSQL 18.

В: Каков операционный эффект расширенного вывода EXPLAIN в PostgreSQL 18?

Расширенный EXPLAIN раскрывает поведение хранилища, включая новый счётчик Index Searches — именно по нему можно убедиться, что skip scan используется. Это даёт DBA и platform-инженерам прямую видимость стратегии планировщика, которую раньше приходилось восстанавливать по количеству буферов, что значительно ускоряет разбор медленных запросов.

AD
Alex Drover
RiverCore Analyst · Dublin, Ireland
ПОДЕЛИТЬСЯ
// ПОХОЖИЕ СТАТЬИ
ГлавнаяРешенияПроектыО насКонтакт
Новости06
Дублин, Ирландия · ЕСGMT+1
LinkedIn
🇷🇺RU