EXPLAIN ба query оновчлол
Асуулга удаан ажиллаж байна — гэхдээ яагаад удааширч байгааг мэдэхгүй бол юу засах вэ? EXPLAIN нь PostgreSQL-н асуулга яг яаж гүйцэтгэж байгааг харуулдаг хамгийн чухал оношилгооны хэрэгсэл юм. Энэ хичээлийг эзэмшвэл "асуулга удаан байна" гэсэн шалтгааныг өөрөө тодорхойлж засах чадвартай болно.
EXPLAIN — гүйцэтгэлийн төлөвлөгөө
EXPLAIN нь асуулгыг гүйцэтгэлгүй төлөвлөгөөг харуулна:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INT NOT NULL,
amount NUMERIC NOT NULL,
status TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 100,000 мөр оруулах
INSERT INTO orders (customer_id, amount, status)
SELECT
(RANDOM() * 1000)::INT,
(RANDOM() * 100000)::NUMERIC,
(ARRAY['pending','completed','cancelled'])[(RANDOM()*2+1)::INT]
FROM GENERATE_SERIES(1, 100000);
-- Индексгүй үед
EXPLAIN SELECT * FROM orders WHERE customer_id = 42;
Гаралт:
Seq Scan on orders (cost=0.00..2137.00 rows=100 width=44)
Filter: (customer_id = 42)
Seq Scan нь бүх мөрийг нэг нэгээр уншиж байгааг (Sequential Scan) харуулна. cost=0.00..2137.00 нь эхлэх ба дуусах зардлын тооцоо юм.
EXPLAIN ANALYZE — бодит хэмжилт
EXPLAIN ANALYZE нь асуулгыг бодитоор гүйцэтгэж бодит цагийг хэмжинэ:
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 42;
Гаралт:
Seq Scan on orders (cost=0.00..2137.00 rows=100 width=44)
(actual time=0.041..18.327 rows=97 loops=1)
Filter: (customer_id = 42)
Rows Removed by Filter: 99903
Planning Time: 0.085 ms
Execution Time: 18.412 ms
actual time=0.041..18.327 нь бодит эхлэх ба дуусах цаг (миллисекунд). Rows Removed by Filter: 99903 нь 99,903 мөрийг уншаад хаясан гэсэн утга — энэ нь индекс дутаж байгааг илтгэнэ.
-- Индекс нэмэх
CREATE INDEX idx_orders_customer ON orders (customer_id);
-- Дахин шалгах
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 42;
Шинэ гаралт:
Index Scan using idx_orders_customer on orders
(cost=0.29..212.58 rows=97 width=44)
(actual time=0.045..0.412 rows=97 loops=1)
Index Cond: (customer_id = 42)
Execution Time: 0.451 ms
18ms → 0.45ms болж 40 дахин хурдассан.
Гол нэр томьёонуудыг унших
EXPLAIN гаралтын хамгийн чухал нэр томьёонууд:
-- Олон JOIN-тэй асуулга шинжлэх
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT o.id, o.amount, c.name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.status = 'completed'
AND o.amount > 50000
ORDER BY o.created_at DESC
LIMIT 20;
| Нэр томьёо | Утга |
|------------|------|
| Seq Scan | Бүх мөр уншиж байна — индекс хэрэгтэй байж болно |
| Index Scan | Индексээр хайж байна — сайн |
| Index Only Scan | Индексээс шууд уншиж байна — хамгийн хурдан |
| Hash Join | Жижиг хүснэгтийг санах ойд хадгалж JOIN хийж байна |
| Nested Loop | Мөр бүрт давталт хийж байна — том хүснэгтэд удаан |
| Sort | Эрэмбэлж байна — индексээр шийдэж болох эсэхийг бод |
| rows= | Тооцооллын мөрийн тоо (бодиттой ялгаа их байвал ANALYZE хийх) |
Нийтлэг удааширлын шалтгаан ба шийдэл
-- 1. Индексгүй баганаар шүүх
-- Асуудал: Seq Scan
-- Шийдэл:
CREATE INDEX ON orders (status);
CREATE INDEX ON orders (created_at DESC);
-- 2. Хэрэглэгдэхгүй байгаа индекс — статистик хуучирсан
-- Шийдэл:
ANALYZE orders;
-- 3. N+1 асуудал — давтан JOIN хийж байна
-- Асуудал: Nested Loop with many loops
-- Шийдэл: нэг асуулгад JOIN нэгтгэх
-- 4. LIKE хайлт индекс ашиглахгүй
-- Асуудал:
EXPLAIN SELECT * FROM orders WHERE status LIKE '%complet%';
-- Шийдэл: full-text search эсвэл trigram индекс ашиглах
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX ON orders USING GIN (status gin_trgm_ops);
EXPLAIN гаралтыг дүрслэн харах
Нарийн төвөгтэй асуулгад EXPLAIN гаралтыг визуал хэлбэрт хөрвүүлж харах сайтууд байдаг:
-- JSON форматаар гаргаж визуал хэрэгсэлд оруулах
EXPLAIN (ANALYZE, FORMAT JSON)
SELECT * FROM orders WHERE customer_id = 42;
explain.dalibo.com сайтад JSON гаралтыг оруулбал гүйцэтгэлийн мод хэлбэрээр дүрслэн харуулна — ялангуяа олон JOIN-тэй асуулгад маш тустай.
Дараагийн хичээлд:
Нэг PostgreSQL сервертэй систем доголдвол бүх зүйл зогсоно. Replication нь өгөгдлийг хэд хэдэн серверт хуулж, найдвартай байдал ба уншилтын гүйцэтгэлийг нэмэгдүүлдэг — үндсийг нь сурна.