// Database Từ Bản Chất™ · Phần 0–7

Hiểu vì sao Postgres quyết định vậy. Không phải học thuộc cú pháp.

8 phần, đi từ storage internals tới MVCC tới cách planner ra quyết định.

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

// Nếu bạn thấy mình ở đây

Có một câu trả lời chỉ dùng được đúng một lần trong đời đi phỏng vấn: "index giống mục lục sách".

Lần đầu nói ra, người phỏng vấn gật đầu. Lần sau họ hỏi thêm một câu, và câu đó lộ ra bạn chỉ thuộc ví dụ, chưa hiểu cái gì thật sự xảy ra bên dưới.

  1. 01

    Query chậm, thêm index vào là hết chậm. Hỏi "tại sao" thì chỉ nói được "vì có index rồi".

  2. 02

    Mở EXPLAIN ANALYZE, thấy Seq Scan dù bảng có index sẵn. Không biết đọc từ đâu, đóng lại, thử thêm index khác.

  3. 03

    Phỏng vấn hỏi index hoạt động thế nào. Trả lời trôi tới "giống mục lục sách" rồi im.

  4. 04

    Một bảng update nhiều, càng ngày càng chậm. VACUUM cho yên tâm, không hiểu vì sao nó chậm ngay từ đầu.

Vấn đề không phải bạn học chưa đủ. Là hầu hết chỗ dạy chỉ dừng ở đúng một ví dụ và một dòng lệnh, rồi coi như xong.

// Tại sao cần hỏi “tại sao”

Có bao giờ bạn tự hỏi, trong cùng một nhóm, cùng điều kiện, tại sao có người đi xa, có người đứng yên?

Không phải người nhớ nhiều nhất. Là người hỏi “tại sao” nhiều nhất.

Kiến thức thì ngày mai đã thêm cái mới, cái cũ lạc hậu. Câu hỏi đúng thì khác: bạn giữ cả đời, và tự tìm câu trả lời mới mỗi khi hoàn cảnh thay đổi.

Người A

Hôm nay

Làm xong việc. Đóng laptop. Đi về.

1 năm sau

Vẫn y như vậy. Gặp lại bài cũ, vẫn phải tra cứu lại từ đầu.

5 năm sau

Vẫn y như vậy. Trong khi thế giới xung quanh đã đi tiếp từ lâu.

Người B

Hôm nay

Làm xong việc. Rồi dừng lại, hỏi thêm một câu “tại sao”.

1 năm sau

Hiểu sâu thêm một tầng. Thấy thứ người bên cạnh không thấy.

5 năm sau

Đã đứng ở chỗ rất khác, vì mỗi ngày gửi thêm một câu hỏi vào chính mình.

Mỗi câu “tại sao” bạn hỏi thêm giống như gửi tiết kiệm vào chính mình. Một mình thì chẳng thấy gì. Gửi đều đặn, một năm nhìn lại đã khác. Năm năm: bạn đứng ở chỗ rất ít người đứng được.

// Cái giá của việc bỏ qua

Mỗi lần bỏ qua câu hỏi “tại sao” là bạn cho phép mình trôi về phía trung bình: chỗ an toàn nhất, chỗ không sai nhưng cũng chỗ không ai nhớ đến nhất.

// Điều cuối cùng muốn nói

Câu trả lời thì ngày mai đã cũ.Câu hỏi đúng thì không bao giờ cũ, vì nó tự sinh ra câu trả lời mới mỗi khi bạn cần.

// Cách nhìn thay đổi tất cả

Khoảng cách tới hiểu bản chất.

Kiến thức về database nằm trên một trục: một đầu là thuộc cú pháp, đầu kia là hiểu vì sao Postgres quyết định vậy. Gần hết tài liệu chỉ đưa bạn tới nửa đường.

Bạn đang ở đây
Cú pháp
Mốc chuyển
Đích đến
Cấu trúc

Vị trí bạn đang đứng

Người biết cú pháp

Thuộc CREATE INDEX, thuộc câu "giống mục lục sách", copy sẵn bảng "dùng loại nào khi nào" từ blog. Chạy được. Hỏi thêm một câu là bí.

Sau khi học xong

Người đọc được quyết định của Postgres

Biết dữ liệu nằm ở đâu, cây tìm kiểu gì, ghi tốn gì, version nào "dính" theo index, và vì sao planner chọn scan này chứ không phải scan kia.

Bạn biết cách dùng. Chỉ là chưa ai chỉ bạn Postgres đang nghĩ gì trước khi ra quyết định đó.

