// Khoá 2 / Database Deep Dive

Hiểu Postgres làm gìbên dưới câu SELECT

Bạn viết được query. ORM chạy được. Nhưng khi chậm, bạn không biết bắt đầu nhìn vào đâu. Khoá này cài mental model từng tầng: cách Postgres lưu 1 row trên heap page, cách B-tree tìm ctid, cách planner chọn join algorithm dựa vào statistic. Đọc EXPLAIN như đọc code, không phải nhìn rồi bỏ qua.

Xem nội dung
EXPLAIN ANALYZE
Before4823 ms
Seq Scan on orders  rows=12  Filter: user_id=42 AND status='paid'  Rows Removed: 3,841,209Execution: 4823 ms
After0.089 ms
Nested Loop  rows=12  Index Scan on users  rows=1    Index Cond: id = 42  Index Scan on orders  rows=12    Index Cond: user_id = 42    Filter: status = 'paid'Execution: 0.089 ms
Index Scanactual rowscost estimate// đọc bottom-up

// Approach

Khoá này dạy hiểu bản chất, không dạy lý thuyết kiểu mẹo

Mọi engineer làm việc với Postgres đứng ở 1 trong 3 lớp dưới. Lớp càng cao, bạn hiểu Postgres càng sâu, diagnose vấn đề càng nhanh.

Khoá này dạy lớp này

Lớp 3

Physical

Page trên đĩa, ctid, B-tree leaf, cost model, MVCC tem

Bạn biết
Data sống ở đâu vật lý, Postgres ra quyết định thế nào, vì sao 1 query slow.
Khả năng
Predict plan trước khi chạy. Diagnose 1 incident trong 15 phút. Tune autovacuum với reasoning.

Lớp 2

Mechanical

Index, EXPLAIN, vacuum, replication, partitioning

Bạn biết
Tools tồn tại, biết cú pháp dùng, hiểu loose rules kiểu 'dùng index cho equality, không dùng cho LIKE %'.
Khả năng
Làm việc với case bình thường. Khi gặp case khác thường thì gambling, thử-sai, copy Stack Overflow.

Các khoá Postgres performance khác dạy lớp này.

Lớp 1

Surface

SELECT, JOIN, WHERE, GROUP BY, INSERT, UPDATE

Bạn biết
Viết query, kết quả ra đúng dữ liệu.
Khả năng
Build CRUD application. Không tune được.

Lớp này không dạy ở khoá này, giả định bạn đã có.

Hầu hết tài liệu Postgres ngoài kia dừng ở lớp 2: liệt kê index types, paste EXPLAIN, kèm vài rule of thumb. Khoá này đi xuống lớp 3 để mỗi rule ở lớp 2 tự khắc có lý do.

// The Reality Check

5 thứ về Postgres bạn chưa biết, dù đã viết query mỗi ngày

Không phải bạn kém. Là không ai chỉ phần này. Production biết, tutorial bỏ qua.

ORM chạy, query ra kết quả, app lên prod. Cho đến khi table có 2 triệu dòng.

Lý thuyết

Cứ viết SELECT, Postgres lo phần còn lại.

Production thực tế

Postgres đọc dữ liệu theo page 8KB. 1 câu SELECT không index có thể đọc hàng nghìn page dù chỉ lấy 10 dòng. Dev không biết điều này sẽ không hiểu tại sao query nhanh ở dev, chậm ở prod khi data tăng lên.

Lý thuyết

Thêm index là xong. Index nào cũng như nhau.

Production thực tế

Index sai order trong composite index = planner không dùng được. Partial index, covering index, expression index giải quyết các bài toán hoàn toàn khác nhau. Thêm index mà không hiểu B-tree = đoán mò, đôi khi còn làm chậm hơn.

Lý thuyết

EXPLAIN chạy ra block dài, nhìn qua là hiểu.

Production thực tế

EXPLAIN đọc bottom-up. Cost là estimate, không phải thực tế. Rows estimate sai 10 lần là bình thường khi statistic lỗi thời. Không hiểu cấu trúc planner output = không debug được slow query.

Lý thuyết

Transaction là transaction. MVCC là tính năng Postgres tự lo.

Production thực tế

MVCC sinh dead tuple mỗi khi UPDATE hoặc DELETE. Dead tuple chồng lên làm bảng phình to, index phình to, query chậm dần. Hiểu xmin/xmax mới hiểu tại sao vacuum cần chạy và khi nào bloat trở thành vấn đề.

