한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

ゲームラグ白書 › L12 データベース

ログイン殺到とN+1クエリ Login storm, N+1 queries

原因ID db-login-storm · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

図と実験のあるメインページでこのカードを開く →

キャラクター1体を読み込むたびに数十回の個別クエリを発行していると、数万人の同時ログインは数百万件のクエリになります。

なぜ キャラクターのロード時にアイテム・スキル・クエストを個別にクエリ → すると メンテ明けの同時ログインでクエリが急増 → 画面では ログインの無限ロード、プレイ中のユーザーの保存まで滞る

症状
接続不可・無限ロード, 入力遅延
要因
ストール, 遅延
誰に起きるか
サーバー全体
いつ
接続直後・メンテ明け
担当
主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ
ゲーム開発チームの対応
まとめて1回で取得、ログイン待機列、キャッシュ、ORMの遅延ロードが生むクエリ数の点検。
インフラチームの対応
呼び出し回数の多いクエリのランキングを出して共有、メンテ明けのログイン時間帯のクエリ数・コネクション数を監視。
グラフでは
接続直後・メンテ明けに急増 · DBの秒間クエリ数、ログイン数
確認箇所
メンテ明けのログイン数とDBの秒間クエリ数(MySQLはQuestionsの増加量)を重ねて、ログイン1件あたりのクエリ数を計算。呼び出し回数が上位のクエリは、MySQLはevents_statements_summary_by_digestのCOUNT_STAR、PostgreSQLはpg_stat_statementsのcallsで抽出
該当する場合
ログイン1件あたりのクエリが数十件あり、上位のクエリがキャラクターID 1つで検索する同じ形の短いクエリばかり。アップデート後にログインあたりのクエリ数が増えたなら、そのアップデートが発端
該当しない場合
ログインあたりのクエリ数は少ないのにクエリ1つ1つが遅いなら、コールドキャッシュ(db-cold-cache)かインデックス(db-no-index)
確認手段
インフラのツールで確認(ゲームコード不要)
もっと詳しく
ORM(DBへのクエリを代わりに組み立ててくれるライブラリ)の遅延ロード(lazy loading)が、開発者も気づかないうちにこうしたクエリを生みます。開発サーバーではキャラクターが数体しかないので目立たず、本番の同時ログインで初めて表面化します。

出典

  1. Efficient Querying .NET
    ORMの遅延ロードは項目ごとにクエリをもう1回ずつ送るN+1問題を生み、性能を大きく落とす、一度にまとめて読み込む方式(eager loading)を推奨
  2. pg_stat_statements — track statistics of SQL planning and execution PostgreSQL
    ステートメントごとの実行回数(calls)と合計実行時間を集計し、呼び出しの多いクエリのランキングを出す
  3. Performance Schema Statement Digests and Sampling MySQL
    events_statements_summary_by_digestで同じ形のクエリをまとめ、回数・時間を集計
  4. Statement Summary Tables MySQL
    サマリーテーブルのCOUNT_STAR(実行回数)・SUM_TIMER_WAIT(合計時間)
  5. Server Status Variables MySQL
    Questions:クライアントが送信したステートメントの数

あわせて読みたい原因

同じ層:L12 データベース

同じ症状(接続不可・無限ロード)を起こすほかの層の原因

図と実験のあるメインページでこのカードを見る