0
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?

Pandas SQLiteでの大量データ読み込み速度比較

Posted at

PandasやSQLiteで大量のデータを読み込む際の速度比較と実行によるメモリ使用率を調べてみました。検証パターンは、下記の3パターンです。

1.sqlite3のfetchallでDBの読み込み
2.SQLiteのテーブルをpandasのread_sql_queryでDBの読み込み
3.pandasのread_csvでCSVファイルの読み込み

目次

環境

Python 3.11.9
pandas 2.2.3
sqlite3 3.45.1
memory-profiler 0.61.0
Faker 33.1.0

検証用データ作成

カラム数 10 × 行数(10万・100万・500万)をSQLiteとCSVファイルで作成し検証しました。

データ作成.py
import sqlite3
import csv
import random
import time
from datetime import datetime, timedelta
from faker import Faker

# 日本語のFakerインスタンスを作成
fake = Faker("ja_JP")

conn = sqlite3.connect("test.db")
cur = conn.cursor()

# 既存のテーブルを削除(存在する場合)
cur.execute("DROP TABLE IF EXISTS sample_data")

# 新しいテーブルを作成
cur.execute(
    """
CREATE TABLE sample_data (
    col1 INTEGER PRIMARY KEY,
    col2 TEXT,
    col3 INTEGER,
    col4 REAL,
    col5 TEXT,
    col6 TEXT,
    col7 INTEGER,
    col8 TEXT,
    col9 REAL,
    col10 TEXT
)
"""
)

with open("sample_data.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)
    writer.writerow([f"col{i}" for i in range(1, 11)])  # CSVに列名を生成

    end_date = datetime.now()
    start_date = end_date - timedelta(days=365)

    for i in range(1, 5000001):
        row_data = [
            i,  # ID
            fake.name(),  # 名前
            random.randint(1000, 1000000),  # 数値1
            random.uniform(0.1, 100.0),  # 浮動小数点
            fake.date_between(start_date=start_date, end_date=end_date).strftime("%Y-%m-%d"),  # 日付
            random.choice(["A", "B", "C", "D", "E"]),  # カテゴリ
            random.randint(1, 100),  # 数値2
            fake.email(),  # メールアドレス
            random.random(),  # 0-1の乱数
            random.choice(["active", "inactive", "pending"]),  # ステータス
        ]

        writer.writerow(row_data) # CSVにデータ書き込み

        # SQLiteへの挿入処理
        sql = "INSERT INTO sample_data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
        cur.execute(sql, row_data)

検証用のデータ作成にはFakerライブラリを使用しました。

各パターン 検証コード

■ sqlite3 fetchall

sample.py
import sqlite3
import time
from memory_profiler import profile


@profile
def fetch_data():
    start = time.time()
    with sqlite3.connect("test.db") as conn:
        cur = conn.cursor()
        sql = "SELECT * FROM sample_data"
        
        cur.execute(sql)
        cur.fetchall()

    end_time = time.time()
    elapsed_time = end_time - start
    print(f"実行時間: {elapsed_time/60:.2f}分 ({elapsed_time:.2f}秒)")

■ pandas read_sql_query

sample.py
import pandas
import sqlite3
import time
from memory_profiler import profile


@profile
def pandas_sqlite_db_read():
    with sqlite3.connect("test.db") as conn:
        start = time.time()
        sql = "select * from sample_data"
        
        df = pandas.read_sql_query(sql, conn)

        end_time = time.time()
        elapsed_time = end_time - start
        print(f"実行時間:{elapsed_time/60}分({elapsed_time:.2f}秒)")

■ pandas read_csv

sample.py
import pandas
import time
from memory_profiler import profile

READ_PATH = R"large_data.csv"


@profile
def pandas_csv_read():
    start = time.time()
    
    df = pandas.read_csv(READ_PATH)

    end = time.time()
    elapsed_time = end - start
    print(f"実行時間:{elapsed_time/60}分({elapsed_time:.2f}秒)")

memory_profilerを使用してプログラムのメモリ使用状況を確認することが可能です。

検証結果

10万件読み込み

■ sqlite3.fetchall

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 0.44秒 29.9 MiB 5.6 MiB
2回目 0.31秒 30.8 MiB 6.5 MiB
3回目 0.30秒 29.5 MiB 5.0 MiB

■ pandas.read_sql_query

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 0.46秒 131.9 MiB 64.4 MiB
2回目 0.47秒 131.8 MiB 64.6 MiB
3回目 0.47秒 131.9 MiB 64.5 MiB

■ pandas.read_csv

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 0.26秒 79.8 MiB 12.2 MiB
2回目 0.24秒 79.6 MiB 12.3 MiB
3回目 0.25秒 79.7 MiB 12.4 MiB

100万件読み込み

■ sqlite3.fetchall

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 3.42秒 23.8 MiB 0.4 MiB
2回目 3.32秒 24.5 MiB 0.4 MiB
3回目 3.30秒 24.3 MiB 0.4 MiB

■ pandas.read_sql_query

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 4.62秒 593.6 MiB 526.2 MiB
2回目 4.60秒 686.3 MiB 619.1 MiB
3回目 4.08秒 686.8 MiB 619.4 MiB

■ pandas.read_csv

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 2.13秒 181.5 MiB 114.2 MiB
2回目 2.01秒 179.5 MiB 112.1 MiB
3回目 1.88秒 180.3 MiB 113.0 MiB

500万件読み込み

■ sqlite3.fetchall

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 17.11秒 24.4 MiB 0.4 MiB
2回目 17.59秒 24.3 MiB 0.4 MiB
3回目 17.27秒 24.4 MiB 0.4 MiB

■ pandas.read_sql_query

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 51.16秒 2915.4 MiB 2847.9 MiB
2回目 39.05秒 3085.6 MiB 3018.3 MiB
3回目 40.58秒 2894.4 MiB 2827.0 MiB

■ pandas.read_csv

回数 実行時間 読み込み行でのメモリ使用量 読み込み行での増加量
1回目 12.57秒 338.0 MiB 270.6 MiB
2回目 10.86秒 622.5 MiB 555.3 MiB
3回目 10.30秒 623.0 MiB 555.4 MiB

まとめ

■ sqlite3.fetchall

  • 速度: 比較的速いが、大量データ(500万件)では実行時間が増加。
  • メモリ使用量: 他の方法と比較してメモリ使用量の増加が非常に少なく、効率的。

■ pandas.read_sql_query

  • 速度: 全てのパターンで遅い。特に大量データの場合、実行時間が顕著に増加。
  • メモリ使用量: データ量に対して大幅に増加。大量データではメモリ不足になる可能性がある。

■ pandas.read_csv

  • 速度: 最速(10万件~500万件で安定)。
  • メモリ使用量: pandas.read_sql_queryよりも効率的だが、sqlite3.fetchallよりは高い。
0
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
0
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?