PostgreSQL Indexing nâng cao: B-tree, Hash, GIN, GiST, BRIN cho hiệu năng tối đa

PostgreSQL Indexing nâng cao: B-tree, Hash, GIN, GiST, BRIN cho hiệu năng tối đa

PostgreSQL cung cấp 6 loại index chính: B-tree (mặc định), Hash, GIN, GiST, SP-GiST và BRIN. Mỗi loại tối ưu cho một kiểu truy vấn và dữ liệu cụ thể. Hiểu rõ đặc điểm từng loại giúp bạn tránh over-indexing (tốn disk, chậm write) và under-indexing (truy vấn chậm, sequential scan).

Quy tắc vàng: chỉ index cột xuất hiện trong WHERE, JOIN, ORDER BY, GROUP BY. Index không phải miễn phí — mỗi INSERT/UPDATE/DELETE phải cập nhật thêm index, làm chậm write throughput. Chỉ index khi select ratio đủ lớn (thường >5-10% rows).

B-tree: Index đa năng cho so sánh và sắp xếp

B-tree là mặc định, hỗ trợ mọi phép so sánh: =, , =, BETWEEN, IN, IS NULL, LIKE ‘prefix%’. Cũng hỗ trợ ORDER BY và GROUP BY nếu sort order khớp index. Phù hợp cho khóa chính, khóa ngoại, timestamp, ID dạng UUID có sort.

-- Index B-tree mặc định
CREATE INDEX idx_users_email ON users(email);

-- B-tree descending cho ORDER BY timestamp DESC
CREATE INDEX idx_logs_created_at ON logs(created_at DESC);

-- Partial index: chỉ index rows active
CREATE INDEX idx_orders_pending ON orders(user_id) WHERE status = 'pending';

Partial index giảm kích thước đáng kể khi lọc tập nhỏ. Covering index (INCLUDE) giúp index-only scan mà không cần lookup heap tuple.

Hash: Tốc độ tối đa cho equality check

Hash index chỉ hỗ trợ =, không hỗ trợ range hay ordering. Kích thước nhỏ hơn B-tree, tốc độ O(1) cho exact match. PostgreSQL 10+ có WAL logging cho Hash nên crash-safe. Dùng cho lookup key-value, session ID, cache invalidation.

-- Hash index cho exact match
CREATE INDEX idx_sessions_token ON sessions USING hash(session_token);

-- Not used: WHERE token LIKE 'abc%'  -- sequential scan

GIN: Inverted index cho array, JSONB, full-text search

Generalized Inverted Index lưu mapping từ element đến list row chứa nó. Hoàn hảo cho array, tsvector, jsonb với @>, ?, ?|, ?& operators. GIN hỗ trợ fastupdate (pending list) để giảm overhead write.

-- GIN cho full-text search tiếng Việt
CREATE INDEX idx_articles_content ON articles USING gin(to_tsvector('vietnamese', content));

-- GIN cho JSONB query
CREATE INDEX idx_products_attrs ON products USING gin(attributes);

-- GIN cho array tags
CREATE INDEX idx_posts_tags ON posts USING gin(tags);

GiST: Index không gian, geo, và range type

Generalized Search Tree cho phép định nghĩa operator class tùy biến. Hỗ trợ PostGIS geometry (&&, @>, <@, ), range types (int4range, tsrange), và cube. Dùng cho truy vấn khoảng cách, giao nhau, bao quanh.

-- GiST cho PostGIS point
CREATE INDEX idx_places_location ON places USING gist(geom);

-- GiST cho range type (booking, scheduling)
CREATE INDEX idx_room_booking ON rooms USING gist(booking_period);

BRIN: Block Range Index cho bảng khổng lồ, dữ liệu có order tự nhiên

Block Range Index lưu min/max của từng block range (mặc định 128 pages). Chỉ hoạt động tốt khi dữ liệu vật lý tương quan với logic (timestamp tự tăng, ID tự tăng). Kích thước cực nhỏ (KB cho TB data), write gần như zero overhead.

-- BRIN cho log table theo thời gian
CREATE INDEX idx_logs_ts_brin ON logs USING brin(created_at) WITH (pages_per_range = 128);

-- BRIN cho big serial ID
CREATE INDEX idx_events_id_brin ON events USING brin(id);

So sánh nhanh: chọn loại nào?

Loại Phù hợp Không phù hợp Kích thước
B-tree Equality, range, sort, PK/FK Array, JSON, full-text Trung bình
Hash Equality only, high cardinality Range, sort, LIKE prefix Nhỏ
GIN Array, JSONB, full-text, @> Range, sort Lớn (fastupdate giúp)
GiST Geo, range, custom operators Equality only Trung bình
BRIN Big table, ordered data, timestamp Random data, small table Rất nhỏ

Best practices

  • Dùng EXPLAIN ANALYZE để verify index được dùng (Index Scan vs Seq Scan)
  • Multi-column index: thứ tự cột quan trọng (equality trước, range sau)
  • REINDEX định kỳ cho index bị bloat (bloat > 30% thì reindex)
  • Monitor pg_stat_user_indexes.idx_scan = 0 để tìm index không dùng
  • Kết hợp partial index + covering index cho workload cụ thể

Không có “index tốt nhất”, chỉ có index đúng cho workload của bạn. Hãy đo lường, test, và điều chỉnh — PostgreSQL EXPLAIN (ANALYZE, BUFFERS) là công cụ tin cậy nhất để dẫn đường.

Tham khảo thêm: PostgreSQL Documentation – IndexesUse The Index, Luke! cho design pattern indexing chuyên sâu.

Bảng so sánh các loại index PostgreSQL và trường hợp sử dụng

Multi-column index: thứ tự cột quan trọng (equality trước, range sau).

Sơ đồ cấu trúc B-tree và BRIN index trong PostgreSQL

Monitor pg_stat_user_indexes.idx_scan = 0 để tìm index không dùng.

Tôi là một lập trình viên IOS. Code chính là IOS nhưng thỉnnh thoảng vẫn đá sang Android hoặc web. Mặc dù không quá thông thạo nhưng tôi sẽ chia sẻ những kiến thức mà mình đã tìm hiểu, áp dụng qua.

Bài viết liên quan

WebRTC là gì? Kết nối P2P thời gian thực cho web

WebRTC là gì? Kết nối P2P thời gian thực cho web WebRTC (Web Real-Time Communication) là bộ API trình duyệt cho phép truyền audio, video, data trực tiếp giữa các…

Xem thêm

Database Sharding là gì? Chiến lược chia dữ liệu cho hệ thống lớn

Khi website hay ứng dụng phát triển nhanh, lượng người dùng và dữ liệu tăng gấp hàng triệu lần, database đơn lẻ trở thành điểm nghẽn. Database sharding là kỹ…

Xem thêm

Astro Framework: Island Architecture cho web hiệu năng cao

Astro là gì? Astro là framework web hiện đại xây dựng dựa trên kiến trúc Island Architecture, tập trung tối ưu hiệu suất bằng cách gửi HTML tĩnh đến trình…

Xem thêm
0 0 đánh giá
Article Rating
Theo dõi
Thông báo của
guest
0 Comments
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất