15 điểm bởi GN⁺ 2024-07-28 | 4 bình luận | Chia sẻ qua WhatsApp
  • SQLite có thể đọc và ghi các Blob nhỏ (ví dụ: ảnh thumbnail) nhanh hơn 35% so với việc đọc hoặc ghi chúng từ các tệp riêng lẻ bằng fread() hoặc fwrite()
  • Ngoài ra, một cơ sở dữ liệu SQLite đơn lẻ lưu trữ các Blob 10KB sử dụng ít hơn khoảng 20% dung lượng đĩa so với việc lưu Blob thành các tệp riêng lẻ
  • Khác biệt về hiệu năng dường như xuất phát từ việc khi làm việc với cơ sở dữ liệu SQLite, các lệnh gọi hệ thống open()close() chỉ được gọi một lần, trong khi khi dùng Blob ở dạng tệp riêng lẻ thì mỗi Blob lại cần một lần open()close(). Có vẻ chi phí phụ trội của open()close() lớn hơn chi phí phụ trội khi dùng cơ sở dữ liệu
  • Việc giảm kích thước xảy ra do các tệp riêng lẻ được đệm tới bội số tiếp theo của kích thước khối của hệ thống tệp, trong khi Blob được đóng gói dày hơn trong cơ sở dữ liệu SQLite

Lưu ý

  • Con số 35% chỉ mang tính xấp xỉ. Thời gian thực tế khác nhau tùy theo phần cứng, hệ điều hành, chi tiết thí nghiệm và còn có biến động hiệu năng ngẫu nhiên trên phần cứng thực
  • Con số 35% là kết quả khi tác giả chạy thử nghiệm trên tất cả các hệ thống mà họ dễ dàng sử dụng được. Một số người phản biện báo cáo rằng trên hệ thống của họ SQLite có độ trễ cao hơn I/O trực tiếp. Hiện vẫn chưa hiểu rõ sự khác biệt đó
  • SQLite cho thấy không hoạt động tốt bằng I/O trực tiếp khi chạy thí nghiệm với bộ nhớ đệm hệ thống tệp ở trạng thái lạnh
  • Tài liệu này phản bác giả định phổ biến rằng cơ sở dữ liệu quan hệ phải chậm hơn I/O hệ thống tệp trực tiếp
  • Theo một nghiên cứu năm 2022, trong tác vụ thực tế SQLite nhanh hơn khoảng 2 lần so với Btrfs và Ext4 trên Linux

Cách đo

  • Hiệu năng I/O được đo bằng chương trình kvtest.c trong cây mã nguồn SQLite
  • Để biên dịch chương trình kiểm thử này, hãy gom tệp nguồn kvtest.c cùng với các tệp nguồn amalgamation của SQLite là sqlite3.csqlite3.h vào một thư mục, rồi trên Unix chạy lệnh tương tự như sau
  • Chương trình kvtest tạo ra từ lệnh này được dùng để tạo cơ sở dữ liệu kiểm thử gồm 100.000 Blob ngẫu nhiên không nén, mỗi Blob có kích thước từ 8.000 đến 12.000 byte
  • Để tạo bản sao của tất cả Blob thành các tệp riêng lẻ trong một thư mục, có thể chạy lệnh export với tùy chọn dòng lệnh --tree
  • Để đo hiệu năng đọc Blob từ cơ sở dữ liệu và đọc Blob từ các tệp riêng lẻ, dùng các lệnh sau
  • Tùy chọn --blob-api cho phép SQLite dùng hàm sqlite3_blob_read() để nạp nội dung Blob thay vì thực thi câu lệnh SQL, nên chạy nhanh hơn một chút trong các bài kiểm thử đọc

Đo hiệu năng đọc

  • Trên Windows10, có thể đọc nội dung từ cơ sở dữ liệu SQLite nhanh hơn khoảng 5 lần so với đọc trực tiếp từ đĩa
  • Trên Android, SQLite nhanh hơn khoảng 35% so với đọc từ đĩa
  • Khi đọc từ cơ sở dữ liệu ánh xạ bộ nhớ bằng sqlite3_blob_read(), trên Mac và Android tốc độ nhanh gấp 2 lần so với đọc các tệp riêng lẻ từ đĩa, còn trên Windows nhanh gấp 10 lần

Đo hiệu năng ghi

  • Trên mọi hệ thống, cả I/O trực tiếp lẫn SQLite đều có hiệu năng ghi chậm hơn đọc từ 5 đến 15 lần
  • Trong bài kiểm thử ghi, phần mềm antivirus hầu như không ảnh hưởng đến việc ghi bằng SQLite, nhưng ghi trực tiếp ra đĩa chậm hơn khoảng 10 lần
  • Có lẽ là vì SQLite chỉ thay đổi một tệp cơ sở dữ liệu duy nhất, trong khi ghi trực tiếp ra đĩa làm thay đổi hàng nghìn tệp riêng lẻ mà antivirus phải quét

Kết quả chung

  • SQLite có sức cạnh tranh với Blob được lưu trong các tệp đĩa riêng biệt ở cả đọc lẫn ghi, và thường nhanh hơn
  • SQLite nhanh hơn rất nhiều so với ghi trực tiếp ra đĩa trên Windows khi bật bảo vệ antivirus
  • Đọc nhanh hơn ghi khoảng 10 lần trên mọi hệ thống, cả với SQLite lẫn I/O đĩa trực tiếp
  • Hiệu năng I/O khác biệt lớn tùy hệ điều hành và phần cứng. Cần tự đo đạc trước khi đưa ra kết luận
  • Một số engine cơ sở dữ liệu SQL khác khuyên nhà phát triển lưu Blob thành tệp riêng rồi lưu tên tệp trong cơ sở dữ liệu. Trong trường hợp đó, lưu toàn bộ Blob trong cơ sở dữ liệu sẽ cho hiệu năng đọc và ghi tốt hơn nhiều với SQLite

