Azure Cosmos DB for PostgreSQL のノードとテーブル

適用対象: Azure Cosmos DB for PostgreSQL (PostgreSQL の Citus データベース拡張機能を利用)

ノード

Azure Cosmos DB for PostgreSQL を使用すると、PostgreSQL サーバー (ノードと呼ばれる) は "シェアード ナッシング方式" のアーキテクチャで互いに調和できるようになります。 クラスター内のノードは、単一サーバーの場合より多くのデータを集合的に保持し、より多くの CPU コアを使用します。 このアーキテクチャでは、クラスターにノードを追加してデータベースを拡張することもできます。

コーディネーターとワーカー

各クラスターに、1 つのコーディネーター ノードと複数のワーカーが存在します。 アプリケーションは、クエリをコーディネーター ノードに送信し、このノードが関連するワーカーにリレーして、結果を累積します。 アプリケーションは、ワーカーに直接接続することはできません。

Azure Cosmos DB for PostgreSQL を使用すると、データベース管理者は、異なる行を異なるワーカー ノード上に格納して、テーブルを "分散" させることができます。 分散テーブルは、Azure Cosmos DB for PostgreSQL のパフォーマンスにとって重要です。 テーブルの分散に失敗すると、コーディネーター ノード上に完全に残り、マシン間の並列処理を利用できません。

分散テーブル上の各クエリに対して、コーディネーターは、必要なデータが単一または複数のノードのどちらに存在するかに応じて、単一のワーカー ノードにルーティングするか、または複数にわたって並列処理を行います。 コーディネーターは、メタデータ テーブルを参照して、どのように処理するかを決定します。 これらのテーブルは、ワーカー ノードの DNS 名およびヘルスと、ノード間でのデータの分布を追跡します。

テーブル型

クラスターには 3 つのテーブル型があり、それぞれが、ノードでは異なる方法で格納され、異なる目的に使用されます。

型 1:分散テーブル

最もよく使用される最初の型が分散テーブルです。 SQL ステートメントには通常のテーブルのように見えますが、ワーカー ノードにわたり水平方向にパーティション分割されます。 この意味は、テーブルの各行が異なるノードの、シャードと呼ばれるフラグメント テーブルに格納されるということです。

Azure Cosmos DB for PostgreSQL では、クラスター全体で SQL ステートメントだけではなく DDL ステートメントも実行されます。 分散テーブルのスキーマの変更は、ワーカーにわたるすべてのテーブルのシャードの更新にカスケーディングされます。

ディストリビューション列

Azure Cosmos DB for PostgreSQL では、アルゴリズムのシャーディングを使用して行がシャードに割り当てられます。 割り当ては、ディストリビューション列と呼ばれるテーブル列の値に基づいて決定論的に行われます。 クラスター管理者は、テーブルを配布するときに、この列を指定する必要があります。 パフォーマンスおよび機能には、適切な選択を行うことが重要です。

型 2:参照テーブル

参照テーブルは、コンテンツ全体が単一のシャードに集中される一種の分散テーブルです。 シャードは、すべてのワーカーにレプリケートされます。 いずれかのワーカーに対するクエリは、参照情報にローカルでアクセスでき、別のノードから行を要求するネットワーク オーバーヘッドは生じません。 行ごとに個別のシャードを区別する必要がないため、参照テーブルにはディストリビューション列はありません。

参照テーブルは通常小さく、任意のワーカー ノードで実行されるクエリに関連したデータの格納に使用されます。 たとえば、注文ステータスや製品カテゴリなどの列挙値があります。

型 3:ローカル テーブル

Azure Cosmos DB for PostgreSQL を使用する場合、接続先のコーディネーター ノードは通常の PostgreSQL データベースです。 コーディネーター上に通常のテーブルを作成し、それらをシャードしないように選択できます。

ローカル テーブルの適切な候補は、結合クエリに参加していない小規模の管理用テーブルになります。 たとえば、アプリケーションのサインインと認証用のユーザー テーブルです。

シャード

前のセクションでは、分散テーブルがワーカー ノード上にシャードとしてどのように格納されるかについて説明しました。 このセクションでは、さらに技術的な詳細について説明します。

コーディネーター上の pg_dist_shard メタデータ テーブルには、システム内の分散テーブルの各シャードの行が含まれます。 行は、ハッシュ領域 (shardminvalue、shardmaxvalue) 内の整数の範囲でシャード ID に一致します。

SELECT * from pg_dist_shard;
 logicalrelid  | shardid | shardstorage | shardminvalue | shardmaxvalue
---------------+---------+--------------+---------------+---------------
 github_events |  102026 | t            | 268435456     | 402653183
 github_events |  102027 | t            | 402653184     | 536870911
 github_events |  102028 | t            | 536870912     | 671088639
 github_events |  102029 | t            | 671088640     | 805306367
 (4 rows)

コーディネーター ノードでは、どのシャードが github_events の行を保持するかを判断する場合、行のディストリビューション列の値がハッシュされます。 その後、ノードにより、どのシャードの範囲にハッシュされた値が含まれるか調べられます。 範囲は、ハッシュ関数のイメージが disjoint 結合になるように定義されます。

シャードの配置

シャード 102027 が問題の行に関連付けられているとします。 行は、いずれかのワーカーにおいて、github_events_102027 と呼ばれるテーブルで読み取られるか書き込まれます。 どのワーカーでしょうか。 これは、すべてメタデータ テーブルによって決定されます。 シャードからワーカーへのマッピングは、シャード配置と呼ばれます。

コーディネーター ノードでは、github_events_102027 のような特定のテーブルを参照するフラグメントにクエリが再書き込みされ、これらのフラグメントが適切なワーカー上で実行されます。 シャード ID 102027 を保持しているノードを見つけるためにバックグラウンドで実行されるクエリの例を次に示します。

SELECT
    shardid,
    node.nodename,
    node.nodeport
FROM pg_dist_placement placement
JOIN pg_dist_node node
  ON placement.groupid = node.groupid
 AND node.noderole = 'primary'::noderole
WHERE shardid = 102027;
┌─────────┬───────────┬──────────┐
│ shardid │ nodename  │ nodeport │
├─────────┼───────────┼──────────┤
│  102027 │ localhost │     5433 │
└─────────┴───────────┴──────────┘

次の手順