0Pricing
Pandas & NumPy Academy · レッスン

SQLAlchemyによるデータベース接続

SQLiteとPostgreSQL用のSQLAlchemyエンジンを作成し、pd.read_sqlに渡してテーブルをDataFrameに読み込みます。

「SQLAlchemyによるデータベース接続」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

Pandas をデータベースに接続する理由

本番環境のデータの多くは、CSV ファイルではなく、PostgreSQL、MySQL、SQLite、SQL Server などのリレーショナルデータベースに保存されています。Pandas をデータベースに直接接続すると、CSV にいったんエクスポートせずにデータを DataFrame にクエリでき、整形した DataFrame をテーブルに戻し、Python の分析機能とデータベースのインデックスおよび結合機能を組み合わせられます。Pandas とデータベースの橋渡しをするのが、Python 標準のデータベース抽象化ライブラリであるSQLAlchemyです。

SQLAlchemy のインストール

SQLAlchemy は Python 用の SQL ツールキット兼 ORM です。Pandas との統合では、ORM ではなくCoreレイヤーだけが必要です。pip install sqlalchemy でインストールしてください。また、使用するデータベースに応じたドライバーも必要です。PostgreSQL には psycopg2、MySQL には pymysql、SQLite には Python に組み込まれている sqlite3 を使用します。SQLAlchemy は抽象化レイヤーとして機能するため、接続文字列だけを変更すれば、同じ Pandas コードを対応する任意のデータベースで使用できます。

# Install dependencies
# pip install sqlalchemy psycopg2-binary  # for PostgreSQL
# pip install sqlalchemy pymysql           # for MySQL
# sqlite3 is built into Python

import sqlalchemy as sa
import pandas as pd

print('SQLAlchemy version:', sa.__version__)

接続エンジンの作成

最初の手順は、データベースの種類、認証情報、ホスト、ポート、データベース名を含む接続 URLを使用して、SQLAlchemy エンジンを作成することです。エンジンはデータベース接続のファクトリであり、実際に必要になるまで接続を開きません。エンジンを Pandas の pd.read_sql() および df.to_sql() 関数に渡します。認証情報をハードコードせず、環境変数またはシークレットマネージャーから読み込んでください。

import sqlalchemy as sa
import os

# SQLite (file-based, no server needed)
sqlite_engine = sa.create_engine('sqlite:///mydata.db')

# PostgreSQL
# pg_url = 'postgresql://user:pass@localhost:5432/mydb'
# pg_engine = sa.create_engine(pg_url)

# From environment variable (safer)
# pg_engine = sa.create_engine(os.environ['DATABASE_URL'])

print(sqlite_engine)
print(type(sqlite_engine))

pd.read_sql_table() によるテーブルの読み込み

pd.read_sql_table('table_name', con=engine) は、データベースのテーブル全体を DataFrame に読み込みます。データベーススキーマから列のデータ型を自動的に推測するため、整数は整数のまま、タイムスタンプは datetime のまま保持されます。これは CSV の型推測より正確です。columns 引数で列を限定することもでき、schema でデフォルト以外のデータベーススキーマを指定して行を絞り込むこともできます。ただし、非常に大きなテーブルでは、すべてのデータが RAM に読み込まれるため注意してください。

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Read a full table
df = pd.read_sql_table('orders', con=engine)
print(df.shape)
print(df.dtypes)
print(df.head())

pd.read_sql_query() によるクエリの実行

pd.read_sql_query('SELECT ...', con=engine) は任意の SQL SELECT 文を実行し、結果を DataFrame として返します。最も柔軟な方法であり、Pandas に読み込む前に SQL でフィルタリング、結合、集計を行えるため、必要な行と列だけを読み込めます。クエリは通常の Python 文字列として記述してください。SQL インジェクションを防ぐため、ユーザー入力をクエリに連結せず、パラメーター化クエリを使用してください。

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

query = '''
    SELECT customer_id, SUM(amount) AS total_spent,
           COUNT(*) AS num_orders
    FROM orders
    WHERE status = 'completed'
    GROUP BY customer_id
    ORDER BY total_spent DESC
    LIMIT 100
'''

top_customers = pd.read_sql_query(query, con=engine)
print(top_customers.head())

安全なパラメーター化クエリ

ユーザーが指定した値を文字列連結して SQL クエリを構築しないでください。SQL インジェクションの脆弱性につながります。代わりに、名前付きプレースホルダーを使用し、パラメーターを辞書として渡すパラメーター化クエリを使います。エスケープ処理は SQLAlchemy が行います。プレースホルダーの構文は、SQLAlchemy の text クエリでは :name、psycopg2 形式のクエリでは %(name)s です。適切な習慣を身につけるため、内部用スクリプトでも必ずパラメーター化を使用してください。

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Safe: parameterised query
params = {'status': 'completed', 'min_amount': 500.0}
query = sa.text(
    'SELECT * FROM orders WHERE status = :status AND amount > :min_amount'
)

with engine.connect() as conn:
    df = pd.read_sql_query(query, con=conn, params=params)
print(f'Loaded {len(df)} rows')

大規模なクエリ結果をチャンクで処理する

