小巧、快速、可靠。
三選一。
SQLite 封存檔 (SQLite Archive Files)

1. 簡介

「SQLite 封存檔」是一種檔案容器,類似於 ZIP 封存檔Tarball,但它基於 SQLite 資料庫。

SQLite 封存檔是一個普通的 SQLite 資料庫檔案,其中包含以下表格作為其綱要的一部分

CREATE TABLE sqlar(
  name TEXT PRIMARY KEY,  -- name of the file
  mode INT,               -- access permissions
  mtime INT,              -- last modification time
  sz INT,                 -- original file size
  data BLOB               -- compressed content
);

SQLAR 表的每一列都保存著單個檔案的內容。檔名(相對於封存根目錄的完整路徑名)位於「name」欄位中。「mode」欄位是一個整數,表示檔案的 Unix 樣式存取權限。「mtime」是檔案的修改時間,以自 1970 年以來的秒數表示。「sz」是檔案原始未壓縮的大小。「data」欄位包含檔案內容。內容通常使用 Deflate 壓縮,但並非總是如此。如果「sz」欄位等於「data」欄位的大小,則內容以未壓縮的形式儲存。

1.1. 資料庫作為容器物件

SQLite 封存檔是一個更廣泛概念的一個例子,即 SQLite 資料庫可以充當一個容器物件,容納許多較小的資料元件。

對於像 PostgreSQL 或 Oracle 這樣的客戶端/伺服器資料庫,使用者和開發人員傾向於將資料庫視為服務或「節點」,而不是物件。這是因為資料庫內容分散在伺服器上的多個檔案中,或者可能分散在服務叢集中的多個伺服器上。人們無法指向單個檔案甚至單個目錄並說「這是資料庫」。

相比之下,SQLite 將所有內容儲存在磁碟上的單個檔案中。您可以指向該單個檔案並說「這是資料庫」。它的行為就像一個物件。SQLite 資料庫檔案可以複製、重新命名、作為電子郵件附件發送、作為 POST HTTP 請求的參數傳遞,或者像其他資料物件(例如圖像、文件或媒體檔案)一樣處理。

研究表明,許多應用程式已經將 SQLite 用作容器物件。例如,Kennedy(與 SQLite 開發人員 無關)報告說,14% 的 Android 應用程式從不寫入其 SQLite 資料庫。據信,這些應用程式正在從雲端下載整個資料庫,然後根據需要在本地使用這些資訊。換句話說,這些應用程式使用 SQLite 並不是作為資料庫,而是作為可查詢的線路傳輸格式。

1.2. 使用 SQLite 封存檔的應用程式

Fossil 分散式版本控制系統為使用者提供了以 Tarball、ZIP 封存檔或 SQLite 封存檔下載簽入的選項。

