Documentdb-partitioning

提供:Dev Guides
移動先:案内検索

DocumentDB-パーティショニング

データベースが10GBを超えて大きくなり始めると、新しいコレクションを作成してから、さらに多くのコレクションにデータを分散またはパーティション分割するだけでスケールアウトできます。

遅かれ早かれ、10GBの容量を持つ単一のコレクションでは、データベースを含めるのに十分ではなくなります。 10GBはそれほど大きな数字には聞こえないかもしれませんが、JSONドキュメントを保存していることに注意してください。これは単なるテキストであり、インデックスのストレージオーバーヘッドを考慮しても、多くのプレーンテキストドキュメントを10GBに収めることができます。

スケーラビリティに関しては、ストレージだけが問題ではありません。 コレクションで使用可能な最大スループットは、S3コレクションで取得できる1秒あたり2.5リクエスト単位です。 したがって、より高いスループットが必要な場合は、複数のコレクションでパーティション化してスケールアウトする必要もあります。 スケールアウトパーティショニングは、*水平パーティショニング*とも呼ばれます。

Azure DocumentDBでデータをパーティション分割するために使用できる多くのアプローチがあります。 以下は最も一般的な戦略です-

  • スピルオーバーパーティショニング
  • 範囲分割
  • ルックアップパーティショニング
  • ハッシュ分割

スピルオーバーパーティショニング

スピルオーバーパーティショニングは、パーティションキーがないため、最も単純な戦略です。 多くのことについて確信が持てない場合は、多くの場合、最初から始めるのが良い選択です。 単一のコレクションを超えてスケ​​ールアウトする必要があるかどうか、追加する必要があるコレクションの数、または追加する必要のある速度を知ることはできません。

  • スピルオーバーパーティショニングは単一のコレクションから始まり、パーティションキーはありません。
  • コレクションは拡大し始め、その後、10GBの制限に近づくまで、さらに拡大し、さらに拡大します。
  • 容量が90%に達すると、新しいコレクションにあふれて、新しいドキュメントに使用し始めます。
  • データベースがより多くのコレクションにスケールアウトしたら、おそらくパーティションキーに基づく戦略に移行する必要があります。
  • その場合、移行先の戦略に基づいてドキュメントを異なるコレクションに移動することにより、データのバランスを取り直す必要があります。

範囲分割

最も一般的な戦略の1つは、範囲分割です。 このアプローチでは、ドキュメントのパーティションキーが含まれる可能性のある値の範囲を決定し、その範囲に対応するコレクションにドキュメントを向けます。

  • 定義された日付の範囲内のドキュメントを保持するコレクションを作成するこの戦略では、通常、日付が使用されます。 十分に小さい範囲を定義すると、コレクションが10GBの制限を超えることはないと確信できます。 たとえば、1つのコレクションで1か月間ドキュメントを合理的に処理できるシナリオがあります。
  • また、ほとんどのユーザーが現在のデータ(今月またはおそらく先月のデータ)を照会している場合もありますが、はるかに古いデータを検索することはほとんどありません。 そのため、6月にS3コレクションを開始します。S3コレクションは、購入できる最も高価なコレクションであり、取得できる最高のスループットを提供します。
  • 7月に別のS3コレクションを購入して7月のデータを保存し、6月のデータをより安価なS2コレクションに縮小します。 次に、8月に別のS3コレクションを取得し、7月をS2に、6月をS1に縮小します。 毎月、常に最新のデータを高いスループットで使用できるようにし、古いデータは低いスループットで使用できるようにします。
  • クエリがパーティションキーを提供している限り、クエリが必要なコレクションのみがクエリされ、スピルオーバーパーティショニングで発生するようなデータベース内のすべてのコレクションはクエリされません。

ルックアップパーティショニング

ルックアップパーティション分割を使用すると、パーティションキーに基づいてドキュメントを特定のコレクションにルーティングするパーティションマップを定義できます。 たとえば、地域ごとにパーティションを分割できます。

  • 1つのコレクションにすべての米国のドキュメント、別のコレクションにすべてのヨーロッパのドキュメント、および3番目のコレクションにある他の地域のすべてのドキュメントを保存します。
  • このパーティションマップとルックアップパーティションリゾルバを使用すると、各ドキュメントに含まれるリージョンプロパティであるパー​​ティションキーに基づいて、ドキュメントを作成するコレクションとクエリするコレクションを判別できます。

ハッシュ分割

ハッシュパーティション分割では、ハッシュ関数の値に基づいてパーティションが割り当てられるため、複数のパーティションにリクエストとデータを均等に分散できます。

