😺

大規模データを効率処理する方法:Pythonで使えるデータベース比較

に公開

はじめに

最初はCSVをpandasで直接扱うだけで十分ですが、データが数十万行を超えると処理が重くなり、共有も難しくなります。こうした課題を解決する方法がデータベースへの登録です。必要な部分だけ抽出でき、検索や集計も高速化されます。この記事では、Pythonから使える代表的なDBの特徴とメリット・デメリットを整理します。

DBに登録して扱うメリット

以前の記事ではテーブルデータをそのままデータフレームで扱ってきましたが、 データ量が増えると次のような課題が出てきます。

  • メモリに載りきらない大規模データは処理が重くなる
  • 毎回CSVを読み直すと処理が遅い
  • 複数人でデータを共有するのが難しい

こうした場合には、SQLiteなどのデータベースに一度登録してから 、SQLで必要な部分だけを取り出す方法が有効です。DBを使うメリットは以下の通りです。

  • 大規模データに対応:必要な部分だけ抽出してメモリ節約 できる
  • 検索・集計が高速:インデックスやSQL文を活用できる
  • データの永続化・再利用:前処理済みデータを保存して再利用できる
  • 共有・拡張性:PostgreSQLやMySQLにすれば複数人で利用できる

分析フェーズではpandasの方が手軽ですが、「中長期的にデータを蓄積して分析する」場面ではDBの利用を検討する価値があります。

Pythonから構築・利用できるDB

SQLite

  • 特徴
    • Python標準ライブラリ(sqlite3)で扱える
    • 1つのファイルにすべてのデータを格納する
  • メリット
    • インストール不要(Pythonに同梱)
    • 高速・単一ファイル形式なので軽量
    • 小規模~中規模データの保存・分析に最適
  • デメリット
    • 同時アクセス(並行処理)に弱い
    • 大規模トランザクション処理には不向き
コーディング例
# 標準ライブラリのためpip不要
import sqlite3

db_path = "example.sqlite"
conn = sqlite3.connect(db_path)
cur = conn.cursor()

# スキーマ作成
cur.execute("""
CREATE TABLE IF NOT EXISTS items (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  price REAL NOT NULL
)
""")

# CREATE
cur.execute("INSERT INTO items (name, price) VALUES (?, ?)", ("apple", 120.5))
conn.commit()

# READ
cur.execute("SELECT id, name, price FROM items WHERE name = ?", ("apple",))
print(cur.fetchall())

# UPDATE
cur.execute("UPDATE items SET price = ? WHERE name = ?", (150.0, "apple"))
conn.commit()

# DELETE
cur.execute("DELETE FROM items WHERE name = ?", ("apple",))
conn.commit()

cur.close()
conn.close()

MySQL

  • 特徴
    • mysqlclientやsqlalchemyで利用可能
    • 世界的に広く使われているRDB
  • メリット
    • レプリケーションや分散処理に対応している
    • Webサービスでの利用実績が豊富
  • デメリット
    • PostgreSQLより機能面で制約がある部分もある
    • 設定や運用にDB知識が必要
コーディング例
# pip install pymysql
import pymysql

conn = pymysql.connect(
    host="localhost", port=3306,
    user="root", password="password",
    database="testdb", autocommit=True
)
cur = conn.cursor()

# スキーマ作成
cur.execute("""
CREATE TABLE IF NOT EXISTS items (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  price DOUBLE NOT NULL
)
""")

# CREATE
cur.execute("INSERT INTO items (name, price) VALUES (%s, %s)", ("apple", 120.5))

# READ
cur.execute("SELECT id, name, price FROM items WHERE name = %s", ("apple",))
print(cur.fetchall())

# UPDATE
cur.execute("UPDATE items SET price = %s WHERE name = %s", (150.0, "apple"))

# DELETE
cur.execute("DELETE FROM items WHERE name = %s", ("apple",))

cur.close()
conn.close()

PostgreSQL

  • 特徴
    • psycopg2やsqlalchemyで利用可能
    • オープンソースの高機能RDB
  • メリット
    • トランザクション・インデックス・集計機能が強力
    • JSONや全文検索など拡張性が高い
    • 大規模・複雑なシステムでも安定稼働
  • デメリット
    • インストールや設定が必要
    • SQLiteより学習コストが高め
コーディング例
# pip install psycopg2-binary
import psycopg2

conn = psycopg2.connect(
    host="localhost", port=5432,
    user="postgres", password="password",
    dbname="testdb"
)
cur = conn.cursor()

# スキーマ作成
cur.execute("""
CREATE TABLE IF NOT EXISTS items (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  price DOUBLE PRECISION NOT NULL
)
""")
conn.commit()

