Contents
FastAPIとMySQL接続におけるパフォーマンス向上の重要性
FastAPIとMySQLを組み合わせたWebアプリケーションでは、データベースアクセスが全体の処理速度に直接影響するため、パフォーマンスチューニングは不可欠です。特に高負荷環境では、接続の遅延やクエリの非効率がボトルネックとなるケースが多く見られます。本記事では、Connection Pooling・クエリ最適化・非同期処理の3つのアプローチから、実務で即活用できるパフォーマンス向上策を解説します。
Connection Poolingの設定方法とベストプラクティス
データベース接続はコストが高く、頻繁な開閉が性能低下につながります。Connection Poolingにより、接続プールを事前に準備し、リソースの再利用を促進することで、処理効率を向上させます。SQLAlchemyやasyncmyなどのライブラリでの実装例も紹介します。
プールサイズの決定基準
プールサイズはアプリケーションの負荷とDBの制限によって調整する必要があります。以下に代表的な基準を示します。
| 項目 | 内容 |
|---|---|
| 最小値 | 10〜20:軽量な処理でも十分な接続数を確保するための下限 |
| 最大値 | DBサーバーの制限内:MySQLのmax_connectionsパラメータが上限となる |
| 動的調整 | アプリケーション負荷によって自動拡張可能な設定も検討(例: SQLAlchemyのpool_size) |
注意点:プールサイズが過剰に大きいと、DBサーバーのリソースを圧迫する可能性があるため、テスト環境でのシミュレーションが必要です。
接続タイムアウトの設定
接続が長時間待機しないようにタイムアウト値を明示的に設定しましょう。SQLAlchemyでは以下のように指定できます。
|
1 2 3 4 5 6 7 8 9 |
from sqlalchemy import create_engine engine = create_engine( "mysql+mysqlconnector://user:password@host/dbname", pool_size=20, max_overflow=5, pool_timeout=30 # 接続待ちの最大時間を30秒に設定 ) |
pool_timeoutが適切でない場合、クライアントが長時間待機する可能性があるため、アプリケーションのレスポンス性に悪影響を与えます。
クエリ最適化手法とSlow Query Logの活用
Slow Query Logの有効化手順
MySQLのSlow Query Logは、実行時間が閾値を超えるクエリを記録する機能で、ボトルネックの特定に有効です。設定方法は以下の通りです。
-
MySQL構成ファイル(
my.cnfまたはmy.ini)に以下を追加
ini
[mysqld]
slow_query_log = ON
long_query_time = 2 # 2秒以上のクエリを記録
log_output = FILE # ログの出力形式(FILEまたはTABLE) -
MySQLを再起動して設定を反映
重要:
long_query_timeはアプリケーションの特性に応じて調整してください。例えば、高頻度の小規模なクエリでは1秒未満が適切です。
OS/MySQLバージョン依存性について:Linux環境での設定例を示していますが、WindowsやMySQL 8.0以降ではlog_outputのオプションが異なります(例:log_output = TABLE)。
インデックス戦略とEXPLAIN Planの読み方
インデックスがない場合、フルスキャンが発生して処理時間が長引く可能性があります。EXPLAINコマンドでクエリ実行計画を確認し、インデックスの有効性を検証します。
EXPLAIN Planの読み方(初心者向け解説)
EXPLAINは、クエリの実行計画を表示するコマンドで、以下のような出力を得られます。
| 列名 | 役割 |
|---|---|
id |
クエリ内のサブクエリや联合クエリの識別子 |
select_type |
選択されたクエリタイプ(例: SIMPLE、SUBQUERY) |
table |
テーブル名 |
type |
アクセスメソッド(例: index, range, ALL) |
possible_keys |
使用可能なインデックスのリスト |
key |
実際に使用されたインデックス |
rows |
推定検索行数 |
注意:
type=ALL(フルスキャン)の場合は、インデックスの最適化が必須です。
例: インデックス不足による問題
|
1 2 3 |
-- 検索条件がインデックス対象ではない場合 SELECT * FROM users WHERE email LIKE '%test%'; |
このクエリでは、email列にインデックスを設定しても効果がないため、フルスキャンが発生し、処理時間が増加します。
修正例: インデックスの適切な設計
|
1 2 3 |
-- email列に前置き一致用インデックスを追加 CREATE INDEX idx_email_prefix ON users (email(10)); |
EXPLAINの出力例:type=rangeがtype=indexと比較して、アクセスコストが減少します。
FastAPIにおける非同期DBアクセスの実装方法
async/awaitによる非同期処理
FastAPIは非同期処理をサポートしており、I/O待ち時間を短縮するのに有効です。以下にasyncmyを使ったコードサンプルを示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from fastapi import FastAPI import asyncio import asyncmy app = FastAPI() @app.get("/data") async def get_data(): conn = await asyncmy.connect( host="localhost", port=3306, user="root", password="password", db="test" ) async with conn.cursor() as cur: await cur.execute("SELECT * FROM users WHERE id = 1") result = await cur.fetchone() return {"data": result} |
同期処理と比較して、リクエストの処理効率が向上し、スループットが増加します。
接続プールの非同期対応
非同期接続プールは、大量の同時アクセスを安定して処理できるようにする仕組みです。asyncmyでは以下のように設定できます。
|
1 2 3 4 5 6 7 8 9 10 |
from asyncmy import create_pool pool = await create_pool( host="localhost", port=3306, user="root", password="password", db="test" ) |
比較例: 同期処理と非同期処理の処理時間(100リクエスト)
| 方法 | 平均処理時間(ms) | スループット(req/s) |
|---|---|---|
| 同期処理 | 2,500 | 40 |
| 非同期処理 | 800 | 125 |
Docker環境におけるリソース制限対策
メモリとCPUの制限設定
Dockerコンテナでは、メモリやCPU使用量を上限に設定しないと、ホストマシンのリソースが枯渇し、パフォーマンス低下につながります。docker-compose.ymlで以下のように設定します。
|
1 2 3 4 5 6 7 8 9 |
services: fastapi-app: image: my-fastapi-image deploy: resources: limits: memory: 512M cpus: "1" |
注意点: リソース制限が厳しすぎると、アプリケーションの処理性能が低下するため、適切な閾値を設定することが重要です。
コンテナ間通信の最適化
Dockerネットワークでは、ホスト名でアクセスする場合、DNSリゾルバに時間がかかるケースがあります。以下のように--network hostを使用することで、ホストネットワークを利用し、通信遅延を軽減できます。
|
1 2 |
docker run --network host my-fastapi-image |
代替案: 事前にコンテナのホスト名とIPアドレスを紐付けたDNSサーバーを構築する方法もありますが、簡単な環境では
--network hostが最も効果的です。運用環境での注意点:
--network hostはLinuxのみで動作し、コンテナ内でのポート競合やセキュリティリスクがあります(例: ホストのポートを直接公開)。本番環境では避けるべきです。
実践的なパフォーマンステストの実施方法
ロードテストツールの選定
自社環境でのパフォーマンス確認には、以下のようなツールを使用します。
- Locust: Python製で、簡単にシナリオを記述できる
- JMeter: Java製で、複雑な負荷パターンに対応する
FastAPIアプリケーションではlocustが特に使いやすいです。以下にインストールと実行例を示します。
|
1 2 3 |
pip install locust locust -f locustfile.py |
計測指標の設計
パフォーマンステストにおいて、以下の計測項目を明確に定義することが重要です。
| 項目 | 計測方法 |
|---|---|
| 応答時間 | 平均応答時間をlocustのグラフで確認 |
| エラーレート | 500エラーなどの発生率をモニタリング |
| スループット | 秒単位あたり処理可能なリクエスト数 |
CTA: 本記事で紹介したコードサンプルをもとに、自社環境でのパフォーマンステストを実施してみてください。
まとめ
- Connection Poolingにより接続待機時間を短縮する
- Slow Query Logとインデックスの最適化でクエリ処理効率向上
- 非同期処理でI/O待ち時間を軽減し、スループットを改善
- Docker環境ではリソース制限と通信設定を調整
- パフォーマンステストは実環境での数値確認が不可欠
これらの対策を組み合わせることで、FastAPIとMySQLの接続パフォーマンスを安定して向上させることができます。