PostgreSQL 18: що нового і чи варто оновлюватись
Асинхронний ввід-вивід, uuidv7(), віртуальні згенеровані колонки, OLD/NEW у RETURNING і інші зміни 18-ї версії — що з цього дасть користь вашому проєкту і на що звернути увагу при оновленні.
PostgreSQL 18 вийшов восени 2025 року і за рік отримав кілька мінорних оновлень — тобто вже достатньо «відлежався» для продакшену. Розберемо зміни, які найпомітніші в щоденній роботі, і нюанси оновлення.
Асинхронний ввід-вивід
Найбільша зміна під капотом. Раніше PostgreSQL читав дані з диска синхронно: запросив сторінку — чекає. Тепер з'явилась підсистема асинхронного I/O, яка дозволяє видати кілька запитів на читання одночасно і не чекати кожен окремо.
SHOW io_method; -- worker (за замовчуванням) або io_uring на Linuxworker— асинхронність через окремі процеси, працює всюди;io_uring— нативний механізм ядра Linux, потребує збірки з підтримкою liburing.
У першій версії асинхронно виконуються читання: послідовні скани, bitmap heap scan, VACUUM. Найбільший виграш — на мережевих дисках у хмарі з високою латентністю. Навантаження з великою кількістю дрібних записів (типовий OLTP) кардинально швидшим не стане.
ПорадаНовий системний вид
pg_aiosпоказує операції вводу-виводу, які виконуються зараз, — корисно для діагностики.
uuidv7()
SELECT uuidv7();
-- 0199a5f2-4c1b-7e3a-9d41-6f2b8c0e1a77UUID версії 7 починається з мітки часу, тож нові значення впорядковані за часом. Для первинних ключів це важливо: випадкові UUIDv4 вставляються в довільні місця B-tree індексу, викликаючи розщеплення сторінок і погіршуючи кешування. UUIDv7 поводиться майже як автоінкремент — нові ключі йдуть у кінець індексу.
CREATE TABLE events (
id uuid PRIMARY KEY DEFAULT uuidv7(),
kind text NOT NULL,
data jsonb
);ПриміткаМітка часу в UUIDv7 видна всім, хто бачить ідентифікатор. Якщо час створення об'єкта — чутлива інформація, для публічних ID краще залишити UUIDv4.
Віртуальні згенеровані колонки
Згенеровані колонки тепер можуть бути віртуальними — обчислюватись при читанні, без зберігання на диску. І саме VIRTUAL став поведінкою за замовчуванням.
CREATE TABLE products (
name text NOT NULL,
price_net numeric(10,2) NOT NULL,
vat_rate numeric(4,2) NOT NULL DEFAULT 0.20,
-- обчислюється при читанні (VIRTUAL за замовчуванням)
price_gross numeric(10,2) GENERATED ALWAYS AS (price_net * (1 + vat_rate)),
-- зберігається на диску: потрібна для індексу
search_tsv tsvector GENERATED ALWAYS AS (to_tsvector('simple', name)) STORED
);УвагаЯкщо ваші міграції створюють згенеровані колонки без явного
STORED, у PostgreSQL 18 вони стануть віртуальними. Віртуальну колонку не можна проіндексувати — для індексів і повнотекстового пошуку пишітьSTOREDявно.
OLD і NEW у RETURNING
Тепер у RETURNING можна отримати і старі, і нові значення — без тригерів і додаткових запитів:
UPDATE accounts SET balance = balance - 100
WHERE id = 42
RETURNING old.balance AS before, new.balance AS after;Зручно для аудиту, логування змін і логіки «повернути, що змінилось».
Темпоральні обмеження
Первинні й унікальні ключі з WITHOUT OVERLAPS забороняють перетин періодів — наприклад, щоб одна кімната не була заброньована двічі на той самий час:
CREATE EXTENSION IF NOT EXISTS btree_gist;
CREATE TABLE bookings (
room_id int,
during tstzrange,
PRIMARY KEY (room_id, during WITHOUT OVERLAPS)
);Безпека і доступ
- OAuth 2.0 як метод автентифікації — інтеграція з корпоративними провайдерами ідентичності;
- автентифікація MD5 оголошена застарілою — переходьте на SCRAM-SHA-256, якщо ще не перейшли.
-- Знайти користувачів, у яких пароль досі зберігається як MD5
SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%';Оновлення стало менш болісним
pg_upgrade тепер переносить статистику планувальника. Раніше після мажорного оновлення база кілька годин працювала на «порожній» статистиці, доки не відпрацював ANALYZE, і запити могли отримувати погані плани. Також з'явилась опція --swap, яка пришвидшує оновлення великих кластерів.
Чекліст оновлення
- Перевірити сумісність розширень (PostGIS, pgvector, TimescaleDB тощо) з 18-ю версією.
- Знайти в міграціях згенеровані колонки без явного
STORED. - Перевести паролі з MD5 на SCRAM.
- Прогнати тести застосунку на копії бази з PostgreSQL 18.
- Зробити свіжий бекап, перевірити відновлення, потім
pg_upgrade --linkабо логічну реплікацію для мінімального простою. - Після оновлення стежити за планами найважчих запитів —
pg_stat_statementsв допомогу.
Чому uuidv7 кращий за gen_random_uuid() для первинного ключа великої таблиці?
UUIDv7 впорядкований за часом, тому нові ключі додаються в кінець B-tree індексу, як автоінкремент. Випадкові UUIDv4 розкидаються по всьому індексу, викликаючи розщеплення сторінок, більший розмір індексу і гірше використання кешу.
Збережіть статтю собі
Увійдіть, щоб імпортувати її у власні нотатки, відмічати вивчене, ставити лайки й питати спільноту. Реєстрація безкоштовна: вхід через Google займає кілька секунд.
Увійти через Google Інші способи входу