UUID — gen_random_uuid, uuid-ossp extension

~10 daq · PostgreSQL · PostgreSQL Maxsus Imkoniyatlari

Muammodan boshlaylik

Jadvalda SERIAL bilan avtomatik ID berasiz: 1, 2, 3, 4... Oddiy va qulay. Lekin ba'zi hollarda muammo chiqadi:

Ikki alohida serverda ma'lumot yaratildi — birinchisida ID=5, ikkinchisida ham ID=5. Ularni birlashtirishda to'qnashuv.

Yoki API orqali qaysi ID lar mavjudligini taxmin qilish mumkin — /users/1, /users/2, /users/3... Xavfsizlik nuqtai nazaridan bu yomon.

Yechim — UUID: har safar yagona, taxmin qilib bo'lmaydigan ID.


UUID nima?

UUID (Universally Unique Identifier) — 128 bitli yagona identifikator. Ko'rinishi:

550e8400-e29b-41d4-a716-446655440000

8-4-4-4-12 hexadecimal raqamlar, defis bilan ajratilgan.

Hayotiy o'xshatma: pasport raqami. Dunyoning istalgan nuqtasida yangi pasport berilsa — avval berilgan hech bir pasport raqami bilan to'qnashmaydi. UUID — shunday global yagona raqam.

SERIAL:                        UUID:
───────────────────────        ────────────────────────────────────────
1, 2, 3, 4, 5...               550e8400-e29b-41d4-a716-446655440000
Taxmin qilish oson             Taxmin qilib bo'lmaydi
Serverlar orasida to'qnashadi  Har qanday serverda yagona
Ketma-ket — tartib seziladi    Tartibsiz — URL dan narsa sezilmaydi

UUID ishlatish

PostgreSQL 13 va undan yuqori — gen_random_uuid()

PostgreSQL 13 dan boshlab extension kerak emas — gen_random_uuid() built-in:

SELECT gen_random_uuid();
-- a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

Har safar chaqirilganda yangi, yagona UUID qaytaradi.

CREATE TABLE foydalanuvchilar (
  id     UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  ism    TEXT NOT NULL,
  email  TEXT UNIQUE NOT NULL
);

INSERT INTO foydalanuvchilar (ism, email)
VALUES ('Ali', 'ali@mail.com');
-- id avtomatik: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

DEFAULT gen_random_uuid() — qo'shish vaqtida avtomatik UUID yaratiladi.

uuid-ossp extension — eski versiyalar uchun

PostgreSQL 12 va eski versiyalarda:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

SELECT uuid_generate_v4();
-- 6ba7b810-9dad-11d1-80b4-00c04fd430c8

uuid_generate_v4() — tasodifiy UUID (gen_random_uuid() ga o'xshash).

CREATE TABLE foydalanuvchilar (
  id     UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  ism    TEXT
);

UUID versiyalari

UUID ning bir nechta versiyasi bor. Eng ko'p ishlatiladiganlari:

v1 → vaqt + MAC adres asosida. Tartiblash mumkin, lekin MAC adres oshkor bo'ladi.
v4 → to'liq tasodifiy. Eng keng tarqalgan. gen_random_uuid() shu.
v7 → vaqt + tasodifiy (PostgreSQL 17+). Tartiblash mumkin, v4 xavfsizligi.

Amalda v4 — standart tanlov. Tartiblash kerak bo'lsa — v7 (PostgreSQL 17+):

-- PostgreSQL 17+
SELECT gen_random_uuid(); -- v4
SELECT uuidv7();          -- v7 (vaqt asosida, tartiblash mumkin)

UUID va SERIAL — qachon qaysi?

SERIAL/BIGSERIAL:                UUID:
─────────────────────────────    ─────────────────────────────────
Kichik hajm (4/8 bayt)           Katta hajm (16 bayt)
Tez join (integer taqqoslash)    Sekinroq join
Oddiy o'qiladi (1, 2, 3)        O'qilishi qiyin
URL da ketma-ketlik seziladi     URL da hech narsa sezilmaydi
Bir server uchun yaxshi           Taqsimlangan tizim uchun yaxshi

SERIAL tanlang:

  • Oddiy ilova, bitta server
  • JOIN ko'p, performance muhim
  • Foydalanuvchiga ID ko'rsatilmaydi

UUID tanlang:

  • Taqsimlangan tizim, bir nechta server
  • Tashqi API — ID URL da ko'rinadi
  • Xavfsizlik muhim — ID ni taxmin qilish mumkin bo'lmasligi kerak
  • Ma'lumotlarni serverlar o'rtasida birlashtirish kerak

Amaliy misol

CREATE TABLE buyurtmalar (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  foydalanuvchi_id  UUID NOT NULL REFERENCES foydalanuvchilar(id),
  mahsulot          TEXT,
  sana              TIMESTAMPTZ DEFAULT now()
);

INSERT INTO buyurtmalar (foydalanuvchi_id, mahsulot)
VALUES ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', 'Noutbuk');

-- UUID bo'yicha qidirish
SELECT * FROM buyurtmalar
WHERE id = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';

Node.js dan UUID uzatish — matn sifatida, PostgreSQL avtomatik UUID turiga o'giradi:

const result = await pool.query(
  'SELECT * FROM buyurtmalar WHERE id = $1',
  ['a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11']
);

Tez-tez uchraydigan xatolar

UUID ni TEXT sifatida saqlash:

-- ❌ — UUID ni TEXT da saqlash — indeks sekin, xato ID qabul qilinishi mumkin
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::TEXT

-- ✅ — UUID turi — validatsiya bor, indeks optimal
id UUID PRIMARY KEY DEFAULT gen_random_uuid()

UUID turida saqlash ikki afzallik beradi: noto'g'ri format kiritilsa xato beradi, va indeks kichikroq.

Extension ni eski versiyada unutish:

-- ❌ — PostgreSQL 12 da gen_random_uuid() yo'q
CREATE TABLE t (id UUID DEFAULT gen_random_uuid());
-- ERROR: function gen_random_uuid() does not exist

-- ✅ — extension qo'shib, uuid_generate_v4() ishlatish
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE t (id UUID DEFAULT uuid_generate_v4());

Xulosa

UUID — global yagona identifikator. Taqsimlangan tizimlar, xavfsizlik muhim bo'lgan API lar, serverlar orasida ma'lumot almashishda SERIAL dan ustun.

gen_random_uuid()    → PostgreSQL 13+ (built-in, v4)
uuid_generate_v4()   → uuid-ossp extension (eski versiyalar)

Oddiy qoida: bitta server, ichki tizim → BIGSERIAL. Ko'p server, tashqi API, URL da ID → UUID.


Keyingi dars

28-dars: ENUM type — yaratish, ishlatish, o'zgartirish