大規模なクエリ結果を扱う場合は、pd.read_sql_query() で chunksize を使用し、すべてを一度に読み込むのではなく DataFrame のイテレーターを受け取ります。これは pd.read_csv(chunksize=...) と同じ動作ですが、データベースから行をバッチ単位で取得します。これを実行中のアキュムレーターのパターンと組み合わせると、RAM を使い果たさずに数百万行のクエリ結果を集計できます。

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('postgresql://user:pass@host/db')

total = 0.0
count = 0

for chunk in pd.read_sql_query(
    'SELECT amount FROM orders',
    con=engine,
    chunksize=50000
):
    total += chunk['amount'].sum()
    count += len(chunk)

print(f'Mean amount: {total/count:.2f}')

接続のコンテキストマネージャー

データベース接続は必ずコンテキストマネージャー(with engine.connect() as conn:)内で開き、例外が発生しても接続が適切に閉じられるようにしてください。接続を閉じ忘れると、本番環境で接続プールの枯渇につながり、新しいクエリが空きスロットを待ったまま停止することがあります。SQLAlchemy の接続プールは一定数の接続を管理し、コンテキストマネージャーを使用すると接続を自動的に再利用します。

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Using context manager — connection always closed properly
with engine.connect() as conn:
    df = pd.read_sql_query(
        'SELECT * FROM products WHERE category = "Electronics"',
        con=conn
    )
    print(f'Products loaded: {len(df)}')
# Connection is automatically returned to the pool here

データベーススキーマの確認

クエリを記述する前に、どのテーブルと列が存在するかを把握する必要があります。SQLAlchemy のInspectorを使用すると、生の SQL を記述せずにデータベーススキーマを取得できます。inspector.get_table_names() はすべてのテーブルを一覧表示し、inspector.get_columns('table') は列名と型を返します。これは、よく知らないデータベースを扱う場合に便利で、PRAGMA table_info() や \d tablename を手動で実行するよりもすっきりしています。

import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')
inspector = sa.inspect(engine)

# List all tables
tables = inspector.get_table_names()
print('Tables:', tables)

# Get columns for the 'orders' table
for col in inspector.get_columns('orders'):
    print(f'  {col["name"]}: {col["type"]}')

エンジンの終了とベストプラクティス

長時間実行するスクリプトや Web アプリケーションでは、処理が完了したら engine.dispose() を呼び出し、プール内のすべての接続を閉じてください。短時間で終了するスクリプトでは、Python のガベージコレクターが後処理を行います。データパイプラインでデータベース接続を扱う際のベストプラクティスは、スクリプトの先頭でエンジンを一度だけ作成して再利用すること、接続プールのデフォルト設定(pool_size=5)を使用すること、クエリの間にデータベースサーバーが再起動した場合に自動再接続できるよう pool_pre_ping=True を有効にすることです。

import sqlalchemy as sa

# Production-grade engine creation
engine = sa.create_engine(
    'postgresql://user:pass@host:5432/mydb',
    pool_size=5,          # max 5 persistent connections
    max_overflow=10,      # allow 10 temporary extra connections
    pool_pre_ping=True,   # verify connection before use
    connect_args={'connect_timeout': 10}
)

# ... run all your queries ...

# At the end of the application/script
engine.dispose()
print('Engine disposed')

read_sql と read_csv の速度比較

適切なインデックスが設定されたデータベース内のデータであれば、フィルタリングしたクエリを使う pd.read_sql_query は、CSV にエクスポートしてから読み込むより高速なことがよくあります。データベースサーバーがデータを送信する前にフィルターを適用するため、ネットワーク転送と解析のオーバーヘッドを削減できます。列数が非常に多いテーブルでは、必要な列だけを射影することもできます。ただし、低速なネットワーク経由でリモートデータベースから読み込む場合は、ローカルの Parquet ファイルを読み込むより遅くなる可能性があります。実際の環境では、必ず両方の方法を計測して比較してください。

import pandas as pd
import sqlalchemy as sa
import time

engine = sa.create_engine('sqlite:///data.db')

# Database read with server-side filter
start = time.time()
df_sql = pd.read_sql_query(
    'SELECT * FROM transactions WHERE amount > 100 AND year = 2024',
    con=engine
)
print(f'SQL read: {time.time()-start:.3f}s, {len(df_sql):,} rows')

理解度チェック

このレッスンで学んだデータ分析の概念について、理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、sa.create_engine() が URL 文字列から再利用可能な接続ファクトリを作成すること、pd.read_sql_query() が任意の SQL を実行して DataFrame を返すこと、そして sa.text() と params を使ったパラメーター化クエリによって SQL インジェクションの脆弱性を防げることを学びました。次は、Pandas からより複雑な SQL クエリを実行し、SQL と Python のロジックを組み合わせる方法を見ていきます。

よくある質問

「SQLAlchemyによるデータベース接続」レッスンは無料ですか?

はい。「SQLAlchemyによるデータベース接続」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「SQLAlchemyによるデータベース接続」で何を学びますか?

SQLiteとPostgreSQL用のSQLAlchemyエンジンを作成し、pd.read_sqlに渡してテーブルをDataFrameに読み込みます。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「SQLAlchemyによるデータベース接続」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. SQLAlchemyによるデータベース接続
  2. PandasからのSQLクエリ実行
  3. DataFrameのデータベーステーブルへの書き込み
  4. PandasとSQL:適切なツールの選択
← Pandas & NumPy Academyに戻る