Postgres 18: asinxron I/O va UUIDv7 menda nimani o'zgartirdi
Asinxron I/O va ichki `uuidv7()` — asosiy yangiliklar shular edi. Ulardan biri men ikki yil chetlab o'tib kelgan muammoni jimgina hal qildi; ikkinchisi esa benchmarklar va'da qilganidan kamroq ish qildi.

Postgres 18 e'tiborning katta qismini tortgan ikkita imkoniyat bilan chiqdi: asinxron I/O quyi tizimi va native uuidv7() funksiyasi. Benchmark postlari o'z-o'zidan yozildi — ketma-ket skanlar uchun keltirilayotgan ko'paytiruvchilar yaxshi sarlavha bo'ladi.
Men uni endi fikr aytadigan darajada uzoq ishlatdim, va fikrim kamroq hayajonli, lekin menimcha foydaliroq. Bu ikki imkoniyatdan biri men uchun juda muhim bo'ldi — va u ta'sirchan ko'paytuvchisi bor imkoniyat emas.
Asinxron I/O aslida nima qiladi
Eski model sodda edi va, orqaga qarab aytganda, aniq cheklovli. Backend jarayoniga shared buffers'da bo'lmagan sahifa kerak bo'lganda, u o'qish so'rovini yuborardi va kutardi. Bitta so'rov, bitta kutish, keyin keyingisi. Aylanadigan diskda bu mantiqiy edi — disk baribir bir vaqtda bitta ishni qila olardi. O'nlab parallel so'rovni bajarish uchun qurilgan zamonaviy NVMe'da esa bu shuni anglatadi: baza yigirmata so'rov so'rab turgan qurilmadan xushmuomalalik bilan bittadan so'raydi.
Postgres 18 bir vaqtning o'zida bir nechta o'qishni "havoda" ushlab turadigan AIO quyi tizimini qo'shdi. io_method sozlamasi buni boshqaradi: worker (maxsus I/O jarayonlari, portativ standart) yoki zamonaviy Linux'da io_uring — yadroning asinxron interfeysiga to'g'ridan-to'g'ri yuboradi.
Foyda ko'radigan amallar — ko'p sahifani oldindan aytsa bo'ladigan tartibda o'qiydiganlari: ketma-ket skanlar, bitmap heap skanlar va vacuum.
Aynan shu ro'yxat muhim, va mening yutug'im shuning uchun kamtarona bo'ldi. Mening yukim deyarli butunlay indeksli nuqtali so'rovlardan iborat: shu to'lovni id bo'yicha ol, shu davlat uchun eSIM paketlarini ol. Ular kam sahifaga tegadi va asinxron I/O yordam beradigan ma'noda hech qachon I/O'ga bog'liq bo'lmagan. Men haqiqiy o'zgarish ko'rgan joy — texnik xizmat: katta jadvallarda vacuum sezilarli tezlashdi. Bu eshitilganidan muhimroq, chunki vacuum orqada qolishi — eng noqulay paytda bloat muammosiga aylanadigan narsa.
Halol xulosam: asinxron I/O analitik va texnik xizmat ishlari uchun katta yutuq, OLTP nuqtali so'rovlar uchun kichik yutuq, va ikkala holatda ham yoqishga arziydi, chunki zarari nolga yaqin.
-- buildingiz nima qilayotganini ko'ring
SHOW io_method; -- 'worker' yoki 'io_uring'
SHOW io_combine_limit; -- nechta blok bitta so'rovga birlashtiriladiMuhimi — UUIDv7
Men faqat shuning uchun ham yangilagan bo'lardim, va uning foydasi o'tkazuvchanlikda emas — sekin harakatdagi tuzilmaviy muammoni yo'q qilishida.
Tasodifiy UUID (v4) — taqsimlangan identifikatsiya uchun go'zal g'oya va B-tree uchun dushman g'oya. Har bir yangi id tasodifiy bo'lgani uchun har bir insert indeksning ixtiyoriy barg sahifasiga tushadi. Indeks xotiraga sig'maydigan darajada katta jadvalda bu shuni anglatadi: har bir insert boshqa sahifani iflos qiladi, bufer lokalligi yo'qoladi, yozish amplifikatsiyasi o'sadi. Hech nima buzilmaydi. Shunchaki jadval hajmiga bog'liq ravishda sekinlashadi — shuning uchun jadval kattayib ketmaguncha buni sezish qiyin.
UUIDv7 yuqori bitlarga millisekundlik vaqt tamg'asini joylaydi. Vaqt jihatidan yaqin yaratilgan id'lar tartib bo'yicha ham yaqin turadi, shuning uchun insertlar indeksning eng o'ng sahifalarida to'planadi — bigserial beradigan kirish naqshining o'zi, lekin UUID tanlashingizga sabab bo'lgan xususiyatlar saqlanadi: mijoz tomonda hosil qilinadi, kelishuv talab qilmaydi, qatorlar sonini oshkor qilmaydi.
CREATE TABLE payment_events (
id uuid PRIMARY KEY DEFAULT uuidv7(),
payment_id uuid NOT NULL,
provider text NOT NULL,
raw_payload jsonb NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);18 dan oldin buni olish uchun pg_uuidv7 kengaytmasi kerak edi — bu kengaytma o'rnatishga ruxsat bermaydigan joyga deploy qilmaguningizcha yaxshi, keyin esa migratsiya muammosi. Uning yadroda bo'lishi butun bir muhit muzokarasi turkumini yo'q qiladi.
Bitta chindan foydali yon ta'sir: vaqt tamg'asi ichkarida bo'lgani uchun uuid_extract_timestamp(id) kalitning o'zidan yaratilish vaqtini beradi. Men bunga biznes mantiqni qurmagan bo'lardim — ustun aniqroq va id sxemasi o'zgarsa ham omon qoladi — lekin hodisalar logini tekshirish uchun bu ajoyib.
Sarlavhaga chiqmaydigan murosa
UUIDv7 vaqtni oshkor qiladi. Id'ni ushlab turgan har kim qator qachon yaratilganini millisekundgacha taxminan o'qiy oladi.
To'lov hodisalari logi uchun bu yaxshi — hatto foydali. Id foydalanuvchiga ko'rinadigan va yaratilish vaqti maxfiy bo'lgan joyda esa o'tishdan oldin o'ylab ko'ring. Agar ikkita id foydalanuvchiga A va B akkauntlari to'rt sekund farq bilan yaratilganini bildirsa, siz nimadir oshkor qildingiz. Odatda zararsiz, ba'zan yo'q — va bu keyin orqaga qaytarishdan ko'ra hozir o'ylab olish osonroq bo'lgan narsa.
Yangilash haqida
Menga eng yoqqan narsa imkoniyatlar ro'yxatida yo'q. pg_upgrade endi planner statistikasini olib o'ta oladi.
Ilgari yirik yangilash sizga bo'sh pg_statistic qoldirardi. Baza ko'tarilardi, ilova ulanardi, planner esa — umuman statistikasiz fikr yuritib — ANALYZE tugaguncha o'rtachadan halokatligacha bo'lgan rejalar tuzardi. Yangilash oynasi qisqa edi; tiklanish oynasi esa eng katta jadvallaringizda to'liq analyze qancha davom etsa shuncha edi, va aynan o'sha oynada hamma narsa buzilgandek ko'rinardi.
Statistikaning omon qolishi bu jarlikni yo'q qiladi. Yangilashdan keyingi xatti-harakat endi yangilashdan oldingiga o'xshaydi — yangilashdan kutadigan yagona narsangiz esa aynan shu.
Bunga tayanishdan oldin bitta istisnoni bilib qo'ygan ma'qul: kengaytirilgan statistika ko'chirilmaydi. CREATE STATISTICS obyektlari ta'rif sifatida omon qoladi, lekin ular hisoblab chiqqan ma'lumot yo'q bo'ladi. Ya'ni o'zaro bog'liq ustunlar uchun kengaytirilgan statistika qo'shgan bo'lsangiz — ko'p ustunli predikatda yomon qator bahosi bilan bir marta kurashgan bo'lsangiz, qo'shgansiz — ular bo'sh qaytadi va planner aynan siz ular uchun qurgan query'larda yana taxmin qila boshlaydi.
Shuning uchun keyin baribir analyze qiling. Aniqroq varianti — vacuumdb --all --analyze-in-stages --missing-stats-only: u omon qolmaganini to'ldiradi, omon qolganini qayta ishlamaydi. Lekin "yaqin orada analyze qiling" bilan "trafik kelguncha analyze qiling, aks holda sayt nega sekin ekanini tushuntirasiz" orasidagi farq — oddiy texnik xizmat oynasi bilan hodisa orasidagi farq.
Qaror qilayotgan odamga aytadiganim
Agar siz 15 yoki 16 da bo'lsangiz va odatiy tranzaksion yuk bilan ishlasangiz, asinxron I/O benchmark raqamlari uchun yangilamang — ular haqiqiy, lekin ular asosan sizniki bo'lmagan yukni tasvirlaydi.
Agar UUID birlamchi kalitlarni ishlatsangiz, uuidv7() uchun yangilang — u kengaytmasiz bosqichma-bosqich yomonlashuv manbasini yo'q qiladi. Agar yangilashdan keyingi yomon soatni boshdan kechirgan bo'lsangiz, statistikani saqlaydigan pg_upgrade uchun yangilang. Yetib borganingizda asinxron I/O ni yoqing, chunki vacuum'ning tezlashishi — sizni qutqargan kunigacha sezmaydigan sovg'a.
Manbalar: PostgreSQL 18.0 reliz eslatmalari; PostgreSQL 18 press kit.
Ruknlar