Lý thuyết

Managed Postgres (RDS, Supabase, Neon) lo hết, không cần hiểu internals.

Production thực tế

Cloud lo infra, không lo schema sai và index sai. Seq Scan trên table 5 triệu dòng tốn tiền như nhau dù chạy trên RDS hay self-hosted. Mental model internals giúp bạn debug được trên mọi deployment, không chỉ trên máy local.

Những thứ này không có trong tutorial ORM. Nhưng production hỏi đến ngay khi data bắt đầu lớn.

4 tình huống quen thuộc khi production bắt đầu nói chuyện

Không phải drama. Đây là tình huống thật của dev backend VN khi table bắt đầu có vài trăm nghìn dòng.

Query nhanh ở dev, chậm ở prod

Dev chạy với 500 dòng test data, dưới 10ms. Prod có 3 triệu dòng, cùng câu query đó: 8 giây. Bạn thêm index nhưng không biết index đúng loại nào, đúng thứ tự columns nào. Planner vẫn chọn Seq Scan vì statistic lỗi thời. Không biết storage layer và cost model, bạn chỉ có thể đoán.

EXPLAIN ra block dài, không biết đọc từ đâu

Chạy EXPLAIN ANALYZE, nhìn vào output dài 40 dòng với Nested Loop, Hash Join, cost=0.00..8472.13, rows=1. Bạn không biết nên nhìn vào node nào, rows estimate sai ở đâu, tại sao planner không chọn index có sẵn. Đọc tài liệu online vẫn không map được lý thuyết vào output thực tế.

App toang vì lock, không biết lock từ đâu

Batch job chạy ban đêm UPDATE nhiều dòng. Sáng ra: request timeout hàng loạt, connection pool hết slot, log đầy 'waiting for lock'. Bạn không hiểu MVCC, không biết tại sao UPDATE sinh dead tuple, không biết lock granularity. Restart app là xong tạm, nhưng hôm sau lại xảy ra.

Thêm index mà query không nhanh hơn

Index đã có trên cột filter, nhưng EXPLAIN vẫn hiện Seq Scan. Hoặc có Index Scan nhưng query vẫn chậm vì planner estimate rows sai 100 lần. Bạn chạy ANALYZE, REINDEX, restart, vẫn không hiểu tại sao planner không dùng index bạn tạo. Không hiểu pg_statistic và selectivity, bạn không có chỗ tiếp tục debug.

// Myth-Buster

4 ngộ nhận về Postgres khiến dev viết code không debug được

Không phải bạn tin những thứ này vì dốt. Tutorial và ORM docs không nói ngược lại. Production mới nói.

ORM giải quyết rất tốt phần syntax. Nhưng ORM không giải thích tại sao query sinh ra từ nó chậm, không giải thích planner chọn gì, không giải thích bloat từ đâu. Phần đó dev phải tự biết.

Ngộ nhận của fresher

"ORM lo hết, không cần hiểu internals."

Reality check

ORM sinh ra SQL, Postgres chạy SQL đó. Query plan, index selection, vacuum: ORM không can thiệp được. Prisma hay Drizzle không ngăn được Seq Scan trên table 5 triệu dòng nếu schema hoặc index sai. Internals là tầng bên dưới ORM, ORM không che được nó.

Ngộ nhận của fresher

"Postgres tự tune được, cứ để mặc định là chạy tốt."

Reality check

Mặc định Postgres đủ để chạy. Không đủ để chạy tốt khi data lớn. Nhưng vấn đề thật hiếm khi là params: shared_buffers hay work_mem. Vấn đề thật thường là schema sai, index sai, statistic lỗi thời. Tune params mà schema và index vẫn sai: không giúp được gì.

Ngộ nhận của fresher

"Cần học thuộc hết postgresql.conf mới gọi là biết Postgres."

Reality check

postgresql.conf có hàng trăm params. Dev không cần nhớ hết, DBA cũng không nhớ hết. Thứ dev cần là hiểu cách planner đọc statistic để chọn plan, hiểu cách MVCC sinh dead tuple, hiểu khi nào index type nào phù hợp. Đó là nền tảng dùng được mỗi ngày.

Ngộ nhận của fresher

"DBA lo mấy chuyện performance này, dev chỉ cần viết query đúng."

Reality check

