はじめに
MongoDBでの効率的なコレクション設計には、シャーディングを考慮したアプローチが不可欠です。本記事では、最適なシャードキーの選び方に焦点を当て、それらのキーがMongoDBのパフォーマンスにどのように影響するかを探ります。
シャードキーとは
シャーディングはデータベースの水平分散を指し、データを異なるサーバーに分散させて負荷を軽減します。シャードキーはこのシャーディングプロセスにおいて、どのデータがどのシャードに割り当てられるかを決定する重要な要素です。
MongoDBでは、シャードキーによってデータは重複なく分割されます。分割されたデータ範囲をチャンクと呼び、MongoDBはこれらのチャンクを各シャードに均等に分配します。この均等なデータ分配プロセスをオートバランシングと称します。
シャードキーの選び方アンチパターン
まずは、やってはいけない選び方を説明します。シャードキーの選び方はいろいろありますが、やらない方を先に分かっておくと選択肢が狭まり、選びやすくなります。
では、シャードキーのアンチパターンを3つ紹介します。
アンチパターン1:検索に使用しないフィールド
検索に使用しないフィールドをシャードキーに設定してしまうと、サーバーに無駄な負荷をかけてしまいます。
シャーディングされたサーバーへデータを取得するときの流れを説明します。
- mongosからconfigサーバーへ、データが格納されている場所を問い合わせます。
- configサーバーは設定されたシャードキーから、データが格納されたシャードを見つけます
- configサーバーからmongosへ格納場所(シャード)を渡します
- mongosは指定されたシャードからデータを取得します
ここで、シャードキーのフィールドが検索クエリに指定されていないと、configサーバーがmongosへ格納場所を教えることができず、シャードを全検索します。
そのため、せっかくシャードを分散しているのに、負荷分散できなければシャーディングの意味がないため、検索に使わないフィールドはシャードキーに指定しないようにしましょう。
アンチパターン2:単調増加するフィールド
単調増加するフィールド(例えば、タイムスタンプやID)は、新しいデータが特定のシャードに偏ることを引き起こすため、シャードキーとしては適していません。
例えばUserコレクションで、UserIDをシャードキーにしたとき、UserIDは001,002,003と単調増加していきます。多くのユーザーがいる場合、UserIDの値も大きくなり、片方のシャードに問い合わせが偏ります。
これはMongoDBが各チャンクにminKey,maxKeyをいう値をもっており、単調増加した場合、maxKeyのみが増えていくためです。
単調増加するフィールドとしては、_idや、インクリメントだけする数値データ、日付データなどがあります。これらは、シャードキーに設定しないようにしましょう。
シャードキーの選び方
アンチパターンがわかったところで、シャードキーの選び方を考えます。
適切なシャードキーを選ぶことは、システムのスケーラビリティとパフォーマンスに直接影響します。
以下に選び方の一種を載せます。
検索条件に使われるフィールド
「アンチパターン1:検索に使用しないフィールド」の逆で、検索によく使われるフィールドはシャードキーに適しています。
カーディナリティの高いフィールド
シャードキーのカーディナリティによって、作成できるチャンクの最大数が決まります。
そのため、カーディナリティが高い、つまり多様な値を持つフィールドをシャードキーに選ぶことで、データの分散が均等になり、負荷分散に寄与します。
例として、投稿コレクションを例に、どのフィールドがシャードキーに適切か考えてみましょう。
投稿IDはシステムにより自動採番される値とします。
【投稿コレクション】
- _id
- 投稿ID
- ユーザーID
- 投稿日時
- 投稿内容
- いいね数
検索条件に使用されない、「_id」「いいね数」はシャードキーに適切ではありません。
単調増加する、「投稿ID」「投稿日時」はシャードキーに適切ではありません。
残ったのは「ユーザーID」「投稿内容」ですが、カーディナリティが高い「ユーザーID」が適切です。
終わりに
適切なシャードキーの選定は、MongoDBのパフォーマンスとスケーラビリティを最大化する上で重要です。これらのガイドラインを参考に、効果的なシャーディング戦略を立てましょう。
参考文献
- MongoDB公式ドキュメント: シャードキーの選び方