はじめに
Pythonの勉強として、SQLiteでテーブルを作成し、そのデータを圧縮してみます。
今回のポイントは以下の2つです。
- sqlite3 を使ってSQLiteのテーブルを作成し、データを格納する
- Pythonの圧縮モジュール(zlib, gzip, bz2, lzma)を比較し、圧縮率や速度を確認する
SQLiteのテーブル作成
さっそく圧縮する対象のテーブルを作成します。
今回はidとdataという2つのカラムを持つテーブルを作成しました。
data列にはランダムな文字列を格納します。
import sqlite3
from faker import Faker
db_name = "my_db.db"
table_name = "my_table"
rows = 100000
# Fakerインスタンスを作成
fake = Faker()
# 生成する文章の重複を防ぐ
def random_text() -> str:
# fake = Faker()
random_text = fake.text()
return random_text
# データベースへの接続
con = sqlite3.connect(f"{db_name}")
# SQLクエリの結果を取得するためにデータベース・カーソルを使用する
cur = con.cursor()
try:
# 既存のテーブルを削除
cur.execute(f"DROP TABLE IF EXISTS {table_name}")
print(f"テーブル {table_name} を削除しました。")
# テーブルの作成
cur.execute(
f"""CREATE TABLE IF NOT EXISTS {table_name}(
id INTEGER PRIMARY KEY,
data TEXT not null)
"""
)
print(f"テーブル {table_name} を作成しました。")
# データの作成
data = [(i, random_text()) for i in range(rows)]
data_insert_sql = f"INSERT INTO {table_name} (id, data) VALUES (?, ?)"
# テーブルにデータを挿入
cur.executemany(data_insert_sql, data)
# コミットして、DB接続を閉じる。
con.commit()
finally:
con.close()
print("データベース接続を閉じました。")
圧縮モジュールの比較用コードの作成
今回は、以下の4つの圧縮モジュールを使って、SQLiteのデータを圧縮します
- zlib
- gzip
- bz2
- lzma
比較の観点は2つです。
- 圧縮にかかる時間
- 圧縮前のバイト数に対する圧縮後のバイト数の比
これらの圧縮モジュールを用いて、SQLiteのデータを実際に圧縮してみます。コードは以下のように書きました。
import zlib
import gzip
import bz2
import lzma
import time
db_name = "my_db.db"
# ファイルをバイナリモードで開く
with open(db_name, "rb") as f:
data = f.read()
# 圧縮前のDBのバイト数
size_before_compression = len(data)
# 圧縮後のバイト数を計算
def get_compressed_size(compress_func, data):
compressed_data = compress_func(data)
return len(compressed_data)
# 圧縮時間と圧縮の程度を計測する関数
def measure_time(compress_func, data, name):
start = time.time()
compressed = compress_func(data)
end = time.time()
# 圧縮にかかる時間
compression_time = end - start
# 圧縮後のバイト数
size_after_compression = len(compressed)
# 圧縮前のバイト数に対する圧縮後のバイト数の計算
compression_ratio = size_after_compression / size_before_compression
print(
f"{name} 圧縮時間: {compression_time:.6f} 秒, 圧縮後のサイズ: {size_after_compression:.2f} byte, 圧縮率: {compression_ratio:.2f}"
)
# 圧縮モジュール名と圧縮関数のマッピング
compression_methods = {
"zlib": zlib.compress,
"gzip": gzip.compress,
"bz2": bz2.compress,
"lzma": lzma.compress,
}
# 圧縮前のサイズを表示
print(f"圧縮前:{size_before_compression} byte")
# 各圧縮方法で計測を実施
for method, compress_func in compression_methods.items():
measure_time(compress_func, data, method)
圧縮モジュールの比較用コードの実行結果
前節のコードを実行してみました。
圧縮前:16101376 byte
zlib 圧縮時間: 0.545227 秒, 圧縮後のサイズ: 6339633.00 byte, 圧縮率: 0.39
gzip 圧縮時間: 0.544726 秒, 圧縮後のサイズ: 6339511.00 byte, 圧縮率: 0.39
bz2 圧縮時間: 0.787286 秒, 圧縮後のサイズ: 4292200.00 byte, 圧縮率: 0.27
lzma 圧縮時間: 6.657628 秒, 圧縮後のサイズ: 5031192.00 byte, 圧縮率: 0.31
zlibとgzipは圧縮時間や圧縮率が非常に近い値ですね。
圧縮率に注目すると、bz2がいい感じっぽいですね。lzmaはすごい時間がかかっていますね。
こんなに違いが出るんですね。おどろきです。
まとめ
速度重視であればzlibやgzipを使用し、データを少しでも小さくしたい時はbz2が良さそうでした。
ただ、これらの結果は圧縮する対象のデータの種類やサイズにも依存しそうですね。