Mười một bài qua đã mổ xẻ SQLite từ mười sáu byte đầu của file tới các núm tối ưu cuối cùng — mỗi khẳng định kèm một con số đo trong container sqlite 3.45.3. Bài cuối gom tất cả lại và trả lời câu hỏi mà mọi kiến thức đó phục vụ: với những gì đã đo, khi nào nên chọn SQLite, và khi nào nên dùng một CSDL máy chủ?

SQLite mạnh đến đâu: đo trần đọc và ghi

Trước khi bàn giới hạn, hãy đo sức mạnh. Trên một bảng hai triệu dòng ở chế độ WAL, một tiến trình đơn:

đọc  : 50 000 điểm tra cứu theo khóa chính = 102 ms  →  ~490 000 lượt đọc/giây
ghi  : 500 000 dòng trong MỘT giao dịch    =  55 ms  →  ~9 000 000 dòng/giây
giới hạn một CSDL: 281 TB (page_size 65536 × 2³² trang)

Gần nửa triệu lượt đọc mỗi giây từ một tiến trình, và ghi hàng loạt chín triệu dòng mỗi giây khi gói trong một giao dịch. Đây không phải "CSDL đồ chơi" — với tải đọc nặng trên một máy, SQLite nhanh hơn nhiều người tưởng, lại không có chi phí mạng hay tiến trình máy chủ. Giới hạn dung lượng 281 TB cũng xa tầm với của gần như mọi ứng dụng. Vậy giới hạn thật nằm ở đâu?

Trần cứng: một người ghi tại một thời điểm

Phần 7 và 8 đã chạm tới nó, và đây là ranh giới quyết định: SQLite cho nhiều người đọc đồng thời, nhưng chỉ một người ghi tại một thời điểm. WAL nới cho người đọc chạy song song với người ghi, nhưng hai giao dịch ghi vẫn phải xếp hàng. Với tải ghi từ nhiều nguồn cùng lúc — hàng nghìn client cùng cập nhật — việc ghi tuần tự hóa này trở thành nút cổ chai, và SQLITE_BUSY bắt đầu xuất hiện. Thêm nữa, SQLite là thư viện trong tiến trình, không có cổng mạng: nhiều máy không thể cùng mở một file SQLite qua mạng một cách an toàn (WAL còn cần bộ nhớ chia sẻ, không chạy trên NFS). Hai giới hạn này — một người ghi, và không qua mạng — là đường phân giới với CSDL máy chủ.

Ảnh chụp sơ đồ nền tối trình bày khi nào chọn SQLite trong container sqlite 3.45.3. Cột trái NÊN DÙNG SQLite màu xanh: ứng dụng nhúng desktop mobile CLI, định dạng tệp của ứng dụng, tải đọc nặng khoảng 490 nghìn lượt mỗi giây, một máy một hoặc vài tiến trình với WAL, web vừa và nhỏ chủ yếu đọc, kiểm thử và nguyên mẫu. Cột phải DÙNG CSDL MÁY CHỦ màu cam: nhiều máy cùng ghi qua mạng, ghi đồng thời cao từ nhiều client, cần client server qua mạng, cần phân quyền từng người và nhân bản, dữ liệu trên hệ tệp mạng NFS. Ở giữa ghi trần cứng một người ghi tại một thời điểm và không truy cập qua mạng là đường phân giới

Hình 1: Khi nào chọn SQLite (trái) và khi nào cần CSDL máy chủ (phải) — ranh giới là trần "một người ghi, không qua mạng". Đo trong container sqlite 3.45.3.

Nên dùng SQLite khi

SQLite là lựa chọn đúng — thường là tốt nhất — cho rất nhiều trường hợp mà người ta theo quán tính lại dựng một máy chủ CSDL nặng nề:

  • Ứng dụng nhúng: desktop, mobile, CLI — nơi CSDL sống cùng ứng dụng, không cài đặt, không cấu hình. Đây là lý do SQLite có mặt trong mọi điện thoại và trình duyệt.
  • Định dạng tệp của ứng dụng: thay cho một mớ file tùy biến, dùng một file SQLite làm định dạng lưu tài liệu — có giao dịch, truy vấn, và khả năng chống hỏng.
  • Tải đọc nặng trên một máy: blog, trang nội dung, cache, phân tích dữ liệu cục bộ — nơi đọc áp đảo ghi, 490 nghìn lượt đọc/giây là quá đủ.
  • Web vừa và nhỏ: với WAL, một ứng dụng web một máy chủ, lưu lượng chủ yếu đọc và một luồng ghi, chạy SQLite rất gọn và nhanh.
  • Kiểm thử và nguyên mẫu: dựng CSDL trong một dòng, xóa bằng cách xóa file.

