Câu hỏi cốt lõi
SQLite không phải là phiên bản nhỏ của Postgres. Nó là một công cụ có hình dạng khác. Toàn bộ cơ sở dữ liệu là một tệp trên đĩa, và ứng dụng làm việc với nó qua một thư viện được liên kết vào cùng tiến trình: không máy chủ, không mạng, không người dùng. Thiết kế đó khiến SQLite xuất sắc ở một số việc và không hợp với những việc khác.
Câu hỏi quyết định gần như không bao giờ là "SQLite có đủ nhanh không?" (thường là đủ). Mà là "hình dạng của ứng dụng có khớp với thế mạnh của SQLite không?" Có hai yếu tố quyết định điều đó: dữ liệu nằm ở đâu, và có bao nhiêu thứ ghi vào nó cùng lúc.
Dùng SQLite khi dữ liệu đi cùng ứng dụng
SQLite tỏa sáng khi cơ sở dữ liệu thuộc về một ứng dụng trên một máy. Tệp nằm cạnh code, ứng dụng mở trực tiếp, và đó là toàn bộ kiến trúc.
Schema nhỏ xíu đó có thể là toàn bộ backend của một ứng dụng thật. Vài trường hợp mẫu này rất tự nhiên:
- Ứng dụng desktop và di động. Mọi ứng dụng iOS và Android cần lưu trữ cục bộ có cấu trúc đều dùng SQLite bên dưới. Firefox, Chrome và phần lớn trình duyệt cũng vậy.
- Công cụ dòng lệnh.
git, trình quản lý package và trình quản lý dotfile đều dùng cơ sở dữ liệu nhúng. - Thiết bị nhúng. Router, ô tô, máy bay: bất cứ thứ gì cần một cơ sở dữ liệu chỉ chiếm vài trăm kilobyte.
- Bộ test. Một tệp SQLite mới (hoặc cơ sở dữ liệu
:memory:) cho mỗi test nhanh hơn và tách biệt hơn so với dựng Postgres.
Nếu dữ liệu không cần chia sẻ giữa nhiều máy, SQLite có lẽ là câu trả lời đúng.
Dùng SQLite cho trang web đọc nhiều
SQLite xử lý việc đọc rất tốt. Nhiều tiến trình đọc đồng thời, không tranh chấp, thời gian truy vấn tính bằng micro giây với tra cứu có index. Nếu trang web của bạn chủ yếu là người dùng đọc nội dung, như blog, tài liệu, trang giới thiệu, dashboard SaaS nhỏ, SQLite sẽ chạy ổn, thường còn tốt hơn Postgres qua mạng vì không phải đi một vòng qua mạng.
Vấn đề nằm ở lệnh ghi. SQLite tuần tự hóa các lệnh ghi: mỗi lúc chỉ một tiến trình ghi giữ được khóa. Với một blog có vài tác giả, điều đó không ai nhận ra. Với một ứng dụng chat có hàng nghìn người dùng gửi tin nhắn mỗi giây, đó là vấn đề.
Chế độ WAL (write-ahead logging, được trình bày ở phần sau) nâng giới hạn này lên đáng kể bằng cách cho phép các tiến trình đọc và tiến trình ghi chạy song song. Rất nhiều trang web production phục vụ hàng triệu request mỗi ngày bằng SQLite + WAL.
Dùng SQLite cho bộ nhớ đệm cục bộ và dữ liệu tạm
Bất cứ khi nào bạn cần lưu trữ cục bộ có cấu trúc, nhiều hơn một tệp JSON nhưng ít hơn một máy chủ cơ sở dữ liệu đầy đủ, SQLite rất khó bị đánh bại.
Log, bộ đệm dữ liệu phân tích, vùng trung gian cho ETL, kho đặc trưng cho machine learning, index của IDE: tất cả đều hợp với SQLite. Tệp dễ mang đi, ngôn ngữ truy vấn là SQL đầy đủ, và không có máy chủ nào phải trông chừng.
Đừng dùng SQLite khi có nhiều tiến trình ghi đồng thời
Đây là giới hạn khiến nhiều người vấp. SQLite dùng khóa ghi ở cấp cơ sở dữ liệu: một tiến trình ghi, hết. Hai tiến trình cùng cố insert vào đúng một thời điểm nghĩa là một bên phải chờ.
Với phần lớn ứng dụng, điều đó không quan trọng: lệnh ghi hiếm và nhanh. Nhưng nếu khối lượng công việc của bạn trông như sau:
- Một SaaS nhiều khách hàng với hàng nghìn người dùng cùng ghi một lúc,
- Một hàng đợi tin nhắn hoặc log sự kiện có thông lượng cao,
- Một backend game thời gian thực hoặc chat với trạng thái thay đổi liên tục,
thì SQLite sẽ trở thành điểm nghẽn. Postgres và MySQL dùng khóa ở cấp hàng và được xây dựng chính cho việc này. Hãy chọn chúng.
-- The error you'll see when writers pile up:
Error: database is locked
Nếu bạn gặp lỗi đó khi tải ở mức bình thường, SQLite là công cụ sai, chứ không phải một bug cần tìm cách lách.
Đừng dùng SQLite trên nhiều máy
SQLite là một thư viện chạy trong tiến trình. Ứng dụng đọc và ghi tệp trực tiếp, nghĩa là tệp phải nằm trên một ổ đĩa mà ứng dụng có thể read() và write() bằng các lời gọi hệ thống tệp thông thường.
Điều đó loại trừ:
- Nhiều máy chủ ứng dụng sau một bộ cân bằng tải, cùng muốn dùng chung một cơ sở dữ liệu. (Hệ thống tệp qua mạng như NFS về lý thuyết vẫn chạy nhưng sẽ làm hỏng tệp khi tải cao. Đừng làm vậy.)
- Serverless function, nơi mỗi lần gọi chạy trên một máy khác nhau.
- Pod Kubernetes cần một cơ sở dữ liệu dùng chung, trừ khi bạn triển khai một pod duy nhất với persistent volume.
Nếu kiến trúc của bạn có nhiều hơn một tiến trình trên nhiều hơn một máy cùng ghi vào cơ sở dữ liệu, bạn cần một cơ sở dữ liệu máy khách và máy chủ. Đó là ranh giới.
Đừng dùng SQLite khi cần người dùng ở cấp cơ sở dữ liệu
SQLite không có khái niệm người dùng, vai trò hay quyền. Cơ sở dữ liệu là một tệp: ai đọc được tệp thì đọc được mọi thứ; ai ghi được tệp thì ghi được mọi thứ. Kiểm soát truy cập là việc của hệ điều hành.
Với một ứng dụng desktop một người dùng, vậy là ổn. Với một hệ thống nhiều khách hàng, nơi những người khác nhau cần quyền khác nhau bên trong cơ sở dữ liệu, bạn nên dùng Postgres hoặc MySQL.
Danh sách kiểm tra nhanh để quyết định
Đi qua danh sách này. Nếu bạn trả lời "có" cho tất cả, SQLite có lẽ là lựa chọn tuyệt vời:
- Cơ sở dữ liệu nằm trên cùng máy với ứng dụng.
- Một tiến trình (hoặc vài tiến trình, chủ yếu đọc) làm việc với nó.
- Tổng dữ liệu vừa thoải mái trên một ổ đĩa: hàng terabyte vẫn ổn, nhưng vẫn là một ổ đĩa.
- Bạn không cần phân quyền người dùng ở cấp cơ sở dữ liệu.
- Ghi đồng thời chỉ thỉnh thoảng xảy ra, không phải khối lượng công việc chính.
Nếu có câu trả lời "không", hãy xem xét Postgres hoặc MySQL. Hai trang tiếp theo so sánh trực tiếp với chúng.
Điều cần nhớ
- SQLite là lựa chọn đúng khi cơ sở dữ liệu nằm cục bộ với ứng dụng: desktop, di động, thiết bị nhúng, công cụ dòng lệnh, bộ test, trang web đọc nhiều, bộ nhớ đệm cục bộ.
- Nó đủ chuẩn production: hàng tỷ thiết bị có sẵn nó. Các giới hạn nằm ở kiến trúc, không ở chất lượng.
- Bỏ qua nó khi bạn cần nhiều tiến trình ghi đồng thời, truy cập từ nhiều máy, hoặc phân quyền theo người dùng trong cơ sở dữ liệu.
Tiếp theo: cài đặt SQLite
Lý thuyết vậy là đủ. Trang tiếp theo hướng dẫn đưa SQLite lên máy của bạn: nó có sẵn trên macOS và phần lớn bản phân phối Linux, và chỉ cần tải một lần trên Windows, rồi kiểm tra cài đặt từ dòng lệnh.
Câu hỏi thường gặp
Khi nào nên dùng SQLite?
Dùng SQLite khi dữ liệu nằm cạnh ứng dụng: ứng dụng desktop, ứng dụng di động, công cụ dòng lệnh, thiết bị nhúng, trang web vừa và nhỏ, bộ nhớ đệm cục bộ và bộ test. Nó rất hợp bất cứ khi nào một tiến trình (hoặc vài tiến trình chủ yếu đọc) cần một cơ sở dữ liệu SQL thực thụ mà không phải chạy máy chủ riêng.
SQLite có dùng tốt cho production không?
Có, với đúng dạng khối lượng công việc. SQLite có sẵn trong mọi iPhone, thiết bị Android và phần lớn trình duyệt, và nó chạy nhiều trang web production. Giới hạn không nằm ở độ tin cậy mà ở khả năng truy cập đồng thời: mỗi lúc chỉ một tiến trình ghi trên toàn bộ cơ sở dữ liệu, và tệp cơ sở dữ liệu phải nằm trên cùng máy với ứng dụng.
Khi nào không nên dùng SQLite?
Bỏ qua SQLite khi bạn cần nhiều tiến trình ghi đồng thời, khi nhiều máy chủ ứng dụng phải truy cập cơ sở dữ liệu qua mạng, hoặc khi bạn cần phân quyền người dùng chi tiết. Đó là những việc Postgres và MySQL được xây dựng để làm.