DBA lo infra và config. Schema sai, index sai, query sinh bloat: dev design ra, dev phải hiểu. DBA không thể sửa schema đã deploy lên production với dữ liệu thật mà không có downtime. Code thiết kế bad schema từ đầu, chi phí fix sau tăng theo cấp số nhân.

Hiểu internals không có nghĩa là trở thành DBA. Có nghĩa là khi query chậm, bạn biết nhìn vào đâu và tự debug được.

// Bạn đang nghĩ

"Tao chỉ viết REST API, học internals Postgres làm gì?"

Câu này hợp lý khi app mới đi prod với 1.000 users. Không còn hợp lý khi table có 2 triệu dòng và khách hàng bắt đầu complain.

  1. Lý do #1

    API chậm thì DB chậm là gốc rễ

    Phần lớn REST API endpoint chậm không phải vì business logic phức tạp, mà vì 1 hoặc vài câu query bên dưới. N+1 query từ ORM, Seq Scan vì thiếu index, Hash Join trên bảng không có statistic tốt. Debug được API performance = debug được DB performance. Hai thứ không tách rời nhau.

  2. Lý do #2

    "Đọc Use The Index Luke đủ rồi" vẫn còn 1 khoảng trống

    Use The Index Luke giải thích B-tree rất tốt. Nhưng không đi vào cách map sang ORM Prisma hay Drizzle thực tế, không có production case study VN, không có narrative từ storage đến planner đến MVCC theo thứ tự học hợp lý. Đọc xong bạn có kiến thức rời, chưa có mental model liên kết.

  3. Lý do #3

    Xài Supabase hay Neon không che được schema sai

    Managed Postgres lo server, backup, replication. Không lo cho bạn schema thiếu index, query sinh Seq Scan, MVCC bloat vì batch UPDATE không có vacuum kịp. Cloud không thêm index tự động, không rewrite query cho bạn. Mental model internals dùng được trên mọi Postgres deployment.

  4. Lý do #4

    Internals là thứ bạn học 1 lần, dùng được cả career

    Storage page 8KB, B-tree traversal, cost model, MVCC: những concept này không thay đổi giữa Postgres 14, 15, 16, 17. Không thay đổi giữa self-hosted và cloud. Không thay đổi khi bạn đổi ORM. Đầu tư 1 lần vào mental model nền tảng, không bị obsolete sau 2 năm như framework docs.

Không cần trở thành DBA. Chỉ cần đủ hiểu để tự debug được khi production chậm, không phải đợi DBA hoặc gửi ticket lên team platform.

// Entry barrier

Khoá KHÔNG bắt học thuộc params, KHÔNG bắt vẽ B-tree trên giấy

Bạn không cần đọc paper Stonebraker hay thuộc postgresql.conf để học được. Khoá đi từ vấn đề thực, lý thuyết đến sau khi bạn đã thấy cần.

Không cần học thuộc 50 params trong postgresql.conf

Params như shared_buffers, work_mem, effective_cache_size: quan trọng với DBA tuning server. Dev cần hiểu tại sao planner chọn plan này thay vì plan kia, tại sao index không được dùng, tại sao vacuum cần chạy. Đó là câu hỏi thật hàng ngày, không phải config server.

Không cần vẽ B-tree trên giấy như đại học

Đại học vẽ B-tree là để thi. Khoá này mở pg_btree_page_items thật trong Postgres docker, đọc page layout thật. Bạn hiểu bằng cách làm, không bằng cách nhớ định nghĩa. Khoá giải thích B-tree vừa đủ để bạn chọn đúng index type và hiểu composite order.

Không cần đọc paper 'MVCC in PostgreSQL' của Uber hay Citus

Paper đó dài và đi rất sâu vào implementation detail. Khoá chỉ cần bạn hiểu xmin/xmax trên mỗi tuple, snapshot isolation, và tại sao dead tuple sinh ra. Đủ để hiểu vacuum và debug bloat, không cần đọc source code Postgres.

Không cần biết SQL nâng cao trước khi bắt đầu

Khoá tập trung vào internals và EXPLAIN, không phải viết query phức tạp. Biết SELECT/JOIN/WHERE là đủ để bắt đầu. SQL nâng cao như window function hay recursive CTE sẽ giải thích inline khi gặp trong context planner.

Không cần kinh nghiệm DBA hay ops Postgres trước

Khoá nhìn từ góc dev viết code, không phải góc DBA vận hành server. Bạn sẽ chạy Postgres local trong Docker, query pg_stat_user_tables, đọc EXPLAIN output, debug slow query. Không cần biết setup replication hay backup strategy trước.