Nên dùng CSDL máy chủ khi

Ngược lại, hãy chọn PostgreSQL/MySQL khi chạm đúng các giới hạn đã đo:

  • Nhiều máy cùng ghi: cần truy cập qua mạng từ nhiều máy chủ ứng dụng — SQLite không làm được.
  • Ghi đồng thời cao: hàng nghìn client cùng ghi liên tục — trần một-người-ghi thành nút cổ chai.
  • Cần nhân bản, phân quyền từng người, mở rộng ngang: những tính năng của hệ máy chủ mà SQLite cố ý không có.
  • Dữ liệu trên hệ tệp mạng (NFS): WAL cần bộ nhớ chia sẻ cục bộ.

Quy tắc gọn: một máy, chủ yếu đọc → SQLite; nhiều máy, ghi đồng thời cao → máy chủ. Và một lời khuyên từ chính tác giả SQLite: đừng nghĩ lựa chọn là "SQLite so với máy chủ" mà là "SQLite so với fopen()" — nó thay thế cho việc tự đọc ghi file, và ở vai trò đó nó gần như luôn thắng.

Tổng hợp mười hai phần: mọi con số đã đo

Ảnh chụp sơ đồ nền tối bảng tổng hợp mười hai phần sê-ri SQLite đo thật trong container sqlite 3.45.3. Phần 1 định dạng tệp một file header 100 byte SQLite format 3 page_size nhân page_count bằng file. Phần 2 cây B-tree fanout 373 một triệu dòng chỉ 3 tầng tìm theo khóa dưới 3 đọc trang. Phần 3 rowid INTEGER PRIMARY KEY là bí danh rowid WITHOUT ROWID cắt 24 xuống 12 MB. Phần 4 index SCAN 43 mili-giây so SEARCH 0,014 nhanh 3000 lần. Phần 5 ANALYZE chọn nhầm 53 mili-giây thành chọn đúng 0,010 nhanh 5300 lần. Phần 6 nhật ký hoàn tác gói giao dịch 3680 xuống 5 mili-giây 736 lần. Phần 7 WAL đọc ghi song song 3000 giao dịch 2170 xuống 581 mili-giây. Phần 8 giao dịch BEGIN IMMEDIATE tránh deadlock DEFERRED. Phần 9 kiểu động cột INTEGER chứa chuỗi STRICT ép kiểu. Phần 10 VACUUM xóa 90 phần trăm file vẫn 37 MB VACUUM còn 3,6 MB. Phần 11 PRAGMA tối ưu chèn 100 nghìn dòng 153 giây xuống 79 mili-giây. Phần 12 tổng kết 490 nghìn đọc mỗi giây trần một người ghi

Hình 2: Toàn bộ sê-ri SQLite đo thật trong một bảng — mười hai phần, mọi con số đo bằng container sqlite 3.45.3.

Đọc lại bảng này là thấy một bức tranh mạch lạc: SQLite là một thư viện nhỏ, một file, dựa trên cây B-tree phẳng cho tra cứu gần như tức thì, với một bộ lập kế hoạch cần thống kê để chọn đúng, hai cơ chế ghi an toàn (rollback journal và WAL) mà chi phí nằm ở fsync, một hệ kiểu động linh hoạt nhưng dễ gài bẫy, và một nắm núm PRAGMA mà núm đáng giá nhất luôn là gói giao dịch.

Lời kết cho cả sê-ri

Điều đáng nhớ nhất không phải một con số cụ thể nào, mà là phương pháp: mỗi khẳng định về SQLite trong sê-ri này đều có thể kiểm chứng bằng một lệnh. xxd cho thấy header, dbstat đếm trang và đo chiều cao cây, EXPLAIN QUERY PLAN phơi bày kế hoạch, typeof tiết lộ kiểu thật, và một đồng hồ date đơn giản biến mọi lời khuyên tối ưu thành con số trước-sau. SQLite minh bạch một cách hiếm có — cả CSDL là một file bạn có thể mở ra và đọc từng byte. Hiểu nó không cần tin lời ai; chỉ cần đo. Và một khi đã đo, bạn biết chính xác khi nào công cụ nhỏ bé này là lựa chọn đúng — thường là nhiều hơn bạn tưởng.

Cảm ơn bạn đã theo trọn mười hai phần. Mong rằng lần tới mở một file .db, bạn sẽ thấy ở đó không phải một hộp đen, mà một cấu trúc rõ ràng mà mình đã đo tới từng trang.