Хүснэгт хуваалт (Partitioning)
Захиалгын систем таван жил ажиллаад хүснэгтэд 200 сая мөр хуримтлагдсан гэж бодъё. Асуулга улам удааширч, DELETE хэтэрхий цаг авч, индекс маш том болсон. Partitioning бол нэг том хүснэгтийг олон жижиг partition хэсгүүдэд задлах PostgreSQL-н шийдэл юм. Гадаад байдлаас нэг хүснэгт мэт харагдах ч дотооддоо хэд хэдэн тусдаа файлд хадгалагддаг.
Partitioning-н ашиг тус
- Хайлт хурдасна — PostgreSQL зөвхөн хамааралтай partition-уудыг уншдаг (partition pruning)
- Хуучин өгөгдөл хялбар устгагдана — нэг partition-г дусааж (
DROP) болно - Индекс жижгэрнэ — partition тус бүр өөрийн жижиг индекстэй
- Backup хялбарна — хуучин partition-уудыг тусад нь архивлаж болно
RANGE partitioning — мужаар хуваах
Огноо, тоон утгаар хуваах хамгийн нийтлэг арга:
-- Эх хүснэгт (partitioned table)
CREATE TABLE orders (
id BIGSERIAL,
customer_id INT NOT NULL,
amount NUMERIC NOT NULL,
status TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
) PARTITION BY RANGE (created_at);
-- 2023 оны partition
CREATE TABLE orders_2023
PARTITION OF orders
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
-- 2024 оны partition
CREATE TABLE orders_2024
PARTITION OF orders
FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
-- 2025 оны partition
CREATE TABLE orders_2025
PARTITION OF orders
FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');
-- Индекс үүсгэх (partition тус бүрт хамаарна)
CREATE INDEX ON orders (created_at);
CREATE INDEX ON orders (customer_id);
-- Мэдээлэл оруулах — автоматаар зөв partition-д очно
INSERT INTO orders (customer_id, amount, status, created_at)
VALUES (1, 50000, 'completed', '2024-03-15 10:00:00');
-- orders_2024 partition-д хадгалагдана
-- Хайлт — PostgreSQL зөвхөн 2024 partition-г уншина
EXPLAIN SELECT * FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01';
-- Гаралтад: "orders_2024" л скан хийгдэнэ
LIST partitioning — утгаар хуваах
Тодорхой утгуудын жагсаалтаар хуваах:
CREATE TABLE products (
id BIGSERIAL,
name TEXT NOT NULL,
category TEXT NOT NULL,
price NUMERIC NOT NULL
) PARTITION BY LIST (category);
CREATE TABLE products_electronics
PARTITION OF products
FOR VALUES IN ('электроник', 'гар утас', 'компьютер');
CREATE TABLE products_clothing
PARTITION OF products
FOR VALUES IN ('хувцас', 'гутал', 'дагалдах хэрэгсэл');
CREATE TABLE products_other
PARTITION OF products
FOR VALUES IN ('бусад');
HASH partitioning — тэнцүү хуваах
Өгөгдлийг тэнцүү хэмжээгээр хуваахад хэрэглэнэ:
CREATE TABLE users (
id BIGSERIAL,
username TEXT NOT NULL,
email TEXT NOT NULL
) PARTITION BY HASH (id);
-- 4 тэнцүү хэсэгт хуваах
CREATE TABLE users_p0 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE users_p1 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE users_p2 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE users_p3 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 3);
Partition удирдах
-- Байгаа partition-уудыг харах
SELECT
child.relname AS partition_нэр,
pg_get_expr(child.relpartbound, child.oid) AS хязгаар
FROM pg_inherits
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
WHERE parent.relname = 'orders';
-- Хуучин partition устгах (маш хурдан — бүх мөрийг нэг нэгээр устгахгүй)
DROP TABLE orders_2023;
-- Partition-г тусдаа хүснэгт болгон салгах (өгөгдлийг хадгалж)
ALTER TABLE orders DETACH PARTITION orders_2023;
-- Байгаа хүснэгтийг partition болгон нэмэх
ALTER TABLE orders ATTACH PARTITION orders_2023
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
Partitioning нь хэдэн сая мөртэй хүснэгтэд утга гардаг. Жижиг хүснэгтэд нэмэлт нарийн төвөгтэй байдал л нэмнэ — тиймээс өгөгдлийн хэмжээ томорч байж л ашиглах нь зүйтэй.
Дараагийн хичээлд:
PostgreSQL-н дотоод "цэвэрлэгч" болох VACUUM ба ANALYZE командуудыг сурна — өгөгдлийн санг эрүүл, хурдан байлгах арга.