Thứ BẠN cần trước khi học: biết viết SELECT/JOIN/WHERE, từng dùng 1 ORM bất kỳ (Prisma, Drizzle, TypeORM, SQLAlchemy), từng thấy EXPLAIN output dù chưa hiểu. Còn lại khoá tự cài vào đầu.

// Pedagogy

Cách content đi: storage trước, index sau, planner cuối

Hầu hết tài liệu Postgres nhảy thẳng vào index tips. Khoá này đi theo thứ tự tầng: biết data nằm ở đâu trước, rồi mới hiểu index tìm gì, rồi mới hiểu planner chọn ra sao. Hiểu tầng dưới xong, tầng trên tự khắc có nghĩa.

  1. Bước 1

    Hiểu 1 row được lưu ở đâu

    Không nhảy thẳng vào index. Trước tiên: 1 row trên disk là gì? Page 8KB chứa gì? ctid là gì? TOAST là gì? Hiểu storage xong thì index không còn là magic nữa, là cấu trúc tìm ctid nhanh hơn.

    Ví dụ

    Bài lab: dùng pageinspect extension đọc raw page của 1 table nhỏ. Thấy tuple header, xmin/xmax, ctid thật trên disk. Từ đó hiểu tại sao UPDATE sinh dead tuple.

  2. Bước 2

    Hiểu index là cây tìm ctid

    Sau khi biết ctid là gì, B-tree mới có nghĩa: là cây lưu (key, ctid) để tìm page nhanh. Composite index order, covering index, partial index: tất cả giải thích được từ nền tảng này. Không cần thuộc, chỉ cần hiểu.

    Ví dụ

    Bài lab: tạo index, dùng pg_btree_page_items đọc page đầu của B-tree. Thấy key và ctid thật. Rồi chạy EXPLAIN và khớp Index Scan node với page đã đọc.

  3. Bước 3

    Đọc EXPLAIN như đọc code

    Sau khi hiểu storage và index, EXPLAIN output không còn là block text rối. Mỗi node là 1 bước planner chọn: Index Scan lấy ctid, Seq Scan đọc heap, Nested Loop join hai luồng. Đọc bottom-up, theo cost và rows estimate, tìm node nào estimate sai nhất.

    Ví dụ

    Bài lab: 1 query slow thực tế. Chạy EXPLAIN ANALYZE, đọc từng node, tìm node có rows estimate lệch xa actual rows. Chạy ANALYZE để update statistic, chạy lại EXPLAIN, so sánh plan thay đổi ra sao.

3 tầng này liên kết với nhau. Học theo thứ tự, mỗi tầng giải thích tầng tiếp theo. Không học rời rạc từng tip.

// Methodology

5 bước rèn tư duy: từ heap đến planner đến MVCC

Không phải xem video rồi quên. Đây là 5 bước cụ thể lặp qua mỗi tầng của Postgres internals. Làm thật trên Postgres docker, không chỉ slide.

