Important
A new version of this extension written in C is now available. This C version offers the advantage of being usable across different platforms, languages, and runtimes. It is not publicly available and is provided under a one-time fee in perpetuity license with support. The original Go version will remain freely available. For more information about the C extension, please email jtarchie@gmail.com.
SQLiteZSTD provides a tool for accessing SQLite databases compressed with Zstandard seekable (zstd) in a read-only manner. Its functionality is based on the SQLite3 Virtual File System (VFS) in Go.
Please note, SQLiteZSTD is specifically designed for reading data and does not support write operations.
- Read-only access to Zstd-compressed SQLite databases.
- Interface through SQLite3 VFS.
- The compressed database is seekable, facilitating ease of access.
Your database needs to be compressed in the seekable Zstd format. I recommend using this CLI tool:
go get -a github.com/SaveTheRbtz/zstd-seekable-format-go/...
go run github.com/SaveTheRbtz/zstd-seekable-format-go/cmd/zstdseek \
-f <dbPath> \
-o <dbPath>.zst
The CLI provides different options for compression levels, but I do not have specific recommendations for best usage patterns.
Below is an example of how to use SQLiteZSTD in a Go program:
import (
sqlitezstd "github.com/jtarchie/sqlitezstd"
)
initErr := sqlitezstd.Init()
if initErr != nil {
panic(fmt.Sprintf("Failed to initialize SQLiteZSTD: %s", initErr))
}
db, err := sql.Open("sqlite3", "<path-to-your-file>?vfs=zstd")
if err != nil {
panic(fmt.Sprintf("Failed to open database: %s", err))
}
// Set PRAGMA for each connection
db.SetConnMaxLifetime(0) // Disable connection pooling
db.SetMaxOpenConns(1) // Allow only one open connection
conn, err := db.Conn(context.Background())
if err != nil {
panic(fmt.Sprintf("Failed to get connection: %s", err))
}
defer conn.Close()
// PRAGMA's are not persisted across `database/sql` pooled connections
// this is to _ensure_ it happens for this one.
_, err = conn.ExecContext(context.Background(), `PRAGMA temp_store = memory;`)
if err != nil {
panic(fmt.Sprintf("Failed to set PRAGMA: %s", err))
}
// Use conn for subsequent operations to ensure PRAGMA is applied
In this Go code example:
- The SQLiteZSTD library is initialized first with
sqlitezstd.Init()
. - The
sql.Open()
function takes as a parameter the path to the compressed SQLite database, appended with a query string withvfs=zstd
to use the VFS. - Setting the
PRAGMA
ensures that the read only VFS is not used to create temporary files.
Here's a simple benchmark comparing performance between reading from an
uncompressed vs. a compressed SQLite database, involving the insertion of 10k
records and retrieval of the MAX
value (without an index) and FTS5.
BenchmarkReadUncompressedSQLite-4 159717 7459 ns/op 473 B/op 15 allocs/op
BenchmarkReadUncompressedSQLiteFTS5Porter-4 2478 471685 ns/op 450 B/op 15 allocs/op
BenchmarkReadUncompressedSQLiteFTS5Trigram-4 100 10449792 ns/op 542 B/op 16 allocs/op
BenchmarkReadCompressedSQLite-4 266703 3877 ns/op 2635 B/op 15 allocs/op
BenchmarkReadCompressedSQLiteFTS5Porter-4 2335 487430 ns/op 33992 B/op 16 allocs/op
BenchmarkReadCompressedSQLiteFTS5Trigram-4 48 21235303 ns/op 45970431 B/op 148 allocs/op
BenchmarkReadCompressedHTTPSQLite-4 284820 4341 ns/op 3312 B/op 15 allocs/op