はじめに

開発環境ではDjangoアプリがスムーズに動作し、クエリも瞬時に返ってきます。しかし、本番環境では処理速度が著しく低下します。ページの読み込みに数秒かかり、ユーザーからの苦情が殺到し、CPU使用率が急上昇します。

犯人は?データベースインデックスの欠如 - トラフィックが増えるまで隠れたままの、目に見えないパフォーマンスキラーです。Glintecoでは、ユーザー数は増加するのにデータベース設計が追い付いていない、このようなケースを数えきれないほど見てきました。

状況:遅いクエリ

開発環境では、このような単純なクエリはミリ秒単位で実行されます。

BlogPost.objects.filter(author_id=42).order_by('-created_at')

しかし、本番環境で数百万行のデータになると、同じクエリが数秒かかるようになります。データベースはショートカットを使用する代わりに、テーブル全体をスキャンします。

この事件現場で欠けているもの?インデックスです。

問題が発生する仕組み

  1. 開発環境の小さなデータセット

    • ローカルデータベースには数百行しかありません。パフォーマンスは良好に見えます
       

  2. 本番環境での急激な増加

    • レコード数が数百万に増加すると、クエリは指数関数的に遅くなります
       

  3. インデックス戦略の欠如

    • 開発者はデフォルト設定に依存し、フィルターや結合で頻繁に使用される列の最適化を忘れています
       

  4. インデックスの過剰使用によるミス

    • 逆に、インデックスが多すぎると書き込み速度が遅くなり、ストレージが無駄になります

ボトルネックのデバッグ

欠けているインデックスを見つけるために、開発者はデータベースツールを使用します。

  • EXPLAIN / EXPLAIN ANALYZE (PostgresまたはMySQL) でクエリプランを確認します。
     

  • Django Debug Toolbar で遅いクエリを特定します。
     

  • クエリのパフォーマンスメトリクスを監視するツールとしてNew RelicやDatadogを使用します。

PostgreSQLのドキュメントでは、クエリプランの読み取りに関する詳細なガイダンスを提供しています。

解決策

一般的なフィルターにインデックスを追加する

例
 

CREATE INDEX idx_blogpost_author ON blogpost (author_id);

Djangoのdb_index=Trueを使用する

author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)

複合インデックスを活用する

複数のフィールドをフィルタリングするクエリの場合。

BlogPost.objects.filter(author_id=42, created_at__gte="2025-01-01")

インデックスがない場合、データベースはblogpostテーブル全体をスキャンします。(author_id、created_at)の複合インデックスを使用すると、データベースは適切なサブセットに直接ジャンプできます。

解決策

class BlogPost(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [
            models.Index(fields=['author', 'created_at']),
        ]

クエリを定期的に監査する

本番環境レベルのデータ量でステージング環境でクエリ分析を実行します。

インデックスの過剰使用を避ける

すべてのインデックスは読み取り速度を向上させますが、書き込み速度を低下させます。バランスを取ることが重要です。

詳細については、こちらをご覧ください:https://testdriven.io/blog/django-db-indexing/

教訓

データベースインデックスは、システムを停止させるまで、存在しない場合にしか認識されません。「欠けているインデックスのケース」は、パフォーマンスはコードだけでなく、大規模なデータ設計も重要であることを思い出させてくれます。

Glintecoでは、さまざまな業界のクライアントに対し、スケーラブルなDjangoとデータベースシステムの設計を支援しています。適切なインデックスの追加、クエリのチューニング、長期的な成長計画の策定など、アプリケーションの規模が拡大しても高速に動作するようにします。

アプリの動作が遅く、原因がわからない場合は、インデックスが欠落している可能性があります。そして、私たちはそれを発見する方法を知っています。