シャーディングとパーティショニング — 引き出しを仕切るか、タンスごと分けるか
注文が毎日増え続けるテーブルは、やがて重すぎるタンスになります。引き出しが1つしかないので、何を探すにも中身を全部ひっくり返す。しかも出し入れできる人は1人だけで、注文が殺到すると行列ができる。
対策は2つあります。タンスの中に月別の仕切りを入れるのがパーティショニング、タンスそのものを何台かに分けるのがシャーディングです。名前は似ていますが、解決する問題が違います。下の図1で分け方を切り替えて、2通りの探し方と書き込みの殺到を試してみてください。
パーティショニング — 同じタンスの中に仕切りを入れる
パーティショニングは、1つのテーブルを同じサーバーの中でいくつかの区画に分けることです。図1では注文月で6つの棚に分けました。この「月」がパーティションキーです。
効くのはキーと同じ条件で探すときです。「5月の注文」なら5月の棚だけを開け、残り5つは見もしない(パーティションプルーニング)。さらに「1年より古い注文を消す」も、1件ずつ消さずに古い棚を丸ごと捨てるだけで済みます。ログや注文履歴のように時間とともに積み上がるデータでよく使われるのは、このためです。
ただし、サーバーは1台のままです。図1でスライダーを右に振ると分かるとおり、仕切りを入れても書き込みをさばく力は1ミリも増えません。整理はできても、力持ちにはならないのです。
シャーディング — タンスそのものを増やす
1台では書き込みが追いつかない、ディスクにも入りきらない。そうなったらサーバーごと分けるしかありません。これがシャーディングで、分けた1台1台をシャードと呼びます。図1では「会員番号を3で割った余り」で振り分けました。この会員番号がシャードキーです。
会員#7の注文を探すときは、7÷3の余りが1だからシャードBだけに聞けばいい。計算だけで置き場所が分かるので、ほかの2台は別の客の相手をしていられます。台数を増やせば、さばける量もそのまま増えていきます。
代わりに、シャードキー以外の条件で探すと全台に聞いて回ることになります(scatter-gather)。「5月の売上合計」のような集計は全シャードの結果を集め直す必要があり、シャードをまたぐJOINやトランザクションも、1台のときのように気軽には書けません。
キー選びが、ほぼすべて
どちらの方式でも、うまくいくかどうかはキーの選び方で決まります。基準は2つ。よく使う探し方と合っているか、そしてデータと負荷が偏らないかです。
たとえば注文を「月」でシャーディングすると、探しやすそうに見えて、実は今月のシャードだけに書き込みが集中します。残りの台は古い注文を抱えて暇なまま。これをホットスポットと呼びます。整理棚なら月で仕切って構わないけれど、タンスを分けるなら負荷が散らばる会員番号のほうが向いている――同じ「月」でも、仕切りに使うか振り分けに使うかで向き不向きが変わるわけです。
- パーティショニング
- 1つのテーブルを、同じDBの中で複数の区画に分けること。探す範囲を絞り、古いデータを区画ごと捨てやすくする。
- シャーディング
- データを複数のDBサーバーに分けて置くこと。書き込み性能と容量を、台数に応じて増やせる。
- パーティションキー / シャードキー
- どの区画・どのサーバーに入れるかを決める列。よく使う検索条件と合っていることが大事。
- パーティションプルーニング
- 検索条件から、見なくてよい区画を最初から飛ばすこと。
- ホットスポット
- キーの偏りで、特定のシャードにだけ負荷やデータが集中する状態。
まとめ
パーティショニングはタンスの中の仕切りで、探す範囲を狭くしたり古いものを捨てやすくしたりする「整理」の技術です。シャーディングはタンスを何台にも分けることで、1台では受けきれない量をさばく「力仕事」の技術です。そしてどちらも、キーと同じ条件で探すときだけ速く、違う条件では全部を見ることになります。分ける前に考えるべきは「どう分けるか」より先に、「いちばんよく、何で探すのか」です。