// Outline 8 phần

Toàn bộ khóa học, theo đúng thứ tự một database engine thật sự vận hành.

Mỗi phần dựa vào aha moment của phần trước, không phải danh sách mẹo rời rạc.

  1. 00

    Phần 0 · Câu hỏi mở đầu

    Vì sao có bảng đã tạo index mà Postgres vẫn chọn Seq Scan? Câu hỏi dẫn dắt cả khóa, trả lời đầy đủ nằm ở Phần 6.

  2. 01

    Phần 1 · Storage internals

    Dữ liệu thật sự nằm ở đâu: page, tuple, heap. Nền cho mọi phần sau.

  3. 02

    Phần 2 · B-tree traversal

    Không phải "giống mục lục sách". Cấu trúc thật của B-tree và cách nó tìm dữ liệu.

  4. 03

    Phần 3 · Write path

    Một INSERT/UPDATE thật sự tốn gì khi bảng có index. Chi phí ẩn không nằm trong tutorial nào.

  5. 04

    Phần 4 · MVCC × Index

    Vì sao index scan vẫn đụng dead tuple, và HOT Update giải quyết chuyện đó ra sao. Aha moment mạnh nhất khóa học.

  6. 05

    Phần 5 · B-tree thực chiến

    Hành vi thật của B-tree khi bảng lớn dần: không còn ví dụ đồ chơi 50 dòng.

  7. 06

    Phần 6 · Planner decision

    Selectivity, cost, lý do thật đằng sau Seq Scan hay Index Scan. Trả lời trọn vẹn cho Phần 0.

  8. 07

    Phần 7 · EXPLAIN ANALYZE

    Đọc được Postgres đang tính gì trong một query thật, thôi đoán mò.

// Niềm tin đang giữ bạn lại

Không phải bạn thiếu kỹ năng. Là vài niềm tin đang giữ bạn ở lớp ghi nhớ.

Nghe hợp lý, ai cũng tin, nên chẳng ai buồn nghi ngờ. Gỡ được thì đi được nửa đường rồi.

Bẫy ORM

"Prisma/TypeORM lo hết, cần gì biết index."

Sự thật

ORM sinh SQL, không sinh hiểu biết. Query chậm ở production, ORM không giải thích hộ bạn đâu. Người gỡ được là người hiểu bên dưới, không phải người thuộc API ORM.

Bẫy "học rồi"

"Học course index rồi, khóa nào cũng như nhau."

Sự thật

Phần lớn khóa dừng ở ví dụ mục lục sách và cú pháp CREATE INDEX, đúng 10% câu chuyện. MVCC ảnh hưởng index thế nào, vì sao update chậm dần: gần như không ai đụng tới, vì khó dạy hơn cú pháp nhiều.

Nỗi sợ AI

"AI viết query hộ rồi, học sâu DB làm gì."

Sự thật

AI viết đúng cú pháp. Nó không biết vì sao query đó chậm trên data thật của bạn, không đọc EXPLAIN ANALYZE hộ bạn lúc production sập. Phần AI làm tốt là gõ code. Phần hiểu để ra quyết định vẫn là việc của bạn.

Ảo tưởng theo thời gian

"Làm lâu tự khắc hiểu sâu."

Sự thật

Việc hàng ngày không ép bạn hiểu bản chất: query chạy được là xong task, chẳng ai bắt giải thích tại sao. Nhiều người làm cả chục năm vẫn dừng ở lớp "dùng được". Hiểu sâu là một quyết định chủ động, không tự tới theo số năm.

Bẫy tài liệu tiếng Anh

"Tài liệu tiếng Anh đầy, học tiếng Việt làm gì."

Sự thật

Tài liệu có thật, nhưng phần lớn là docs khô hoặc sách vài trăm trang viết cho người đã có nền sẵn. Không phải không có, mà tự học một mình theo đúng thứ tự không dễ.

Bẫy "để dành lên senior"

"Cái này để lên senior học cũng chưa muộn."

Sự thật

Người có mác senior ở công ty này có khi chỉ là junior ở chỗ khác: cái mác là do người khác gán, không phải thước đo giá trị thật. Đừng thần thánh hóa role; quan trọng là skill thực của bạn, và skill thì không tự tới khi bạn đợi có mác rồi mới bắt đầu học.

// Học kiểu cũ, học kiểu này

Cùng một Postgres, hai cách hiểu khác hẳn nhau.

Cách cũ
Cách ở đây

Thuộc "B-tree cho equality, GIN cho full-text" như học bảng cửu chương.

