Schema — nima, yaratish, search_path, public schema

~15 daq · PostgreSQL · Kirish va O'rnatish

Loyiha o'sdi. Jadvallar ko'paydi. Bir database ichida:

foydalanuvchilar
admin_foydalanuvchilar
mahsulotlar
arxiv_mahsulotlar
to'lovlar
arxiv_to'lovlar
hisobotlar
...

Hammasi bir joyda — tartibsiz, chalkash. Yangi dasturchi kelsa, qaysi jadval nima uchunligini tushunish qiyin. Jamoa bilan ishlasangiz — biri boshqasining jadvalini tasodifan o'chirib qo'yishi mumkin.

Bu muammoning yechimi — schema.


Schema nima?

Schema — database ichidagi papka. Xuddi kompyuteringizda hujjatlar, rasmlar, dasturlar uchun alohida papkalar bo'lganidek — database da ham jadvallar, viewlar, funksiyalar schemalar bo'yicha ajratiladi.

Hayotiy o'xshatma

Katta ofis binosi tasavvur qiling. Birinchi qavat — buxgalteriya, ikkinchi qavat — marketing, uchinchi qavat — IT. Har qavatning o'z xonalari (jadvallar) bor. Buxgalteriya xodimi marketing hujjatlariga kirish uchun alohida ruxsat kerak — o'z qavatida esa erkin ishlaydi.

Database — bino. Schema — qavat. Jadvallar — xonalar.

┌──────────────────────────────────────────────┐
│                mydb (database)               │
│                                              │
│  ┌────────────┐  ┌──────────┐  ┌──────────┐ │
│  │   public   │  │  admin   │  │ billing  │ │
│  │  (schema)  │  │ (schema) │  │ (schema) │ │
│  ├────────────┤  ├──────────┤  ├──────────┤ │
│  │foydalanuv. │  │ rollar   │  │ to'lovlar│ │
│  │mahsulotlar │  │ loglar   │  │ fakturalar│ │
│  │buyurtmalar │  │sozlamalar│  │          │ │
│  └────────────┘  └──────────┘  └──────────┘ │
└──────────────────────────────────────────────┘

Nima uchun schema kerak?

Tartib

Katta loyihalarda 50-100 ta jadval bo'lishi mumkin. Barchasini bir joyga yig'sangiz — qaysi jadval qaysi modulga tegishligini bilish qiyinlashadi. Schema bilan har modul o'z "qavatida":

public   → umumiy jadvallar
admin    → boshqaruv paneli
billing  → to'lov tizimi
reports  → hisobotlar

Xavfsizlik

Har bir schemaga alohida huquq beriladi. Misol: backend dasturchi billing schemaga kira olmaydi — faqat moliya moduli kiradi. Shunday qilib bitta database ichida turli jamoalar turli schemalar bilan ishlaydi, bir-birining ma'lumotlariga tegmaydi.

Bir nechta mijoz — Multi-tenant

Yirik SaaS loyihalarda har bir mijoz uchun alohida schema yaratiladi. Hammaning ma'lumotlari bitta database da, lekin to'liq ajratilgan:

tenant_alif   → Alif kompaniyasining jadvallari
tenant_uzum   → Uzum kompaniyasining jadvallari
tenant_payme  → Payme kompaniyasining jadvallari

Har schema ichida bir xil tuzilma — foydalanuvchilar, buyurtmalar, mahsulotlar — faqat ma'lumotlar alohida. Bitta so'rovda bir mijozning boshqasining ma'lumotini ko'rishi imkonsiz.


public schema — standart

PostgreSQL har yangi database yaratilganda avtomatik public nomli schema yaratadi. Siz hech qanday schema ko'rsatmasangiz — jadvallar public ga tushadi.

Kichik loyihalarda bu yetarli — hamma jadval bir joyda, schema bilan ovora bo'lishning hojati yo'q. Lekin loyiha o'sgach, modullar ko'paygach — alohida schemalar kerak bo'ladi.

-- Bu ikkalasi aynan bir xil
CREATE TABLE foydalanuvchilar (...);
CREATE TABLE public.foydalanuvchilar (...);

Schema yaratish va ishlatish

Schema yaratish oddiy:

CREATE SCHEMA admin;
CREATE SCHEMA billing;

Schema ichida jadval yaratishda uning nomini prefix qilib yoziladi:

CREATE TABLE admin.foydalanuvchilar (
    id   SERIAL PRIMARY KEY,
    ism  TEXT NOT NULL,
    rol  TEXT NOT NULL
);