# CREATE
cur.execute("INSERT INTO items (name, price) VALUES (%s, %s)", ("apple", 120.5))
conn.commit()

# READ
cur.execute("SELECT id, name, price FROM items WHERE name = %s", ("apple",))
print(cur.fetchall())

# UPDATE
cur.execute("UPDATE items SET price = %s WHERE name = %s", (150.0, "apple"))
conn.commit()

# DELETE
cur.execute("DELETE FROM items WHERE name = %s", ("apple",))
conn.commit()

cur.close()
conn.close()

DuckDB

  • 特徴
    • Pythonからduckdbライブラリで利用
    • 「SQLiteの分析特化版」とも呼ばれる組み込みDB
  • メリット
    • SQLでデータフレームやParquetやCSVを直接クエリ可能
    • 列指向DBなので分析処理が非常に高速
    • SQLite同様にデータをファイルベースで軽量に扱える
  • デメリット
    • まだ新しく利用実績は比較的少ない
    • 同時アクセスやトランザクション処理は弱め
コーディング例
# pip install duckdb
import duckdb

# ファイル永続化する場合は 'example.duckdb' を指定、:memory: ならメモリDB
conn = duckdb.connect("example.duckdb")

# スキーマ作成
conn.execute("""
CREATE TABLE IF NOT EXISTS items (
  id INTEGER,
  name TEXT,
  price DOUBLE
)
""")

# CREATE
conn.execute("INSERT INTO items (id, name, price) VALUES (?, ?, ?)", (1, "apple", 120.5))

# READ
print(conn.execute("SELECT id, name, price FROM items WHERE name = ?", ("apple",)).fetchall())

# UPDATE
conn.execute("UPDATE items SET price = ? WHERE name = ?", (150.0, "apple"))

# DELETE
conn.execute("DELETE FROM items WHERE name = ?", ("apple",))

conn.close()

MongoDB

  • 特徴
    • Pythonからはpymongoで利用
    • ドキュメント指向のNoSQL DBで、JSONに近い形式でデータを保存
  • メリット
    • JSONライクな柔軟なデータ構造
    • データ項目を事前に固定しなくても良い(データ構造が頻繁に変わる場合に特に便利)
    • 項目数の増加に強い
  • デメリット
    • 複雑なJOINはできない
    • データ整合性(ACID)はRDBより弱い
コーディング例
# pip install pymongo
from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")
db = client["testdb"]
col = db["items"]

# CREATE(_id は自動付与。RDBのid相当を自分で入れてもOK)
col.insert_one({"name": "apple", "price": 120.5})

# READ
doc = col.find_one({"name": "apple"})
print(doc)

# UPDATE(最初に一致した1件を更新)
col.update_one({"name": "apple"}, {"$set": {"price": 150.0}})

# DELETE(該当1件削除)
col.delete_one({"name": "apple"})

client.close()

Redis

  • 特徴
    • Pythonからはredis-pyで利用
    • インメモリ型のKey-Valueストア
  • メリット
    • メモリ上で処理するため非常に高速(キャッシュ用途に最適)
    • pub/sub(通知)、セッション管理などに強い
  • デメリット
    • 永続化は補助的(ディスク保存も可能だがメインはメモリ)
    • 大量データを長期保存する用途には不向き
コーディング例
# pip install redis
import redis
import json

r = redis.Redis(host="localhost", port=6379, db=0)

# キーを "item:{id}" として表現、値はHashまたはJSON文字列を利用
key = "item:1"

# CREATE(Hash)
r.hset(key, mapping={"name": "apple", "price": "120.5"})

# READ
print(r.hgetall(key))  # b'name': b'apple', b'price': b'120.5'

# UPDATE(Hashのフィールド更新)
r.hset(key, "price", "150.0")

# DELETE(キーごと削除)
r.delete(key)

# JSONで保持したい場合(RedisJSONがない前提で文字列化)
key_json = "itemjson:1"
r.set(key_json, json.dumps({"name": "apple", "price": 120.5}))  # CREATE
print(json.loads(r.get(key_json)))  # READ
r.set(key_json, json.dumps({"name": "apple", "price": 150.0}))  # UPDATE(丸ごと上書き)
r.delete(key_json)  # DELETE

おわりに

大規模データを効率的に扱うには、DBの活用が有効です。

  • 個人利用や小規模データ:SQLite・DuckDB
  • チームや大規模データを扱う業務システム:PostgreSQL・MySQL
  • 柔軟なデータ構造やキャッシュ用途:MongoDB・Redis

pandasの手軽さを活かしつつ、データ規模や用途に応じてDBを選ぶのがおすすめです。

GitHubで編集を提案

Discussion