1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLiteで作成したテーブルを対象にしたPython圧縮モジュールの比較

Posted at

はじめに

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("データベース接続を閉じました。")

作成したテーブルはこんな感じ。できてる!!
image.png

圧縮モジュールの比較用コードの作成

今回は、以下の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が良さそうでした。
ただ、これらの結果は圧縮する対象のデータの種類やサイズにも依存しそうですね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?