SQLite là một cơ sở dữ liệu quan hệ, phổ biến mà bạn nhúng vào ứng dụng của mình. Với lượng dữ liệu ngày càng tăng trong cơ sở dữ liệu của bạn, bạn cần áp dụng điều chỉnh hiệu suất SQLite. Bài viết này thảo luận về các chỉ số và các cạm bẫy của nó, việc sử dụng công cụ lập kế hoạch truy vấn, chế độ ghi nhật ký Ghi-Ahead-Ghi nhật ký (WAL) và tăng kích thước bộ nhớ cache. Nó cũng giải thích chi tiết về tầm quan trọng của việc đo lường tác động của các chỉnh sửa của bạn, bằng cách sử dụng các bài kiểm tra tự động.
Giới thiệu
SQLite là một hệ thống cơ sở dữ liệu quan hệ (DB) phổ biến . Không giống như những người anh em lớn hơn, dựa trên máy chủ, chẳng hạn như MySQL, SQLite có thể được nhúng vào ứng dụng của bạn dưới dạng thư viện . SQLite có một bộ tính năng rất giống nhau và cũng có thể xử lý hàng triệu hàng, nếu bạn biết một số mẹo và thủ thuật về điều chỉnh hiệu suất. Như các phần sau sẽ hiển thị, có nhiều điều cần biết về điều chỉnh hiệu suất SQLite hơn là chỉ tạo chỉ số.
Tạo chỉ số nhưng phải thận trọng
Ý tưởng cơ bản của chỉ mục là tăng tốc độ đọc dữ liệu cụ thể , nghĩa là, SELECT
câu lệnh có WHERE
mệnh đề. Các chỉ số cũng tăng tốc sắp xếp dữ liệu (ORDER BY
) hoặc JOIN
bảng ing. Thật không may, các chỉ mục là con dao hai lưỡi, vì chúng tiêu tốn thêm dung lượng đĩa và làm chậm quá trình thao tác dữ liệu (INSERT
, UPDATE
, DELETE
).
Lời khuyên chung là tạo càng ít chỉ số càng tốt, nhưng càng nhiều càng tốt . Ngoài ra, các chỉ số chỉ có ý nghĩa đối với lớn hơn cơ sở dữ liệu, với hàng nghìn hoặc hàng triệu hàng.
Sử dụng công cụ lập kế hoạch truy vấn để phân tích các truy vấn của bạn
Cách các chỉ mục được SQLite sử dụng nội bộ được ghi lại, nhưng không dễ hiểu lắm. Như được giải thích kỹ hơn bởi bài viết này, bạn nên phân tích một truy vấn bằng cách đặt tiền tố cho nó bằng EXPLAIN QUERY PLAN
. Hãy xem xét mọi dòng đầu ra, trong đó có ba biến thể cơ bản:
-
SEARCH table ...
dòng là một dấu hiệu tốt - SQLite sử dụng một trong các chỉ số của bạn! -
SCAN table ... USING INDEX
là một dấu hiệu xấu, -
SCAN table ...
thậm chí còn tệ hơn!
Cố gắng tránh SCAN table [using index]
các mục nhập trong đầu ra của EXPLAIN QUERY PLAN
bất cứ khi nào có thể, bởi vì bạn sẽ gặp phải các vấn đề về hiệu suất trên cơ sở dữ liệu lớn hơn. Sử dụng EXPLAIN QUERY PLAN
để thêm hoặc sửa đổi lặp đi lặp lại các chỉ số của bạn cho đến khi không còn SCAN table
các mục xuất hiện.
Tối ưu hóa các truy vấn liên quan đến IS NOT
Kiểm tra IS NOT ...
đắt bởi vì SQLite sẽ phải quét tất cả các hàng của bảng, ngay cả khi cột bị ảnh hưởng có chỉ mục . Các chỉ số chỉ hữu ích nếu bạn tìm kiếm các giá trị cụ thể, tức là so sánh liên quan đến < (nhỏ hơn), > (lớn hơn) hoặc = (ngang nhau), nhưng họ không đăng ký! =(không bằng nhau).
Một mẹo nhỏ là bạn có thể thay thế cột WHERE column != value
với WHERE column > value OR column < value
. Điều này sẽ sử dụng chỉ mục của cột và ảnh hưởng hiệu quả đến tất cả các hàng có giá trị không bằng value
. Tương tự, WHERE stringColumn != ''
có thể được thay thế bằng WHERE stringColumn > ''
, bởi vì các chuỗi có thể sắp xếp được. Tuy nhiên, khi áp dụng thủ thuật này, hãy đảm bảo rằng bạn biết cách SQLite xử lý NULL
so sánh. Ví dụ:SQLite đánh giá NULL > ''
dưới dạng FALSE
.
Nếu bạn sử dụng thủ thuật so sánh như vậy, có một lưu ý khác trong trường hợp truy vấn của bạn chứa WHERE
và ORDER BY
, mỗi cột có một cột khác nhau:điều này sẽ làm cho truy vấn trở lại không hiệu quả. Nếu có thể, hãy sử dụng giống nhau trong WHERE
và ORDER BY
hoặc xây dựng chỉ mục bao trùm liên quan đến cả WHERE
và ORDER BY
cột.
Cải thiện tốc độ ghi với Write-Ahead-Log
Ghi nhật ký trước (WAL) chế độ nhật ký cải thiện đáng kể hiệu suất ghi / cập nhật , so với khôi phục mặc định chế độ nhật ký. Tuy nhiên, như được ghi lại ở đây, có một số lưu ý . Ví dụ:chế độ WAL không khả dụng trên một số hệ điều hành. Ngoài ra, có đảm bảo tính nhất quán của dữ liệu bị giảm trong trường hợp lỗi phần cứng . Đảm bảo đọc vài trang đầu tiên để hiểu bạn đang làm gì.
Tôi thấy rằng lệnh PRAGMA synchronous = NORMAL
cung cấp tốc độ tăng gấp 3-4 lần. Đặt journal_mode
thành WAL
sau đó cải thiện hiệu suất một lần nữa đáng kể (khoảng 10 lần hoặc hơn, tùy thuộc vào hệ điều hành).
Ngoài những lưu ý mà tôi đã đề cập, bạn cũng nên lưu ý những điều sau:
- Sử dụng chế độ nhật ký WAL, sẽ có hai tệp bổ sung bên cạnh tệp cơ sở dữ liệu trên hệ thống tệp của bạn, chúng có cùng tên với cơ sở dữ liệu nhưng có hậu tố là “-shm” và “-wal”. Thông thường bạn không cần quan tâm, nhưng nếu bạn gửi cơ sở dữ liệu đến một máy khác trong khi ứng dụng của bạn đang chạy, đừng quên bao gồm hai tệp đó. SQLite sẽ thu gọn hai tệp này vào tệp chính bất cứ khi nào bạn đóng tất cả các kết nối cơ sở dữ liệu đang mở.
- Hiệu suất chèn hoặc cập nhật đôi khi sẽ giảm, bất cứ khi nào truy vấn kích hoạt việc hợp nhất nội dung tệp nhật ký WAL vào tệp cơ sở dữ liệu chính. Đây được gọi là điểm kiểm tra , xem tại đây.
- Tôi thấy rằng
PRAGMA
s thay đổijournal_mode
vàsynchronous
dường như không được lưu trữ liên tục trong cơ sở dữ liệu. Vì vậy, tôi luôn luôn thực thi lại chúng bất cứ khi nào tôi mở một kết nối cơ sở dữ liệu mới, thay vì chỉ thực thi chúng khi tạo bảng lần đầu tiên.
Đo lường mọi thứ
Bất cứ khi nào bạn thêm các chỉnh sửa về hiệu suất, hãy đảm bảo đo lường tác động. Kiểm tra (đơn vị) tự động là một cách tiếp cận tuyệt vời cho việc này. Chúng giúp tạo tài liệu phát hiện của bạn cho nhóm của bạn và chúng sẽ phát hiện ra các hành vi sai lệch theo thời gian , ví dụ. khi bạn cập nhật lên phiên bản SQLite mới hơn. Ví dụ về những gì bạn có thể đo lường:
- Hiệu quả của việc sử dụng WAL chế độ nhật ký qua khôi phục cách thức? Tác dụng của
PRAGMA
nâng cao hiệu suất khác (được cho là) là gì s? - Sau khi bạn thêm / thay đổi / xóa chỉ mục,
SELECT
sẽ nhanh hơn bao nhiêu câu lệnh trở thành? LàmINSERT/DELETE/UPDATE
chậm hơn bao nhiêu câu lệnh trở thành? - Các chỉ số sử dụng bao nhiêu dung lượng đĩa bổ sung?
Đối với bất kỳ thử nghiệm nào trong số này, hãy xem xét lặp lại chúng với các kích thước cơ sở dữ liệu khác nhau. Ví dụ. chạy chúng trên cơ sở dữ liệu trống và cả trên cơ sở dữ liệu đã chứa hàng nghìn (hoặc hàng triệu) mục nhập. Bạn cũng nên chạy thử nghiệm trên các thiết bị và hệ điều hành khác nhau, đặc biệt nếu môi trường phát triển và sản xuất của bạn khác biệt đáng kể.
Điều chỉnh kích thước bộ nhớ cache
SQLite lưu trữ thông tin tạm thời trong bộ nhớ cache (trong RAM), ví dụ:trong khi xây dựng kết quả của SELECT
truy vấn hoặc khi thao tác dữ liệu chưa được cam kết. Theo mặc định, kích thước này là nhỏ nhất là 2 MB . Máy tính để bàn hiện đại có thể tiết kiệm hơn nhiều. Chạy PRAGMA cache_size = -kibibytes
để tăng giá trị này (nhớ cái trừ ký trước giá trị!). Xem ở đây để biết thêm thông tin. Một lần nữa, đo lường cài đặt này có tác động gì đến hiệu suất!
Sử dụng REPLACE INTO để tạo hoặc cập nhật một hàng
Đây có thể không phải là một điều chỉnh hiệu suất quá nhiều vì nó là một thủ thuật nhỏ gọn gàng. Giả sử bạn cần cập nhật một hàng trong bảng t
hoặc tạo một hàng nếu nó chưa tồn tại. Thay vì sử dụng hai truy vấn (SELECT
theo sau là INSERT
hoặc UPDATE
), sử dụng REPLACE INTO
(tài liệu chính thức).
Để điều này hoạt động, hãy thêm một cột giả bổ sung (ví dụ:replacer
) vào bảng t
, có UNIQUE
hạn chế. Khai báo của cột có thể, ví dụ:được ... replacer INTEGER UNIQUE ...
đó là một phần của CREATE TABLE
của bạn tuyên bố. Sau đó, sử dụng một truy vấn chẳng hạn như
REPLACE INTO t (col1, col2, ..., replacer) VALUES (?,?,...,1)
Code language: SQL (Structured Query Language) (sql)
Khi truy vấn này chạy lần đầu tiên, nó sẽ chỉ thực hiện một INSERT
. Khi nó được chạy lần thứ hai, UNIQUE
ràng buộc của replacer
cột sẽ kích hoạt và hành vi giải quyết xung đột sẽ khiến hàng cũ bị loại bỏ, tự động tạo hàng mới. Bạn cũng có thể thấy lệnh UPSERT liên quan hữu ích.
Kết luận
Khi số lượng hàng trong cơ sở dữ liệu của bạn tăng lên, việc điều chỉnh hiệu suất trở thành một điều cần thiết. Chỉ số là giải pháp phổ biến nhất. Họ đánh đổi cải thiện độ phức tạp về thời gian để giảm độ phức tạp về không gian, cải thiện tốc độ đọc, đồng thời ảnh hưởng tiêu cực đến hiệu suất sửa đổi dữ liệu. Tôi đã chứng minh, bạn cần phải hết sức cẩn thận khi so sánh với bất bình đẳng trong SELECT
vì SQLite không thể sử dụng các chỉ số cho các kiểu so sánh như vậy. Tôi thường khuyên bạn nên sử dụng công cụ lập kế hoạch truy vấn điều đó giải thích những gì xảy ra nội bộ cho mỗi truy vấn SQL. Bất cứ khi nào bạn chỉnh sửa điều gì đó, hãy đo lường tác động!