Ý kiến của GN⁺

  • Việc SQLite có hiệu năng tốt hơn đọc và ghi các tệp riêng lẻ là điều rất thú vị. Điều này có vẻ có thể giúp cải thiện hiệu năng của các ứng dụng dùng cơ sở dữ liệu
  • Tuy nhiên, kết quả benchmark này không nhất thiết áp dụng phổ quát cho mọi tình huống. Nó có thể thay đổi tùy theo đặc tính dữ liệu, mẫu truy cập, cấu hình phần cứng, v.v. Với các ứng dụng quan trọng, điều quan trọng là phải benchmark bằng tải công việc thực tế
  • SQLite cũng có lợi thế là có thể tránh bị antivirus quét. Điều này đặc biệt hữu ích với các ứng dụng xử lý số lượng lớn tệp nhỏ
  • Nhược điểm của SQLite là mọi dữ liệu được lưu trong một tệp duy nhất, nên nếu tệp cơ sở dữ liệu bị hỏng thì toàn bộ dữ liệu có thể bị mất. Vì vậy, việc sao lưu tệp cơ sở dữ liệu định kỳ là rất quan trọng

4 bình luận

 
iolothebard 2024-07-28

Hoặc phải tính cả việc cơ sở dữ liệu truy cập các thuộc tính tệp (tên tệp, kích thước, quyền truy cập, …),
nếu không thì có lẽ nên so sánh với I/O khối chứ không phải I/O tệp thì đúng hơn…
Dù thế nào đi nữa thì SQLite đúng là nhanh thật.

 
GN⁺ 2024-07-28
Ý kiến trên Hacker News
  • Do không có thuộc tính hay siêu dữ liệu của hệ thống tệp nên không cần ghi hay cập nhật thuộc tính bổ sung, cũng không cần kiểm tra tệp vật lý hay pipe/liên kết tượng trưng, kiểm tra quyền, lệch căn chỉnh kích thước khối, nên chỉ cần một lệnh mở duy nhất

    • Điều này có thể hiểu được khi loại bỏ tính năng và bỏ qua thiết kế đa dụng
    • Nếu dùng ánh xạ fuse cho SQLite rồi mount thư mục để truy cập thì hiệu năng có thể tương đương hoặc còn chậm hơn
    • Nếu tắt thuộc tính và tạo một hệ thống tệp tùy chỉnh với kích thước khối được tối ưu thì có thể đạt hiệu năng tương tự
    • Có sự đơn giản ở chỗ có thể dùng các lệnh shell như rsync để duyệt và thao tác tệp
    • SQLite phù hợp với tài sản tĩnh được đóng gói hoặc các ứng dụng dạng appliance
  • Mức tăng tốc gấp 4 lần trên Windows 10 nhấn mạnh các lời gọi hệ thống tệp của Windows chậm đến mức nào

  • Có ý tưởng ghi lại mọi nốt phát ra từ piano điện theo thời gian thực

    • Dùng SQLite để lưu trong một bảng duy nhất, mỗi hàng là một sự kiện MIDI của piano
    • Hiệu năng tốt và có thể phân tích sau này
  • Thật thú vị khi so sánh nghiên cứu cơ sở dữ liệu với nghiên cứu hệ điều hành

    • Cơ sở dữ liệu quan hệ được tối ưu cho các bản ghi riêng lẻ nhỏ và tính nhất quán
    • Khi kích thước hàng tăng lên thì hiệu năng giảm mạnh
  • Đang cân nhắc thêm vào SQLite DB ở chế độ WAL2

    • Gần như không có mức phạt hiệu năng khi ghi và có lợi thế lớn cho việc đọc/phân tích
  • Trong cơ sở dữ liệu SQLite, các lời gọi hệ thống open()close() chỉ được gọi một lần

    • Ít overhead hơn so với dùng blob trong các tệp riêng lẻ
  • Không khuyến nghị lưu tệp bằng cách dùng trường blob của SQLite

    • Kích thước blob tối đa là 2GB
    • Phải tuần tự hóa/giải tuần tự hóa đối tượng thành byte
    • Cần tệp để tương tác với các hệ thống/dịch vụ khác
    • SQLite có các cấu hình để xử lý yêu cầu song song, nhưng cơ sở dữ liệu bị khóa do các yêu cầu cạnh tranh
  • Việc thứ được xây trên hệ thống tệp lại nhanh hơn hệ thống tệp có nghĩa là hệ thống tệp bị chậm khi được sử dụng theo cách chưa tối ưu

  • Xóa nhiều hàng trong cơ sở dữ liệu SQLite chậm hơn xóa tệp

  • Mọi truy cập hệ thống tệp/ổ đĩa đều do hệ điều hành quản lý

    • Tệp cơ sở dữ liệu được lưu thành các cụm trên đĩa
    • Hệ quản trị cơ sở dữ liệu được tạo ra để thuận tiện giải quyết các miền và vấn đề cụ thể
 
halfenif 2024-07-28

20 năm trước tôi đã dùng rất hiệu quả kiến trúc đưa file vào Oracle DB dưới dạng blob.. nhưng lần nào cũng phải giải thích cho mọi người về những ưu điểm của nó. Tất nhiên là không phải lần nào cũng thuyết phục được.

 
narusas 2024-07-29

Nếu là 20 năm trước thì giá SAN DISK của Oracle hẳn là không hề rẻ đâu nhỉ..