Let's say the column a of a SQLite DB is very repetitive with always the same 4 values. Other values might appear later, but there will be less than 1000 different values.
VALUES = ["hello world", "it's a shame to store this str many times", "bye bye", "abc"]
import sqlite3, random
db = sqlite3.connect('repetitive1.db')
db.execute("CREATE TABLE IF NOT EXISTS data(id INTEGER PRIMARY KEY, a TEXT);")
for i in range(1000 * 1000):
db.execute("INSERT INTO data (a) VALUES (?)", (random.choice(VALUES),))
db.commit()
Here the DB is 24 MB large for one million items, i.e. 24 bytes on average.
It's a bit a shame to re-store all the strings many times, since it's always the same values again and again. Of course a solution would be to use an ID = 0, 1, 2, 3 (up to 1000 later) for the repetitive values, and only store the integer IDs:
db = sqlite3.connect('repetitive2.db')
db.execute("CREATE TABLE IF NOT EXISTS data(id INTEGER PRIMARY KEY, a INT);")
for i in range(1000*1000):
db.execute("INSERT INTO data (a) VALUES (?)", (random.randint(0, 3),))
db.commit()
Gain: the DB is only 9 MB, i.e. 9 bytes per row on average, which is much better.
But the drawback is that we have to do this manually:
- maintain another table with a correspondence between IDs and strings,
- detect when a new value (never seen before) appears, give it a new ID, etc.
- if rows are removed and finally a string no longer appears anywhere, we might want to do some cleanup and remove its ID from this second table
- etc.
This is possible and not very difficult, but I've noticed along the years that SQLite often has clever optimizations / good tricks for similar things.
Question: is there a way to let SQLite do everything automatically? i.e. set a mode in which, internally, SQLite will do its best to deduplicate data in a column, for example by using IDs for this column instead of storing the same string again and again? (without having to maintain anything ourselves?)