Anchor: "Query báo cáo tháng chạy 12 giây trên table orders 4 triệu dòng"

  1. Bước 101

    Bóc 1 row trong heap, hiểu page 8KB

    Trước khi làm bất cứ điều gì với query, hiểu 1 row được lưu ở đâu. Dùng pageinspect đọc raw page. Xem ctid, tuple header, xmin/xmax. Đây là nền tảng để mọi thứ phía sau có nghĩa.

    Ví dụ

    SELECT * FROM heap_page_items(get_raw_page('orders', 0)) LIMIT 5; Đọc ctid, lp_len, t_xmin, t_xmax của từng tuple. Thấy dead tuple từ UPDATE trước đó.

  2. Bước 202

    Xây B-tree trên giấy, hiểu vì sao composite order quan trọng

    Không vẽ để thi, vẽ để hiểu tại sao (status, created_at) khác (created_at, status) về mặt planner. Composite index chỉ hữu ích nếu query match prefix. Vẽ tay 1 lần, nhớ mãi.

    Ví dụ

    Tạo 2 index: (status, created_at) và (created_at, status). Chạy EXPLAIN cho query WHERE status = 'paid' AND created_at > '2026-01-01'. So sánh plan và cost. Thấy tại sao prefix matter.

  3. Bước 303

    Mở pg_statistic, hiểu planner đoán selectivity ra sao

    Planner không biết data thật, chỉ biết statistic. Mở pg_stats, đọc n_distinct, most_common_vals, histogram_bounds. Hiểu tại sao estimate rows đôi khi lệch xa actual, và khi nào cần ANALYZE.

    Ví dụ

    SELECT * FROM pg_stats WHERE tablename = 'orders' AND attname = 'status'; Đọc most_common_freqs. So sánh estimate rows trong EXPLAIN với actual rows. Thấy correlation giữa statistic và plan quality.

  4. Bước 404

    Đọc EXPLAIN từng line như đọc code

    Đọc EXPLAIN ANALYZE bottom-up: node lá trước, node gốc sau. Mỗi node có cost estimate và actual time. Tìm node có rows estimate lệch actual nhất: đó thường là root cause của plan tệ.

    Ví dụ

    Query 12 giây: EXPLAIN ANALYZE chỉ ra Hash Join với rows=1 nhưng actual rows=48000. Planner estimate sai vì statistic sau khi bulk insert không được update. Chạy ANALYZE, chạy lại: plan chuyển sang Nested Loop + Index Scan, query còn 0.3 giây.

  5. Bước 505

    Tìm khi nào planner sai và override bằng hint hoặc rewrite

    Planner đôi khi chọn plan không tối ưu dù statistic đúng: correlated columns, partition pruning miss, CTE fence. Biết khi nào dùng enable_seqscan=off để test, khi nào rewrite query, khi nào dùng explicit JOIN order.

    Ví dụ

    Query với 3 JOIN: planner chọn order A-B-C nhưng order A-C-B nhanh hơn vì C có filter rất selective. Dùng SET join_collapse_limit=1 và viết lại JOIN order thủ công. Verify bằng EXPLAIN.

5 bước này lặp lại qua từng module. Cuối khoá: nhìn EXPLAIN output bất kỳ, não tự chạy 5 bước không cần nhớ lại. Đó là mục tiêu.

// Mindset Shifts

4 cú nhảy tư duy giữa dev tin ORM và dev hiểu Postgres

Dev hiểu internals không viết SQL nhiều hơn bạn. Họ nghĩ KHÁC trước khi chạy query. Khoá này cài 4 cách nghĩ đó.

Shift #1
Dev tin ORM nghĩ

"ORM sinh query, query chạy ra kết quả. Chậm thì thêm index. Index nào cũng được, thêm vào cột filter là xong."

Dev hiểu internals nghĩ

"Index nào planner sẽ chọn? Composite order có match prefix không? Selectivity của cột này cao hay thấp? Covering index có cắt được heap fetch không? Thêm index sai còn tệ hơn không thêm vì planner bị nhiễu."

Trigger: "Planner sẽ dùng index này trong trường hợp nào, và không dùng trong trường hợp nào?"

Shift #2
Dev tin ORM nghĩ

"EXPLAIN chạy ra output dài. Nhìn thấy Index Scan là tốt, Seq Scan là xấu. Không cần đọc kỹ hơn."

Dev hiểu internals nghĩ

"Đọc bottom-up. Node nào có rows estimate lệch actual nhiều nhất? Cost của node gốc hợp lý không? Nested Loop với rows=50000 là vấn đề, dù bên trong có Index Scan. Seq Scan trên table 100 dòng là bình thường."

Trigger: "Node nào trong plan có estimate xa thực tế nhất, và tại sao?"

Shift #3
Dev tin ORM nghĩ

"Transaction là transaction. MVCC là tính năng Postgres tự quản lý. Vacuum chạy tự động, không cần quan tâm."

Dev hiểu internals nghĩ

"UPDATE không xoá tuple cũ, chỉ đánh xmax. Dead tuple chồng lên làm bảng phình. Batch UPDATE 500K dòng không có autovacuum kịp = bloat = Seq Scan đọc nhiều page hơn cần thiết. HOT update có giúp không? fillfactor bao nhiêu là hợp lý?"

Trigger: "Sau khi chạy batch UPDATE này, bảng sẽ có bao nhiêu dead tuple, và vacuum có kịp dọn không?"

Shift #4
Dev tin ORM nghĩ

"Query chạy được, kết quả đúng, là xong. Hiểu bên dưới Postgres là việc của người khác."

Dev hiểu internals nghĩ

"Query đúng hôm nay. Đúng khi table có 10K dòng. Khi 2 triệu dòng, plan có còn dùng index không? statistic có cần ANALYZE không? Batch job tuần trước có để lại bloat không? Hiểu internals = tự debug được, không phải đoán."

