Skip to main content
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ゲームエンジニアのための
データベース設計
株式会社 DeNA Games Osaka
技術編成部
人西 聖樹 masaki.hitonishi@dena.com
Copyright © DeNA Co.,Ltd. All Rights Reserved.
自己紹介
 人西聖樹 (ひとにし まさき)
 株式会社 DeNA Games Osaka 2014年 入社
 Webアプリケーションエンジニア
 シューティングゲーム好き。東方Project 大好き
 某400万人ユーザー超えモバイルゲームの
開発やってます
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ゲームの
サーバーサイド
Copyright © DeNA Co.,Ltd. All Rights Reserved.
データを
どうやって
保存しようか?
Copyright © DeNA Co.,Ltd. All Rights Reserved.
多様な選択肢
 RDBMS
MySQL
Oracle
PostgreSQL
 KVS
Redis
Riak
 カラム指向型
Apache Cassandra
Hbase
 ドキュメント指向
MongoDB
Apache CouchDB
etc…
Copyright © DeNA Co.,Ltd. All Rights Reserved.
今日は MySQL の
話をします!
Copyright © DeNA Co.,Ltd. All Rights Reserved.
突然ですがアンケー
ト
Copyright © DeNA Co.,Ltd. All Rights Reserved.
MySQL使った事ある人!
Copyright © DeNA Co.,Ltd. All Rights Reserved.
explain コマンド
使ったことある人!
Copyright © DeNA Co.,Ltd. All Rights Reserved.
InnoDB における
ギャップロック と
ネクストキーロック
について説明できる人!
Copyright © DeNA Co.,Ltd. All Rights Reserved.
本日のテーマ
 RDBMS (リレーショナルデータベース) とは
 データベース観点でのゲームのデータの特徴
 データベース構築時に気をつけること
 アプリケーション開発時に気をつけること
Copyright © DeNA Co.,Ltd. All Rights Reserved.
リレーショナルデータベースとは
 データを行と列の組み合わせによる表で表す
 複数の表と表を関係(リレーション)によって組み合わせられる
ID 名前 攻撃力 防御力
1 Aさん 100 100
2 Bさん 200 150
ユーザーID アイテムID 所持数
1 1 1
1 2 3
1 3 5
ユーザーテーブル
アイテム所持テーブル
ユーザーテーブルの情報から
Aさんがどのアイテムを何個所持している
か取得することができる。
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ACID特性
 Atomicity 原子性
トランザクションの操作は全て実行されるか
まったく実行されないかのどちらか
 Consistency 一貫性
トランザクション開始時と終了時にデータの
整合性が保たれる
 Isolation 独立性
他のトランザクションによる操作の影響を受けない
 Durability 永続性
コミットしたトランザクションのデータは保存される
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ゲームデータの特徴
 ユーザーを primary key としたレコードが多い
 永続データと期間限定データ(イベントのデータ等)がある
 マスタデータ(read only)が多い
アイテムマスタ、ボスマスタ、ボス出現マスタ etc…
 レコードの状態更新が多い
ボスのHP減少、HP回復、マップ移動 etc…
 可用性・整合性は大切
ゲームがプレイできない、アイテムを使用したのに
回復していない等の不具合・障害に対して、
課金しているユーザーの温度感は非常に高い
Copyright © DeNA Co.,Ltd. All Rights Reserved.
データベース構築時に考えること
 Master/Slave 構成
 垂直分割
 水平分割
垂直/水平分割はアプリケーション側で対応しないといけない
(MySQL 側に仕組みがない)が後から追加するのは
大変なので最初から考慮して開発する
Copyright © DeNA Co.,Ltd. All Rights Reserved.
Master / Slave 構成
Master
Slave Slave Slave
レプリケーション
Copyright © DeNA Co.,Ltd. All Rights Reserved.
ゲームは更新系クエリがめちゃ多い
 ボタンを押すだけでステータス更新
 体力増減とか
 ボスへダメージとか
 アイテム獲得とか
Copyright © DeNA Co.,Ltd. All Rights Reserved.
 参照系クエリは Slave に逃せる。
 Slave のスケールアウトは容易
 更新系クエリは必ず Master にI/O負荷がか
かる → Master はボトルネックになりがち
Copyright © DeNA Co.,Ltd. All Rights Reserved.
垂直分割
Aテーブル
Bテーブル
Cテーブル
Dテーブル
Eテーブル
Fテーブル
Gテーブル
Hテーブル
Iテーブル
 テーブルの種類によって DB を分割。
 Join 句が使えなくなる。
 テーブルへのアクセス数が均等になるように分割しないと負荷が偏る
Copyright © DeNA Co.,Ltd. All Rights Reserved.
水平分割
 レコードのカラムの値でDBを分割
 範囲取得や count, sum が面倒に
 auto_increment が使えなくなる→採番テーブルを別途用意する
Aテーブル
Bテーブル
Cテーブル
Aテーブル
Bテーブル
Cテーブル
Aテーブル
Bテーブル
Cテーブル
↑ID: 1 のレコードはこっち
↑ID: 2 のレコードはこっち
↑ID: 3 のレコードはこっち
Copyright © DeNA Co.,Ltd. All Rights Reserved.
複数のトランザクションを扱う
 複数DB へのトランザクションをどう扱うか?
 InnoDB の REPEATABLE READ は最初のクエリ発行時に取得できるレ
コードの値が決定するので、各DBに対して最初のクエリをいつ投げる
か意識する必要がある。
 コミットタイミングは全て同一で行うのが楽
 コミットタイミングが別々だとデータ不整合が起こりやすくなる(片方
はコミット済みなのにもう片方はロールバックとか…
Copyright © DeNA Co.,Ltd. All Rights Reserved.
アプリケーション開発時に気をつけること
 適切なindexとindexを使える適切なクエリ
 クエリ発行量を減らす
 行ロック
 レプリ遅延対策
 Repeatable read の特性
Copyright © DeNA Co.,Ltd. All Rights Reserved.
インデックス
InnoDB のインデックスは B+ Tree
常に一定の深度になるようにバランス化された木構造
1レコードの取得に対して O(log N) で探索することができる
Copyright © DeNA Co.,Ltd. All Rights Reserved.
オプティマイザ
オプティマイザとは・・・
SQLがどのインデックスを使用し、どの順序でアクセスするかという
実行計画(EXPLAIN)を決定する
EXPLAIN構文・・・
「EXPLAIN SELECT~」とすることで、オプティマイザが
選択した実行計画を表示できる
UPDATEやDELETEの場合、SELECTに書き換える必要がある
mysql> explain select * from test where id = 1;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
| 1 | SIMPLE | test | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
Copyright © DeNA Co.,Ltd. All Rights Reserved.
オプティマイザ
MySQLはコストベース・オプティマイザ
コストベースのオプティマイザでは、統計情報だけなく
CPUクロック
メモリ容量
DISK I/O速度
DBMSでのパラメータ
で実行計画が決定される
開発環境と同じ実行計画になるとは限らない
データ件数が違う
データの種類が違う
CPUクロックが違う
メモリ容量が違う
など
MySQL のオプティマイザは実行計画を結構見誤る
不安ならばFORCE INDEX で使用するインデックスを指定する
Copyright © DeNA Co.,Ltd. All Rights Reserved.
インデックスを使えないケース例
ALTER TABLE テーブル名 ADD KEY (col1, col2, col3);
・否定
WHERE col1 <> 1
・2つ目のキーから指定
WHERE col2 = 1 AND col3 = 1
・カラム側に計算式を使用
WHERE col1 * 100 = 100
・範囲指定
WHERE col1 > 1 AND col2 = 2 (col2はインデックスを使えない)
・昇順と降順の混在
ORDER BY col1 ASC, col2 DESC(col2はインデックスを使えない)
Copyright © DeNA Co.,Ltd. All Rights Reserved.
クエリ発行量を減らす
 綺麗に正規化しない(あえて冗長にデータを持つことで 1 query で必要
なデータを取得する)
 あえてカラムを分割する
更新が低いが参照の多いテーブルはmemcached にキャッシュする
更新が多いテーブルはなるべくカラムを絞って InnoDB の buffer
pool に乗るようにする
 時限付きデータ(イベントデータ等)は別テーブルにすることでイベント
終了後に drop table できるようにする
 IN句でSELECT
SELECT * FROM user WHERE id IN(1, 2, 3, ...);
 Bulk insert
INSERT INTO user values (1,'tanaka'),(2,'yamada'),(3,'hansen');
 INSERT INTO … ON DUPLICATE KEY UPDATE …
レコードが存在しなければ INSERT 、存在すれば UPDATE を 1
query で実行できる。
Copyright © DeNA Co.,Ltd. All Rights Reserved.
行ロック
 同時操作を常に意識する
AさんとBさんが同時にボスを攻撃したら両方ともボスを撃破した扱い
になったり…
Aさんが2端末使って、同時にアイテムを受け取りを押すことでアイテ
ム増殖できたり…
 前者は攻撃時にまずボスレコードをロックして、AさんとBさんの処理
を直列させることで防げる
 後者はアイテム受け取り時にAさんのレコードをロックして処理を直列
させることで防げる
 ロックの順番を統一しないと、デッドロックが発生する。
 必ず存在するレコードに対してロックを取る
 存在しないレコードをロックすると、InnoDBの Repeatable Read で
は gap lock が発生し、広範囲にロックを獲得する。
→ lock wait timeout
Copyright © DeNA Co.,Ltd. All Rights Reserved.
レプリケーション遅延対策
 大量クエリのコミット等でレプリ遅延(master DBへの変更が slave
DBへ反映が遅れること)が発生する
 回復アイテムの使用(Masterを更新)→次ページで使用結果を見ると回復
していない(Slave にまだ回復の反映が遅れてる)
→更新処理後、更新したデータをcacheに詰めて、遷移先で使用する
→更新処理後、更新処理から遷移されてきたかどうかを見て、master
or slave のどちらを参照するか決める
 1リクエスト内で Slave のデータを元に Master を更新すると、レプリ
遅延で古い Slave のデータを参照していてデータの不整合が起こる
→更新系のリクエスト内で参照するDB は Master で統一する
Copyright © DeNA Co.,Ltd. All Rights Reserved.
KVSとの併用について
 ゲームデータのキャッシュは難しい
 更新を頻繁に行うのでキャッシュクリア処理が面倒
 忘れると気づきづらい障害に
 トランザクションとの整合性
 Read Only のデータ(マスタ等)をキャッシュするのが一番楽
Copyright © DeNA Co.,Ltd. All Rights Reserved.
 ゲームサーバーのデータベースは整合性/負荷と
の戦い
 ノウハウを知って急激なアクセス増加にも耐えら
れる構築/開発をしよう
Copyright © DeNA Co.,Ltd. All Rights Reserved.
おわり