Hiểu cấu trúc B-tree và heap thật, tự suy ra được loại index nào hợp lý.

Query chậm, thêm index, xóa index, thử lại, tới khi nào work thì thôi.

Đọc EXPLAIN ANALYZE, biết chính xác Postgres đang cân nhắc gì trước khi chọn scan.

Đọc EXPLAIN ANALYZE như đọc chữ Hán, không hiểu Postgres đang tính gì.

Hiểu MVCC tạo dead tuple ra sao, tự giải thích được vì sao update chậm dần.

Phỏng vấn hỏi sâu về DB là lái sang nói chuyện framework.

Trả lời câu hỏi DB trong phỏng vấn bằng lý do, không phải định nghĩa học thuộc.

Học xong quên nhanh, không có gốc, chỉ là mảnh vá rời rạc.

Kiến thức có gốc, dùng lại được cho mọi hệ thống chạy Postgres sau này.

Không phải đường tắt bỏ qua kỹ thuật. Là học đúng lớp, thứ ít tài liệu tiếng Việt chịu dạy.

// Khóa này không dành cho tất cả mọi người

Đọc kỹ hai cột này trước khi quyết.

Đây chính xác là điều bạn cần

  • Đã dùng index, ORM, viết query hàng ngày, nhưng chưa tự tin giải thích tại sao.
  • Từng bị hỏi xoáy về DB trong phỏng vấn và trả lời được nửa câu.
  • Từng thấy một query chậm dần theo thời gian mà không hiểu gốc rễ.
  • Muốn kiến thức có gốc, dùng lại được cho mọi hệ thống Postgres sau này.

Chưa dành cho bạn nếu

  • Chỉ muốn một bảng tra cứu nhanh "loại index nào dùng khi nào".
  • Chưa từng viết SQL, chưa dùng Database trong dự án.
  • Tìm một khóa "học xong lên senior ngay".
  • Không muốn đi lại từ Phần 1, dù đã biết một phần nội dung.

// Tại sao mình làm khóa này

Câu chuyện đằng sau.

Có một buổi phỏng vấn mình nhớ khá rõ. Bên kia hỏi: "Bảng payment của em càng ngày càng nhiều update, query check trạng thái giao dịch chậm dần. Em xử lý sao?" Mình trả lời VACUUM, reindex, rồi im. Vì thật ra mình chỉ biết làm, chưa hiểu tại sao nó xảy ra.

Tối hôm đó mình lục lại hết chỗ mình từng học về index: course, blog, video. Rồi phát hiện một điều khá buồn cười: gần hết chỗ chỉ dạy đúng một ví dụ (index giống mục lục sách) và một dòng lệnh (CREATE INDEX). Không ai kể MVCC tạo tuple version mới mỗi lần update, và index B-tree phải đi qua cả những version đã chết trước khi tìm ra version còn sống. Bảng update nhiều thì dead tuple tích lại, index scan phải bơi qua nhiều rác hơn, đó mới là lý do thật, không phải "bảng lớn thì chậm" chung chung.

Lúc hiểu ra HOT Update: Postgres update tại chỗ, không đụng index, nếu cột update không nằm trong index. Mình mới thấy rõ cái mình thiếu suốt bao lâu nay không phải thêm kỹ thuật. Là hiểu đúng thứ tự một database engine thật sự vận hành.

Khóa này là chỗ mình lấp cái khoảng đó. Không phải thêm một bảng "loại index nào dùng khi nào", mà đi từ storage, tới cách ghi dữ liệu, tới MVCC, tới cách planner ra quyết định. Từ bản chất, đúng nghĩa đen, không phải tagline.

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

Những điều bạn có thể đang phân vân

Được, miễn đã viết SQL và dùng index ít nhất trong một dự án thực tế. Khóa xây từ Phần 1, storage internals, không giả định bạn đã hiểu B-tree hay MVCC từ trước.

// Bước tiếp theo

Xem outline, tự quyết định, không cần để lại email.

Không xin email, không đẩy bạn qua chuỗi bán hàng. Outline và trạng thái sản xuất đã ở ngay phía trên. Thấy đúng thứ đang thiếu thì mua trọn bộ ngay.

P.S. Nếu mỗi lần bị hỏi "tại sao" về index, MVCC, hay planner, câu trả lời duy nhất của bạn là "giống mục lục sách", thì vấn đề không nằm ở việc bạn chưa đủ chăm. Bạn đang dừng ở đúng lớp mà 90% tài liệu để bạn dừng lại. Đây là phần còn lại của câu chuyện.