Trigger: "Query này sẽ còn chạy tốt không khi data tăng gấp 100 lần?"

4 câu hỏi này chạy tự động trong đầu dev đã rèn qua khoá. Không cần nhớ lại, tự khắc hỏi trước khi push code.

// USP

4 thứ khoá này có, tutorial Postgres khác không có

Không phải khoá DBA. Không phải SQL tutorial. Không phải params reference. Đây là content tập trung đúng 1 thứ: mental model internals cho dev viết code backend.

Không phải DBA course, không tune Postgres params

Khoá nhìn từ góc dev: tại sao query chậm, index nào phù hợp bài toán nào, khi nào planner sai và cách fix. Không đi vào shared_buffers, wal_level, replication slot management. Đó là công việc của người vận hành server, không phải người viết code.

Hands-on lab với Postgres docker, không chỉ slide

Mỗi bài có lab thật: pageinspect đọc raw page, pg_btree_page_items đọc B-tree, pg_stats đọc statistic, EXPLAIN ANALYZE trên dataset thực. Không xem video rồi tin lời. Tự chạy, tự thấy, tự hiểu.

Production case study VN, không phải US tutorial clone

Mỗi module có 1 case study từ hệ thống thực: hệ thống ecommerce nội bộ slow report, fintech tích hợp ngân hàng lock contention, SaaS multi-tenant bloat. Không phải Twitter clone hay Stripe clone không map được với job thực tế ở VN.

Mental model dùng được trên mọi Postgres deployment

Storage page, B-tree, cost model, MVCC: concept này giống nhau trên Postgres 14, 15, 16, 17. Giống nhau trên self-hosted, RDS, Aurora, Supabase, Neon. Học 1 lần, áp dụng ở bất kỳ đâu có Postgres.

// Curriculum

28 bài, 6 module

Mỗi module rèn 1 tầng trong mental model: storage layer trước, rồi mới index, rồi mới planner, rồi MVCC. Hiểu từng tầng xong mới lên tầng tiếp theo. Không nhảy cóc.

  • Một đêm tại ShopCore
  • Tại sao Deep Dive
  • Setup playground
  • Page 8KB
  • Heap và ctid
  • TOAST
  • Fillfactor và HOT update
  • Visibility map
  • B-tree từ giấy
  • B-tree page layout
  • Index scan types
  • Composite index
  • Partial index
  • Covering index
  • Expression index
  • GIN index
  • BRIN index
  • Hash, GiST, SP-GiST
  • Query pipeline
  • Cost model
  • pg_statistic
  • Selectivity
  • Join algorithms
  • Join reorder
  • Subquery, CTE, LATERAL
  • Đọc EXPLAIN
  • Khi planner đoán sai
  • MVCC: xmin, xmax

// Click vào module để xem chi tiết các bài học

// Hard Questions

3 câu hỏi bạn sẽ không hỏi trực tiếp

Cả 3 là câu thật từ dev VN khi đọc landing page khoá database. Mình trả lời thẳng.

#01 · Free resource objection

"Sao không học YouTube / Use The Index Luke / Postgres docs miễn phí?"

Thứ tự học
YouTube / Blog / Docs

Rời rạc. Mỗi video 1 tip: 'thêm index composite', 'tránh N+1'. Không có narrative từ storage đến index đến planner đến MVCC theo thứ tự.

Khoá này

Có thứ tự tầng rõ ràng: storage layer trước, B-tree sau, planner sau, MVCC sau. Mỗi tầng giải thích được tại sao tầng tiếp theo hoạt động như vậy.

Hands-on
YouTube / Blog / Docs

Đọc xong biết lý thuyết. Không có lab thật để tự chạy và kiểm chứng trên Postgres docker.

Khoá này

Mỗi bài có lab: pageinspect, pg_stats, EXPLAIN ANALYZE trên dataset thực. Tự chạy, tự thấy output thật.

Context VN
YouTube / Blog / Docs

Use The Index Luke: tiếng Anh, domain US. Postgres docs: reference manual, không phải learning path. YouTube: case study US/EU không map với job VN.

Khoá này

Case study từ hệ thống thực VN: ecommerce nội bộ, fintech, SaaS. Vocabulary và context phù hợp với môi trường làm việc thực tế.

ORM mapping
YouTube / Blog / Docs

Tài liệu nói về SQL thuần. Không hướng dẫn map concept sang Prisma, Drizzle, TypeORM đang dùng hàng ngày.

