Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
PostgreSQL 12, последняя версия «лучшей в мире реляционной базы данных с открытым исходным кодом», выходит через пару-тройку недель (если все пойдет по плану). Это соответствует обычному расписанию — новая версия с уймой новых возможностей выходит раз в год, и, честно говоря, это впечатляет. Поэтому я и стал активным членом сообщества PostgreSQL.
По-моему, в отличие от прошлых выпусков, PostgreSQL 12 не содержит одной-двух революционных функций (как, например, секционирование или параллелизм запросов). Я как-то пошутил, что главная фишка PostgreSQL 12 — в большей стабильности. А разве не это нужно, когда вы управляете критически важными данными вашего бизнеса?
Но PostgreSQL 12 этим не ограничивается: с новыми возможностями и усовершенствованиями приложения будут работать лучше, а от вас всего-навсего требуется сделать апгрейд!
(Ну, может, еще индексы перестроить, но в этом релизе это не так страшно, как мы привыкли.)
Вот будет здорово — апгрейднуть PostgreSQL и сразу наслаждаться значительными улучшениями без лишних телодвижений. Несколько лет назад я анализировал обновление с PostgreSQL 9.4 до PostgreSQL 10 и увидел, как ускорилось приложение благодаря улучшенному параллелизму запросов в PostgreSQL 10. И, главное, от меня почти ничего не требовалось (всего-то задать параметр конфигурации max_parallel_workers
).
Согласитесь, удобно, когда сразу после апгрейда приложения работают лучше. А мы очень стараемся радовать пользователей, ведь у PostgreSQL их все больше.
И как же простой апгрейд до PostgreSQL 12 сделает вас счастливым? Сейчас расскажу.
Серьезные улучшения индексирования
Без индексирования база данных далеко не уедет. А как еще быстро находить информацию? Фундаментальная система индексирования PostgreSQL называется B-дерево. Этот тип индекса оптимизирован для систем хранения.
Мы просто используем оператор CREATE INDEX ON some_table (some_column)
, а PostgreSQL проделывает большую работу, чтобы поддерживать актуальность индекса, пока мы постоянно вставляем, обновляем и удаляем значения. Все работает само по себе, как по волшебству.
Но у индексов PostgreSQL есть одна проблема — они раздуваются и занимают лишнее место на диске, а производительность извлечения и обновления данных снижается. Под «раздуванием» я подразумеваю неэффективное поддержание индексной структуры. Это может быть — а может и не быть — связано с мусорными кортежами, которые удаляет VACUUM (спасибо за информацию Питеру Гейгану (Peter Geoghegan)). Раздувание индекса особенно заметно в рабочих нагрузках, где индекс активно изменяется.
PostgreSQL 12 серьезно улучшает работу индексов B-дерева, и эксперименты с тестами типа TPC-C показали, что места теперь используется, в среднем, на 40% меньше. Теперь мы тратим меньше времени не только на обслуживание индексов B-дерева (то есть на операции записи), но и на извлечение данных, ведь индексы стали гораздо меньше.
Приложения, которые активно обновляют свои таблицы — обычно это OLTP-приложения (обработка транзакций в режиме реального времени) — будут гораздо эффективнее использовать диск и обрабатывать запросы. Чем больше на диске места, тем больше у базы данных пространства для роста без апгрейда инфраструктуры.
Некоторые стратегии апгрейда требуют перестроить индексы B-дерева, чтобы воспользоваться этими преимуществами (например, pg_upgrade не перестроит индексы автоматически). В предыдущих версиях PostgreSQL перестройка больших индексов в таблицах приводила к значительному простою, ведь в это время нельзя было вносить изменения. Но в PostgreSQL 12 есть еще одна классная фишка: теперь можно перестраивать индексы параллельно командой REINDEX CONCURRENTLY, чтобы совсем избежать простоя.
В PostgreSQL 12 есть и другие улучшения инфраструктуры индексирования. Еще одна штука, где не обошлось без волшебства, — журнал упреждающей записи, он же WAL (write-ahead log). Журнал упреждающей записи записывает каждую транзакцию в PostgreSQL на случай сбоя и репликации. Приложения используют его для архивации и восстановления на момент времени. Конечно, журнал упреждающей записи записывается на диск, а это может отразиться на производительности.
В PostgreSQL 12 сократились издержки записей WAL, которые создаются индексами GiST, GIN и SP-GiST при построении индекса. Это дает несколько ощутимых преимуществ: записи WAL занимают меньше места на диске, а данные быстрее воспроизводятся, например во время восстановления после сбоя или восстановления на момент времени. Если вы используете такие индексы в своих приложениях (например, геопространственные приложения на основе PostGIS много используют индекс GiST), это еще одна фича, которая значительно улучшит работу безо всяких усилий с вашей стороны.
Секционирование — больше, лучше, быстрее
В PostgreSQL 10 появилось декларативное секционирование. В PostgreSQL 11 его стало гораздо проще использовать. В PostgreSQL 12 можно менять масштаб секций.
В PostgreSQL 12 производительность системы секционирования стала значительно лучше, особенно если в таблице тысячи секций. Например, если запрос затрагивает всего несколько секций в таблице, где их тысячи, он будет выполняться гораздо быстрее. Производительность улучшена не только для таких типов запросов. Еще вы заметите, как ускорились операции INSERT в таблицах со множеством секций.
Запись данных с помощью COPY — кстати, это отличный способ массовой загрузки данных и вот пример приема JSON — в секционированные таблицы в PostgreSQL 12 тоже стала эффективнее. С COPY и так все было быстро, а в PostgreSQL 12 совсем летает.
Благодаря этим преимуществам в PostgreSQL можно хранить наборы данных еще большего размера, а извлекать их стало проще. И никаких усилий с вашей стороны. Если у приложения много секций, например, оно записывает данные временных рядов, простой апгрейд значительно улучшит его производительность.
И хотя это улучшение не совсем из категории «апгрейднули и радуемся», в PostgreSQL 12 можно создавать внешние ключи, которые ссылаются на секционированные таблицы, чтобы работа с секционированием приносила одно удовольствие.
Запросы WITH стали гораздо лучше
Когда был применен патч для встроенных обобщенных табличных выражений (они же CTE, они же запросы WITH), мне не терпелось написать статью о том, как обрадовались разработчики приложений с PostgreSQL. Это одна из тех фич, которые ускорят приложение. Если, конечно, вы используете CTE.
Я часто замечаю, что новички в SQL любят использовать CTE: если написать их определенным образом, прямо чувствуешь, что пишешь императивную программу. Лично я любил переписывать эти запросы, чтобы обойтись без CTE и увеличить производительность. Сейчас все иначе.
PostgreSQL 12 позволяет встраивать определенный тип CTE без побочных эффектов (SELECT
), который используется только один раз ближе к концу запроса. Если бы я вел статистику запросов с CTE, которые я переписывал, большинство из них попали бы в эту категорию. Это помогает разработчикам писать понятный код, который теперь еще и быстро работает.
Более того, PostgreSQL 12 оптимизирует выполнение SQL сам, вам не придется ничего делать. И хотя теперь, наверное, мне не нужно будет оптимизировать такие запросы, здорово, что PostgreSQL продолжает работать над оптимизацией запросов.
Just-in-Time (JIT) — теперь по умолчанию
В системах PostgreSQL 12 с поддержкой LLVM JIT-компиляция включена по умолчанию. Во-первых, вы получаете поддержку JIT для некоторых внутренних операций, а во-вторых, запросы с выражениями (самый простой пример — x + y) в списках выбора (которые стоят у вас после SELECT), агрегатами, выражениями с предложениями WHERE и другими могут использовать JIT для повышения производительности.
Раз JIT включен в PostgreSQL 12 по умолчанию, производительность улучшится сама по себе, но я советую потестить приложение в PostgreSQL 11, где только появился JIT, чтобы измерить производительность запросов и узнать, нужно ли что-нибудь настраивать.
А как же остальные новые фичи PostgreSQL 12?
В PostgreSQL 12 уйма новых классных фич — от возможности изучать данные JSON с помощью стандартных выражений маршрута SQL/JSON до многофакторной аутентификации с параметром clientcert=verify-full
, создаваемых столбцов и многого другого. Хватит на отдельный пост.
Как и PostgreSQL 10, PostgreSQL 12 повысит общую производительность сразу после апгрейда. У вас, конечно, может быть свой путь — протестируйте приложение при схожих условиях в рабочей системе, прежде чем включать улучшения, как это сделал я с PostgreSQL 10. Даже если PostgreSQL 12 уже сейчас стабильнее, чем я предполагал, не ленитесь качественно тестировать приложения, прежде чем выпускать их в продакшен.