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

遊戲 Lag 白皮書 › L12 資料庫

登入暴增與 N+1 查詢 Login storm, N+1 queries

原因 ID db-login-storm · 主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(DB 基礎設施)

在含圖解與實驗的完整版中開啟卡片 →

載入一個角色要分開查詢數十次的話,數萬人同時登入就會變成數百萬個查詢。

為什麼 載入角色時,道具、技能、任務各自分開查詢 → 於是 維護剛結束時大量同時登入,查詢暴增 → 畫面上 登入時無限讀取,連正在遊戲中的玩家存檔都被拖慢

症狀
連不上/無限讀取, 輸入延遲
因素
停滯, 延遲
誰會遇到
整個伺服器
何時
剛登入/維護剛結束
負責單位
主要負責 遊戲開發團隊(伺服器開發) · 協同 基礎設施團隊(DB 基礎設施)
遊戲開發團隊要做的事
合併成一次查詢、登入排隊、快取,並檢查 ORM 延遲載入產生的查詢數。
基礎設施團隊要做的事
列出呼叫次數最多的查詢排行並分享,監控維護剛結束的登入時段的查詢數與連線數。
圖表上
剛開服或維護結束後暴增 · DB 每秒查詢數、登入數
查看位置
把維護剛結束時的登入數與 DB 每秒查詢數(MySQL 為 Questions 的增加量)疊在一起看,計算每次登入的查詢數。呼叫次數最多的查詢,可從 MySQL events_statements_summary_by_digest 的 COUNT_STAR、PostgreSQL pg_stat_statements 的 calls 列出
符合的跡象
每次登入有數十個查詢,排行前面的都是以單一角色 ID 查詢、形式相同的短查詢。更新後每次登入的查詢數增加的話,就從那次更新查起
不符合的跡象
每次登入的查詢數不多、但每個查詢都很慢時,是冷快取(db-cold-cache)或索引(db-no-index)
確認方式
用基礎設施工具確認(不需要遊戲程式碼)
深入了解
ORM(代為產生 DB 查詢的函式庫)的延遲載入,會在開發者沒察覺的情況下產生這類查詢。開發伺服器上只有幾個角色,看不出差異,要到正式環境大量同時登入時才會浮現。

出處

  1. Efficient Querying .NET
    ORM 的延遲載入會造成每個項目多送一次查詢的 N+1 問題,使效能大幅下降;建議一次合併載入(eager loading)
  2. pg_stat_statements — track statistics of SQL planning and execution PostgreSQL
    收集每個 SQL 陳述式的執行次數(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 資料庫

同一症狀(連不上/無限讀取)在其他層的原因

查看含圖解與實驗的完整版卡片