Khoá này

Giải thích cách đọc query ORM sinh ra, cách dùng EXPLAIN với query từ Prisma/Drizzle, cách debug N+1 thật sự.

Free resource tốt để tra cứu. Khoá này rèn mental model có thứ tự. Hai thứ không thay thế nhau.

#02 · MySQL / Oracle objection

"Tao xài MySQL / Oracle, học Postgres có dùng được không?"

Storage
Postgres-specific

Heap file format, TOAST, ctid: Postgres-specific implementation.

Common across RDBMS

Concept page-based storage, row layout, buffer pool: dùng được khi đọc MySQL InnoDB hay Oracle docs.

Index
Postgres-specific

GIN, BRIN, SP-GiST: Postgres-specific index types.

Common across RDBMS

B-tree traversal, composite index prefix, covering index, selectivity: concept chung cho mọi RDBMS có B-tree index.

Planner
Postgres-specific

pg_statistic, enable_seqscan, join_collapse_limit: Postgres-specific params.

Common across RDBMS

Cost model, statistics-based optimization, join algorithms (hash join, merge join, nested loop): concept chung, MySQL và Oracle cũng dùng.

MVCC
Postgres-specific

xmin/xmax tuple header, visibility rules: Postgres implementation riêng.

Common across RDBMS

Snapshot isolation, dead tuple / undo log concept, transaction visibility: nguyên tắc chung dù implementation khác nhau.

Học Postgres internals là cách học RDBMS internals hiệu quả nhất vì Postgres source code mở, documentation chi tiết, community lớn. Concept transfer sang MySQL hay Oracle dễ hơn chiều ngược lại.

#03 · DDIA objection

"Tao đã đọc Designing Data-Intensive Applications rồi, có cần học thêm không?"

DDIA giải thích tại sao. Khoá này rèn bạn làm được.

DDIA là cuốn sách xuất sắc về distributed systems và storage engines ở mức khái niệm. Kleppmann giải thích B-tree vs LSM-tree, MVCC, replication lag rất tốt ở level 'hiểu nguyên tắc'. Đó là nền tảng lý thuyết tốt.

Nhưng DDIA không đi vào 'mở EXPLAIN ANALYZE và đọc từng line'. Không giải thích pg_stats và tại sao estimate lệch actual. Không có lab hands-on với Postgres docker. Không có case study về composite index order hay covering index trên ORM query thực tế. DDIA quá general để áp dụng trực tiếp vào debug slow query hôm nay.

Nếu đã đọc DDIA: khoá này là bước tiếp theo, đi từ lý thuyết đến thực hành Postgres cụ thể. Nếu chưa đọc DDIA: khoá này standalone, không cần đọc DDIA trước.

DDIA + khoá này không overlap, chúng complement nhau. DDIA cho bạn why rộng. Khoá này cho bạn how cụ thể trên Postgres.

Nếu vẫn còn câu hỏi sau 3 block trên, scroll xuống FAQ. Không có câu trả lời phù hợp? Email thẳng.

// Instructor

Người đi trước

Mình là backend dev. Viết khoá này. Dùng nếu thấy hợp.

// photo soon

[Tên]

Backend dev

Mình từng mò những thứ trong khoá này. Giờ viết lại gọn cho bạn đỡ mò.

// Audience filter

Khoá này KHÔNG dành cho ai

Thà mất đơn còn hơn cầm tiền của người không phù hợp. Đọc kỹ. Dính 1/4, đừng mua.

Fresher chưa từng deploy code lên production

Khoá giả định bạn đã từng thấy query chậm thật, đã từng chạy EXPLAIN dù chưa hiểu output, đã từng dùng ORM trong project thật. Không có context production, các case study sẽ không có nghĩa với bạn.

Build 1 project thật có database, deploy lên server, để data tăng lên vài chục nghìn dòng. Khi query bắt đầu chậm, quay lại khoá này sẽ thấm ngay.

Người chưa bao giờ đụng vào EXPLAIN

Khoá dành phần lớn thời gian vào đọc EXPLAIN ANALYZE output. Nếu bạn chưa từng chạy EXPLAIN một lần, module planner sẽ khó theo kịp. Không cần hiểu trước, nhưng cần đã từng thấy.

Chạy EXPLAIN trên bất kỳ query nào trong project của bạn. Đọc output, không hiểu cũng không sao. Làm điều đó 1 lần trước khi bắt đầu khoá.