CREATE TABLE billing.to'lovlar (
    id      SERIAL PRIMARY KEY,
    miqdor  NUMERIC(10, 2) NOT NULL,
    sana    TIMESTAMPTZ DEFAULT NOW()
);

Endi foydalanuvchilar jadvali ikki joyda — public.foydalanuvchilar va admin.foydalanuvchilar. Bular butunlay alohida jadvallar — bir-biriga aloqasi yo'q. So'rovda qaysi birini nazarda tutayotganingizni aniq ko'rsatish kerak:

SELECT * FROM public.foydalanuvchilar;   -- oddiy foydalanuvchilar
SELECT * FROM admin.foydalanuvchilar;    -- admin foydalanuvchilar
SELECT * FROM billing.to'lovlar;

search_path — schema ko'rsatmasangiz nima bo'ladi?

Har safar schema nomini yozish zerikarli. Shu sababli PostgreSQL da search_path mavjud — bu PostgreSQL ning "birinchi qayerdan qidiraman" ro'yxati.

Oddiy qilib aytganda: siz foydalanuvchilar deb yozsangiz — PostgreSQL search_path dagi schemalarni ketma-ket ko'rib chiqadi va birinchi topganini ishlatadi.

Standart search_path:

SHOW search_path;
-- "$user", public

"$user" — hozirgi foydalanuvchi nomi bilan bir xil schema. Agar admin foydalanuvchi bo'lsangiz — avval admin schemadan qidiradi, keyin public dan.

search_path ni o'zgartirish:

-- Faqat joriy sessiya uchun
SET search_path TO billing, public;

-- Endi schema yozmay ham billing jadvallari topiladi
SELECT * FROM to'lovlar;   -- billing.to'lovlar topiladi

Foydalanuvchi uchun doimiy o'rnatish — har safar SET yozmaslik uchun:

ALTER ROLE billing_user SET search_path TO billing, public;

Schemalarni ko'rish va o'chirish

-- Barcha schemalar ro'yxati
\dn

-- Schema ichidagi jadvallar
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'admin';

-- Schemani o'chirish — faqat bo'sh bo'lsa o'chadi
DROP SCHEMA admin;

-- Barcha jadvallar bilan birga o'chirish
DROP SCHEMA admin CASCADE;

⚠️ CASCADE bilan schema o'chirilsa — ichidagi barcha jadvallar va ularning ma'lumotlari ham yo'qoladi. Qaytarib bo'lmaydi.


Tez-tez uchraydigan xatolar

Schema ko'rsatmay boshqa schemadagi jadvalni qidirish

admin.foydalanuvchilar yaratilgan, lekin search_path da admin yo'q:

SELECT * FROM foydalanuvchilar;
-- ERROR: relation "foydalanuvchilar" does not exist

PostgreSQL public dan qidiradi, u yerda bu jadval yo'q — xato beradi. Ikki yechim:

-- 1. To'liq nom bilan
SELECT * FROM admin.foydalanuvchilar;

-- 2. search_path ga qo'shish
SET search_path TO admin, public;
SELECT * FROM foydalanuvchilar;  -- endi topiladi

Schema o'rniga alohida database yaratish

Ba'zilar har bir modul uchun alohida database yaratadi. Bu noto'g'ri — modular bir-birining ma'lumotiga JOIN qila olmaydi, ulanish boshqaruvi murakkablashadi.

❌ billing_db, admin_db, main_db — uchta alohida database
✅ mydb ichida billing, admin, public — uchta schema

Alohida database faqat butunlay mustaqil loyihalar uchun — masalan, ikki turli mahsulot.

public schemani o'chirish

Ko'p extension lar public schemaga o'rnatiladi. public o'chirilsa — ular ishlashni to'xtatishi mumkin. O'chirish o'rniga huquqlarni cheklash yaxshiroq.


Xulosa

Schema — database ichidagi papka. Jadvallar va boshqa ob'ektlar schemalar bo'yicha ajratiladi.

Nima uchun kerak: katta loyihalarda tartib, jamoalar orasida xavfsizlik, multi-tenant arxitektura.

public — standart schema. Schema ko'rsatilmasa, jadvallar public ga tushadi.

search_path — PostgreSQL jadval nomini schemalar ro'yxatidan ketma-ket qidiradi. O'zgartirilmasa: avval "$user", keyin public.


Keyingi dars

6-dars: CREATE TABLE — constraints, PRIMARY KEY, FOREIGN KEY, CHECK