SQLite ID Benchmarks

Published - 3 min read

Choosing IDs in SQLite

Picking the ID for a database is likely the first important decision you’ll make. It’s hard to change later.

Furthermore, if you are exposing IDs to the client, then you can’t use Integer unless you’re ok with leaking information (e.g. how many users there are). So you’re left with UUIDv4, UUIDv7 via SipHash-masked UUIDv4, or dual column strategy that PlanetScale uses.

SQLite also has the option of tables without rowid, which is an optimization with various trade-offs.

Strategies

Here are the various strategies I tested:

IntegerWithUuid4ColNoIndex was added to act as a control for the dual column strategies, to learn how the additional unique index affects performance.

Methodology

I tested with 200000 user rows, and a few more tables to mimic a small real-world application, using rsqlite and criterion for the benchmarks. These were run on my MacBook M4 Pro.

Since SQLite isn’t supposed to be a high-performance database, I didn’t set the number of rows higher. 200k sounds about right for a small SaaS.

SQLite was configured with the following settings:

sql
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA trusted_schema = OFF;
PRAGMA busy_timeout = 5000;
PRAGMA page_size = 8192;
PRAGMA temp_store = MEMORY;
PRAGMA foreign_keys = ON;
PRAGMA journal_size_limit = 67108864;
PRAGMA auto_vacuum = INCREMENTAL;

Results

StrategyInsert Throughput (Kelem/s)Database Size (MB)Avg Age Query Time (ms)Random Select Time (µs)Join Paginated Time (µs)Select Orders Time (µs)Mixed CRUD Throughput (Kelem/s)Mixed CRUD Time (ms)
Integer4640.055.473.68181.6541147.714.493917.1235.8401
IntegerWithUuid4ColNoIndex3696.058.754.49461.7171157.174.385518.1635.5056
Snowflake3252.763.044.11831.6940158.824.416916.9515.8993
IntegerWithUuid4Col510.9163.794.65811.7223167.134.367815.9536.2686
SnowflakeWithUuid4Col418.1072.435.29221.7853179.814.505016.2856.1407
Uuid4500.0380.104.27622.6851217.894.593013.2727.5346
Uuid4WithoutRowid428.7775.104.36791.8997181.564.731515.1246.6119
Uuid7510.7080.154.29952.6551212.824.697312.9547.7194
Uuid7WithoutRowid429.4275.054.59791.9021178.804.570415.0726.6348
Uuid7WithUuid4Col206.5788.635.34242.7702214.424.688513.7697.2626
Uuid7WithUuid4ColWithoutRowid150.8786.565.52001.9777207.814.820414.7916.7607
Uuid7WithUuid4ToUuid7Mapping98.80891.194.37701.9445180.774.654616.0856.2169

Note: The “Mixed CRUD” benchmark results are a bit noisy. I wasn’t fully able to get consistent results, which may explain why IntegerWithUuid4ColNoIndex is faster than Integer.

Conclusion

So what should you use? It all boils down to your use case: