Submit Search
ゲームエンジニアのためのデータベース設計
•
Download as PPTX, PDF
•
163 likes
•
34,521 views
S
sairoutine
Follow
GameServerDevelopers Vol.1 https://gsdevelopers.doorkeeper.jp/events/42497
Read less
Read more
1 of 32
Download now
Downloaded 76 times
More Related Content
ゲームエンジニアのためのデータベース設計
1.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. ゲームエンジニアのための データベース設計 株式会社 DeNA Games Osaka 技術編成部 人西 聖樹
[email protected]
2.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 自己紹介 人西聖樹 (ひとにし まさき) 株式会社 DeNA Games Osaka 2014年 入社 Webアプリケーションエンジニア シューティングゲーム好き。東方Project 大好き 某400万人ユーザー超えモバイルゲームの 開発やってます
3.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. ゲームの サーバーサイド
4.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. データを どうやって 保存しようか?
5.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 多様な選択肢 RDBMS MySQL Oracle PostgreSQL KVS Redis Riak カラム指向型 Apache Cassandra Hbase ドキュメント指向 MongoDB Apache CouchDB etc…
6.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 今日は MySQL の 話をします!
7.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 突然ですがアンケー ト
8.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. MySQL使った事ある人!
9.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. explain コマンド 使ったことある人!
10.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. InnoDB における ギャップロック と ネクストキーロック について説明できる人!
11.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 本日のテーマ RDBMS (リレーショナルデータベース) とは データベース観点でのゲームのデータの特徴 データベース構築時に気をつけること アプリケーション開発時に気をつけること
12.
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さんがどのアイテムを何個所持している か取得することができる。
13.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. ACID特性 Atomicity 原子性 トランザクションの操作は全て実行されるか まったく実行されないかのどちらか Consistency 一貫性 トランザクション開始時と終了時にデータの 整合性が保たれる Isolation 独立性 他のトランザクションによる操作の影響を受けない Durability 永続性 コミットしたトランザクションのデータは保存される
14.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. ゲームデータの特徴 ユーザーを primary key としたレコードが多い 永続データと期間限定データ(イベントのデータ等)がある マスタデータ(read only)が多い アイテムマスタ、ボスマスタ、ボス出現マスタ etc… レコードの状態更新が多い ボスのHP減少、HP回復、マップ移動 etc… 可用性・整合性は大切 ゲームがプレイできない、アイテムを使用したのに 回復していない等の不具合・障害に対して、 課金しているユーザーの温度感は非常に高い
15.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. データベース構築時に考えること Master/Slave 構成 垂直分割 水平分割 垂直/水平分割はアプリケーション側で対応しないといけない (MySQL 側に仕組みがない)が後から追加するのは 大変なので最初から考慮して開発する
16.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. Master / Slave 構成 Master Slave Slave Slave レプリケーション
17.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. ゲームは更新系クエリがめちゃ多い ボタンを押すだけでステータス更新 体力増減とか ボスへダメージとか アイテム獲得とか
18.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 参照系クエリは Slave に逃せる。 Slave のスケールアウトは容易 更新系クエリは必ず Master にI/O負荷がか かる → Master はボトルネックになりがち
19.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 垂直分割 Aテーブル Bテーブル Cテーブル Dテーブル Eテーブル Fテーブル Gテーブル Hテーブル Iテーブル テーブルの種類によって DB を分割。 Join 句が使えなくなる。 テーブルへのアクセス数が均等になるように分割しないと負荷が偏る
20.
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 のレコードはこっち
21.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 複数のトランザクションを扱う 複数DB へのトランザクションをどう扱うか? InnoDB の REPEATABLE READ は最初のクエリ発行時に取得できるレ コードの値が決定するので、各DBに対して最初のクエリをいつ投げる か意識する必要がある。 コミットタイミングは全て同一で行うのが楽 コミットタイミングが別々だとデータ不整合が起こりやすくなる(片方 はコミット済みなのにもう片方はロールバックとか…
22.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. アプリケーション開発時に気をつけること 適切なindexとindexを使える適切なクエリ クエリ発行量を減らす 行ロック レプリ遅延対策 Repeatable read の特性
23.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. インデックス InnoDB のインデックスは B+ Tree 常に一定の深度になるようにバランス化された木構造 1レコードの取得に対して O(log N) で探索することができる
24.
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 | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
25.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. オプティマイザ MySQLはコストベース・オプティマイザ コストベースのオプティマイザでは、統計情報だけなく CPUクロック メモリ容量 DISK I/O速度 DBMSでのパラメータ で実行計画が決定される 開発環境と同じ実行計画になるとは限らない データ件数が違う データの種類が違う CPUクロックが違う メモリ容量が違う など MySQL のオプティマイザは実行計画を結構見誤る 不安ならばFORCE INDEX で使用するインデックスを指定する
26.
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はインデックスを使えない)
27.
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 で実行できる。
28.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. 行ロック 同時操作を常に意識する AさんとBさんが同時にボスを攻撃したら両方ともボスを撃破した扱い になったり… Aさんが2端末使って、同時にアイテムを受け取りを押すことでアイテ ム増殖できたり… 前者は攻撃時にまずボスレコードをロックして、AさんとBさんの処理 を直列させることで防げる 後者はアイテム受け取り時にAさんのレコードをロックして処理を直列 させることで防げる ロックの順番を統一しないと、デッドロックが発生する。 必ず存在するレコードに対してロックを取る 存在しないレコードをロックすると、InnoDBの Repeatable Read で は gap lock が発生し、広範囲にロックを獲得する。 → lock wait timeout
29.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. レプリケーション遅延対策 大量クエリのコミット等でレプリ遅延(master DBへの変更が slave DBへ反映が遅れること)が発生する 回復アイテムの使用(Masterを更新)→次ページで使用結果を見ると回復 していない(Slave にまだ回復の反映が遅れてる) →更新処理後、更新したデータをcacheに詰めて、遷移先で使用する →更新処理後、更新処理から遷移されてきたかどうかを見て、master or slave のどちらを参照するか決める 1リクエスト内で Slave のデータを元に Master を更新すると、レプリ 遅延で古い Slave のデータを参照していてデータの不整合が起こる →更新系のリクエスト内で参照するDB は Master で統一する
30.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. KVSとの併用について ゲームデータのキャッシュは難しい 更新を頻繁に行うのでキャッシュクリア処理が面倒 忘れると気づきづらい障害に トランザクションとの整合性 Read Only のデータ(マスタ等)をキャッシュするのが一番楽
31.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. ゲームサーバーのデータベースは整合性/負荷と の戦い ノウハウを知って急激なアクセス増加にも耐えら れる構築/開発をしよう
32.
Copyright © DeNA
Co.,Ltd. All Rights Reserved. おわり
Editor's Notes
インデックス効かない場合の解決策 見出しは文字をでっかく
Download