2. SQLite 封存檔的優點

  1. SQLite 封存檔很靈活。ZIP 封存檔和 Tarball 僅限於儲存檔案。SQLite 封存檔可以儲存檔案以及應用程式認為有用的任何其他表格和/或關聯式資料。

  2. SQLite 封存檔是交易式的。更新是原子性和持久的,即使在更新過程中發生當機或斷電也是如此。即使其他程序正在同時更新封存檔,讀取器也會看到一致且不變的內容版本。

  3. SQLite 封存檔可以增量更新。可以新增、移除或替換個別檔案,而無需重寫整個封存檔。

  4. 可以使用高階查詢語言 (SQL) 查詢 SQLite 封存檔。以下是一些範例:

    • 封存檔中名稱以 ".h" 或 ".cpp" 結尾的所有檔案的總大小是多少?
    • 壓縮率低於 25% 的檔案佔總檔案的百分比是多少?
    • 封存檔中有多少個可執行檔?
    無需解壓縮或提取任何內容即可回答這類問題(以及無數其他問題)。
  5. 已經將 SQLite 用於其他用途的應用程式可以輕鬆地新增對 SQLite 封存檔的支援,只需使用一個小型擴充功能 (https://sqlite.dev.org.tw/src/file/ext/misc/sqlar.c) 來處理內容的壓縮和解壓縮即可。如果封存檔中的檔案未壓縮,甚至可以省略這個小型擴充功能。相比之下,支援 ZIP 封存檔和/或 Tarball 需要單獨的函式庫或大量的額外自訂程式碼,或者有時兩者都需要。

  6. SQLite 封存檔可以繞過防火牆施加的審查。例如,某些被認為「危險」的檔案類型(例如:DLL)會被 Gmail 封鎖,而且可能許多其他電子郵件服務和防火牆也會封鎖,即使這些檔案包裝在 ZIP 封存檔或 Tarball 中也是如此。但這些防火牆通常(尚)不了解 SQLite 封存檔,因此可以將內容放入 SQLite 封存檔中以規避審查。

3. SQLite 封存檔的缺點

  1. SQLite 封存檔是一種相對較新的格式。它在 2014 年首次被描述。另一方面,ZIP 封存檔和 Tarball 已經存在數十年,並且已牢固確立為標準格式。大多數程式設計師都知道 ZIP 封存檔或 Tarball 是什麼,但如果您說「SQLite 封存檔」,您更有可能得到「什麼?」的回覆。用於處理 ZIP 封存檔和 Tarball 的工具更有可能安裝在一般電腦上。

  2. 由於 SQLite 資料庫是一種更通用的格式(它被設計用於執行比僅儲存一堆檔案更多的工作),因此它不像 ZIP 封存檔或 Tarball 格式那麼精簡。SQLite 封存檔通常比同等的 ZIP 封存檔大約 1% 的檔案大小。Tarball 是作為一個單元進行壓縮的,而不是像 SQLite 和 ZIP 封存檔那樣單獨壓縮每個檔案。由於這些原因,Tarball 通常比 ZIP 或 SQLite 封存檔更小。

    例如,下表顯示了 SQLite 封存檔、ZIP 封存檔和 SQLite 3.22.0 原始程式碼樹中 1,743 個檔案的 Tarball 的相對大小

    SQLite 封存檔10,754,048
    ZIP 封存檔(使用 Info-ZIP 3.0)10,662,365
    ZIP 封存檔(使用 zipfile10,390,215
    Tarball 9,781,109
  3. SQLite 封存檔僅支援 Deflate 壓縮方法。Tarball 和 ZIP 封存檔支援更廣泛的壓縮方法。

4. 從命令列管理 SQLite 封存檔

建立、更新、列出和提取 SQLite 封存檔的建議方法是使用 SQLite 3.23.0 版(2018 年 4 月 2 日)或更高版本的 sqlite3.exe 命令列介面。此 CLI 支援 -A 命令列選項,可以輕鬆管理 SQLite 封存檔。SQLite 3.22.0 版(2018 年 1 月 22 日)的 CLI 具有用於管理 SQLite 封存檔的 .archive 命令,但這需要與 shell 互動。

要使用以下其中一個命令列出名為「example.sqlar」的 SQLite 封存檔中的所有檔案:

sqlite3 example.sqlar -At
sqlite3 example.sqlar -Atv

要從名為「example.sqlar」的 SQLite 封存檔中提取所有檔案:

sqlite3 example.sqlar -Ax

要建立一個名為「alltxt.sqlar」的新 SQLite 封存檔,其中包含目前目錄中的所有 *.txt 檔案:

sqlite3 alltxt.sqlar -Ac *.txt

要在現有的 SQLite 封存檔中新增或更新檔案:

sqlite3 example.sqlar -Au *.md

如需使用提示和所有選項的摘要,只需在沒有其他參數的情況下向 CLI 提供 -A 選項即可

sqlite3 -A

如果檔案名稱參數是 ZIP 壓縮檔而不是 SQLite 資料庫,所有這些命令的工作方式都相同。

4.1. 其他命令列工具

就像有「zip」程式來管理 ZIP 壓縮檔,以及「tar」程式來管理 Tarball 一樣,「sqlar」程式是用來管理 SQL 壓縮檔的。「sqlar」程式能夠建立新的 SQL 壓縮檔、列出現有壓縮檔的內容、從壓縮檔中新增或移除檔案,以及/或者從壓縮檔中解壓縮檔案。一個單獨的「sqlarfs」程式能夠將 SQL 壓縮檔掛載為Fuse 檔案系統

5. 從應用程式程式碼管理 SQL 壓縮檔

應用程式可以透過連結 SQLite 並包含 ext/misc/sqlar.c 副檔名來處理壓縮和解壓縮,輕鬆讀取或寫入 SQL 壓縮檔。 sqlar.c 副檔名建立了兩個新的 SQL 函式。

sqlar_compress(X)

sqlar_compress(X) 函式嘗試使用預設演算法壓縮 Blob X 的副本,並將結果作為 Blob 返回。如果輸入 X 不是可壓縮的 Blob,則返回 X 的副本。這個例程在將內容插入 SQL 壓縮檔時使用。

sqlar_uncompress(Y,SZ)

sqlar_uncompress(Y,SZ) 函式將會復原 sqlar_compress(X) 完成的壓縮。 Y 參數是被壓縮的內容(先前呼叫 sqlar_compress() 的輸出),而 SZ 是產生 Y 的輸入 X 的原始未壓縮大小。如果 SZ 小於或等於 Y 的大小,則表示未發生壓縮,因此 sqlar_uncompress(Y,SZ) 返回 Y 的副本。否則,sqlar_uncompress(Y,SZ) 會對 Y 執行 Inflate 演算法以將其解壓縮並恢復到其原始格式,並返回未壓縮的內容。這個例程在從 SQL 壓縮檔解壓縮內容時使用。

使用上述兩個例程,應用程式可以輕鬆地將新記錄插入 SQL 壓縮檔或從中解壓縮現有記錄。使用如下程式碼將新的記錄插入 SQL 壓縮檔:

INSERT INTO sqlar(name,mode,mtime,sz,data)
 VALUES ($name,$mode,strftime('%s',$mtime),
         length($content),sqlar_compress($content));

使用如下程式碼從 SQL 壓縮檔中解壓縮一個項目:

SELECT name, mode, datetime(mtime,'unixepoch'), sqlar_uncompress(data,sz)
  FROM sqlar
 WHERE ...;

以上程式碼適用於一般情況。對於僅儲存未壓縮或不可壓縮內容的 SQL 壓縮檔的特殊情況(例如,在僅儲存 JPEG、GIF 和/或 PNG 影像的 SQL 壓縮檔中可能會出現這種情況),則可以將內容插入資料庫或從資料庫中解壓縮,而無需使用 sqlar_compress() 和 sqlar_uncompress() 函式,也不需要 sqlar.c 副檔名。

本頁面最後修改時間:2023-01-12 11:08:35 UTC