今回はデータ量が多くなりそうなテーブルの設計について
考える
負荷をへらすために考慮すべき項目をあげてみる
1.想定されるデータの量(レコードの数、サイズ)
2.テーブルに貼るインデックス
3.テーブルを分割する
4.テーブルをパーティショニングする
1.
レコードの数については設計段階で想定できるだろう
ユーザーが何ユーザーいて、一日何回ユーザーによって実行されるかと考えよう
レコードのサイズについては作ってみないとわからないことも多い
textカラムなど一度に多くのデータを保存しない場合は大きなサイズとなるだろう
レコードのサイズつまりテーブルのサイズについては作ってみないとわからないかも
2.
インデックスを適切に貼るとselectが高速になる
しかしデータの量が多いとインデックスを貼るだけでもデータサイズを食う
またデータが更新されるたびにインデックスを貼り直すため更新速度が遅くなったりする
むやみやたらにインデックスを貼りまくればいいというものでもない
3.
テーブルのサイズが多くなりそうならテーブルを分割するという方法もある
ユーザーIDの末尾で10個に分けたり月の1~12月で12個に分けたりして一月ごとに分けたりと
ただユーザー10の履歴テーブルにユーザー10がプレゼントを送ったユーザー11というユーザー情報が入っていた場合にユーザー11が誰からプレゼントをもらったかということはselectできない
こういう場合は分割ができなかったりする
4.
3とは違い物理的にテーブルを分けるのではなく、1つのテーブルを分割するというパーティショニング
こちらの記事がわかりやすいです
以下のようなデータの分け方があります
RANGE ・・・ パーティションごとに範囲を指定して振り分ける
LIST ・・・ パーティションごとに格納する値で振り分ける
HASH ・・・ 1つのカラムの値を式の結果で振り分ける
KEY ・・・ 1つ以上のカラムの値をMD5関数等で評価して分割する
メリットとしてはselectが高速になります
オプティマイザーを利用するため対象のパーティションのみを参照するらしい
ただし注意点があります
パーティショニングはユニークなキーを含めていなければなりません
オートインクリメントで作成したIDとかユニークだと思うのですがそのカラムをパーティショニングに設定なんて意味ないことはできませんね…
以上、負荷を考慮するときに考えることをあげてみました
検討の流れとしては
作られるデータ量(レコード数、サイズ)を考えそのテストデータを作成
→
さすがに多いとわかればテーブルを分けたりパーティショニングしたり、そうでないなら一つのテーブルで作成
→
テーブルに適切なインデックスを貼ってみる
→
テストデータを突っ込む
→
explainでインデックスをしっかり利用しているか確認
→
selectを投げて、実行速度を見てみる
という感じ
とはいえ実際にリリースしてみないとわからないこともあります
想定外のデータ量の増え方をするとか
社内の知見のある方曰く、「経験が大事」とおっしゃってました
コメント