通知
すべてクリア
04/02/2024 11:01 am
[10_サーバーのスケールアウト.pdf]RDBの負荷対策
で紹介されている
「PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発」スライドのの50ページ目には
「更新の多いデータは水平分割」とありますが、
テーブルのカラムを更新頻度で分割する垂直分割ではないのでしょうか?
なぜ水平なのか理解できませんでした。
04/02/2024 11:02 am
様々な例があるのですが、例えばデータのINSERT/UPDATE時におけるインデックスの更新負荷を下げる目的や検索時のコスト低下を目的に水平分割(シャーディング)を行うことがあります。
---
■例
特定のイベントにおけるスコアを記録するテーブルを考えたとき:
---
■例
特定のイベントにおけるスコアを記録するテーブルを考えたとき:
- イベント情報を記録する
events
テーブル(マスタ)
event_id | event_name | stat_date | end_date
- イベントごとのユーザのスコアを記録する
event_users
テーブル
event_id | user_id | score | created_at | updated_at
- イベントごとのスコア昇順index
-
index_event_id_and_score_on_event_users (event_id, score_id)
があり、仮にユーザー数300万 / イベント開催が2週間に1回x3年実施で 216,000,000 レコード(2億1600万)になります
そして score が高頻度で INSERT / UPDATE されるとすると
どんなにインデックスの更新負荷が微小とはいえ1INSERT/UPDATEごとに 2億レコード以上の情報を持つインデックスの更新負荷が無視できなくなってきます。
また、この場合はスコア昇順の検索コストとしていくら開催中の event_id で絞り込めるといっても
2億レコード以上あると検索負荷が結構なコストになってきます
(もちろんRDBの性能で捌けるキャパは色々ですが、どこかで性能限界は発生します
パズドラなんかはもう10年以上続いてますね)このようなとき、例えば
レコード数は上記の1/3である 72,000,000 (7200万) レコードに削減できるので
インデックス更新負荷の削減や検索コストの削減を期待できるというわけです。
そして score が高頻度で INSERT / UPDATE されるとすると
どんなにインデックスの更新負荷が微小とはいえ1INSERT/UPDATEごとに 2億レコード以上の情報を持つインデックスの更新負荷が無視できなくなってきます。
また、この場合はスコア昇順の検索コストとしていくら開催中の event_id で絞り込めるといっても
2億レコード以上あると検索負荷が結構なコストになってきます
(もちろんRDBの性能で捌けるキャパは色々ですが、どこかで性能限界は発生します
パズドラなんかはもう10年以上続いてますね)このようなとき、例えば
2022_event_users
, 2023_event_users
などと年ごとに分けるだけでもレコード数は上記の1/3である 72,000,000 (7200万) レコードに削減できるので
インデックス更新負荷の削減や検索コストの削減を期待できるというわけです。
- じゃあイベント期間外のデータを消してしまえばいいのではないか?
- イベント期間外のデータをユーザに提供しないのであればそれで対処可能ですが、「過去のイベント情報を見ることができる」という機能を提供することもできなくなります
- じゃあイベント期間外のデータを別テーブルに逃してしまえばいいのではないか?
- それも一つの手段であり、広義では上記の年度で分ける水平分割と同じことです
- この辺り、どういう単位で分割するのかはバックエンド側の実装や組織の判断によって異なるはずです
- 参加してないユーザの情報はINSERTしないとか、各種ユーザのINSERTはイベント開始時に一気にやってしまうとかの手法もあるのでは
- 負荷対策を目的としてどういう手段を取るのかは色々あるので、今回の例のうにデータベース側で対策するのではなくバックエンド側の実装で対処するというのも十分あり得ます。スコアのようなものを記録するのはRDBではなくNoSQLのようなものを使うという手法など色々ありますね
---
垂直分割をするのか水平分割をするのかはデータの特性によってどちらを採用するのかが変わったりするので
単純に「更新負荷を下げる目的なら垂直分割」と判断できるとは限らないということです。
私が出した例も一例であり、「そんなことしないよ」という組織やエンジニアもいるとは思いますので判断は様々ですが、私が過去携わっていた業務では上記のような水平分割は実際に実施していました。
垂直分割をするのか水平分割をするのかはデータの特性によってどちらを採用するのかが変わったりするので
単純に「更新負荷を下げる目的なら垂直分割」と判断できるとは限らないということです。
私が出した例も一例であり、「そんなことしないよ」という組織やエンジニアもいるとは思いますので判断は様々ですが、私が過去携わっていた業務では上記のような水平分割は実際に実施していました。
04/02/2024 11:02 am
水平分割は水平分割したものを跨ぐような検索に弱いですし
垂直分割はレコード数が起因となる上記例のようなものの対策には効きにくいです
水平分割も垂直分割も行わずデータベースのスペック引き上げで対処するというのも1つの判断です
RDB(リーレーショナルデータベース)じゃないものを使うという手ももちろんありますどれもメリットデメリットあるので目的に応じて適切な手段を考えられるようになるのが大事ですね
04/02/2024 11:02 am
このような事例と対策のような話はインターネットに多く公開されており
ChatGPTにも大量の解決事例がパラメータとして学習データに入っている(はず)ですから
「こういう問題が発生しそうなんだけど水平分割や垂直分割で対応できるか?」
「水平分割と垂直分割どちらかを採用して対策するならどちらが適切か」
などChatGPTにきいてみるのもいいと思います。