これは一般に、多数の個別のクライアントから生成または消費されるデータを分割するために使用され、ユーザープロファイル、カタログアイテムなどの保存に役立ちます。

NET SDKが提供するRangePartitionResolverを使用した範囲分割の簡単な例を見てみましょう。.

  • ステップ1 *-新しいDocumentClientを作成し、CreateCollectionsタスクで2つのコレクションを作成します。 1つはA〜Mで始まるユーザーIDを持つユーザー用のドキュメントを含み、もう1つはユーザーID N〜Zを持つドキュメントを含みます。
private static async Task CreateCollections(DocumentClient client) {
   await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
      Id = “CollectionAM” });

   await client.CreateDocumentCollectionAsync(“dbs/myfirstdb”, new DocumentCollection {
      Id = “CollectionNZ” });
}
  • ステップ2 *-データベースの範囲リゾルバーを登録します。
  • ステップ3 *-新しいRangePartitionResolver <string>を作成します。これは、パーティションキーのデータ型です。 コンストラクターは、パーティションキーのプロパティ名と、シャードマップまたはパーティションマップであるディクショナリの2つのパラメーターを取ります。ディクショナリは、リゾルバー用に事前定義している範囲と対応するコレクションの単なるリストです。
private static void RegisterRangeResolver(DocumentClient client) {

  //Note: \uffff is the largest UTF8 value, so M\ufff includes all strings that start with M.

   var resolver = new RangePartitionResolver<string>(
      "userId", new Dictionary<Range<string>, string>() {
      { new Range<string>("A", "M\uffff"), "dbs/myfirstdb/colls/CollectionAM" },
      { new Range<string>("N", "Z\uffff"), "dbs/myfirstdb/colls/CollectionNZ" },
   });

   client.PartitionResolvers["dbs/myfirstdb"] = resolver;
 }

ここでは、可能な限り最大のUTF-8値をエンコードする必要があります。 または、最初の範囲は、1つの単一のMを除くどのMでも一致せず、同様に2番目の範囲のZでも一致しません。 したがって、ここでエンコードされた値は、パーティションキーで一致するためのワイルドカードと考えることができます。

  • ステップ4 *-リゾルバーを作成したら、現在のDocumentClientでデータベースに登録します。 それを行うには、PartitionResolverの辞書プロパティに割り当てます。

通常のコレクションではなく、データベースに対してドキュメントを作成およびクエリします。リゾルバーはこのマップを使用して、リクエストを適切なコレクションにルーティングします。

それでは、いくつかのドキュメントを作成しましょう。 最初に、userId Kirk用に1つ作成し、次にSpock用に1つ作成します。

private static async Task CreateDocumentsAcrossPartitions(DocumentClient client) {
   Console.WriteLine();
   Console.WriteLine("*** *Create Documents Across Partitions* ***");

   var kirkDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
      "Kirk", title = "Captain" });
   Console.WriteLine("Document 1: {0}", kirkDocument.Resource.SelfLink);

   var spockDocument = await client.CreateDocumentAsync("dbs/myfirstdb", new { userId =
      "Spock", title = "Science Officer" });
   Console.WriteLine("Document 2: {0}", spockDocument.Resource.SelfLink);
}

ここでの最初のパラメーターは、特定のコレクションではなく、データベースへの自己リンクです。 これはパーティションリゾルバなしでは不可能ですが、1つを使用するとシームレスに機能します。

両方のドキュメントはデータベースmyfirstdbに保存されましたが、RangePartitionResolverが正常に機能している場合、KirkはAからMのコレクションに格納され、SpockはNからZのコレクションに格納されていることがわかります。

次のコードに示すように、これらをCreateDocumentClientタスクから呼び出しましょう。

private static async Task CreateDocumentClient() {
  //Create a new instance of the DocumentClient
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
      await CreateCollections(client);
      RegisterRangeResolver(client);
      await CreateDocumentsAcrossPartitions(client);
   }
}

上記のコードが実行されると、次の出力が表示されます。

*** *Create Documents Across Partitions* ***
Document 1: dbs/Ic8LAA==/colls/Ic8LAO2DxAA=/docs/Ic8LAO2DxAABAAAAAAAAAA==/
Document 2: dbs/Ic8LAA==/colls/Ic8LAP12QAE=/docs/Ic8LAP12QAEBAAAAAAAAAA==/

ご覧のように、2つのドキュメントのセルフリンクは2つの別々のコレクションに存在するため、異なるリソースIDを持っています。