Người muốn học SQL từ đầu

Khoá giả định bạn đã viết được SELECT, JOIN, WHERE, GROUP BY. Không hướng dẫn SQL syntax. Không giải thích primary key hay foreign key là gì. Đây không phải SQL tutorial.

SQLBolt miễn phí, 1-2 tuần là xong SQL cơ bản. Quay lại sau khi viết được query JOIN 3 bảng không cần tra cứu.

Người tin ORM lo hết và không muốn thay đổi điều đó

Khoá này sẽ chỉ ra những gì ORM không làm được và tại sao bạn cần hiểu tầng bên dưới. Nếu bạn không muốn biết điều đó, khoá sẽ không có giá trị với bạn.

Tiếp tục dùng ORM. Khi production chậm lần đầu và bạn tự muốn hiểu tại sao, quay lại.

Vẫn ở đây sau 4 điều trên? Bạn đúng là người khoá này sinh ra để phục vụ. Kéo xuống xem khoá KHÔNG hứa gì.

// Honest expectations

Khoá này KHÔNG hứa gì

Không hứa lương tăng, không hứa đổi đời. Đây là cái khoá KHÔNG hứa, và cái khoá thực sự giao được.

KHÔNG hứa

Không hứa bạn thành DBA sau khoá.

NHƯNG hứa

Hứa khi query chậm, bạn biết bắt đầu nhìn vào đâu: EXPLAIN output, pg_stats, dead tuple count. Không đoán mò, không đợi DBA giải cứu.

KHÔNG hứa

Không hứa fix mọi slow query sau khoá.

NHƯNG hứa

Hứa bạn có đủ mental model để tự debug phần lớn slow query do index sai, statistic lỗi thời, hoặc plan sub-optimal. Vẫn có những bài toán cần DBA chuyên sâu, khoá không thay thế được điều đó.

KHÔNG hứa

Không hứa concept này apply ngay vào job ngày mai.

NHƯNG hứa

Hứa lần tiếp theo bạn thấy query chậm hoặc EXPLAIN output lạ, bạn có framework để tiếp cận thay vì đứng nhìn. Áp dụng được sớm hay muộn phụ thuộc vào mức độ bạn gặp vấn đề thật.

KHÔNG hứa

Không hứa khoá cover hết mọi thứ về Postgres.

NHƯNG hứa

Hứa cover đủ phần dev viết code cần: storage layer, B-tree foundations, query planner, MVCC basics. Replication, logical decoding, extension development: ngoài scope, có nguồn tự học tốt hơn.

KHÔNG hứa

Không hứa xem video xong là xong.

NHƯNG hứa

Hứa nếu bạn làm lab thật trên Postgres docker, tự chạy EXPLAIN trên query của mình, tự đọc pg_stats, bạn sẽ thấy khác biệt. Xem suông không có tác dụng, làm thật mới cài được mental model.

Khoá này lấp 1 khoảng trống cụ thể: mental model internals để debug Postgres. Không phải khoá đổi đời, không phải cert, không phải DBA training. Làm tốt phần đó.

// Pricing

900.000₫. Mở bán đợt đầu.

Giá mở bán đợt đầu. Nội dung đầy đủ 28 bài, không cắt bớt so với regular.

Mở bán đợt đầu
900.000đ

2.500.000đ

Giá mở bán đợt đầu

  • 28 bài chia 6 module, từ storage đến B-tree đến planner đến MVCC
  • Lab Postgres docker mỗi bài: pageinspect, pg_stats, EXPLAIN ANALYZE thật
  • Dataset và code thật từ production case study VN
  • 1 buổi Q&A live qua Zoom sau khi khoá mở
  • Truy cập trọn đời, xem lại bất cứ lúc nào
  • Update nội dung khi Postgres ra major version mới có thay đổi planner hoặc storage
  • Community Discord/Zalo hỏi đáp async

Còn lại

--ngày
--giờ
--phút
--giây

Hoàn 100% trong 7 ngày nếu không thấy phù hợp. Không hỏi lý do.

// FAQ

Câu hỏi thường gặp

Câu hỏi không có ở đây? Email thẳng. Trả lời trong 24h.

Dev backend đã đi làm, đã từng viết query thật và deploy lên production, muốn hiểu tại sao query chậm và cách debug bằng EXPLAIN. Không phải cho fresher mới học SQL, không phải cho DBA muốn tune server params.