マルチテナントアプリケーションでは、ブロードキャストクエリによるパフォーマンス低下や、データ分布の不均一性に起因するリソースの無駄遣いが一般的な課題です。PolarDB for PostgreSQL (Distributed Edition) は、ネイティブのマルチテナント管理機能を提供し、行ベースのシャーディング および スキーマベースのシャーディング の 2 つのモードをサポートします。この機能により、特定のテナントに対するクエリが単一のデータノード(DN)にルーティングされ、ブロードキャストクエリを回避するとともに、効率的な読み取りおよび書き込みを実現します。また、テナント間のデータ分布を均等化することで、データスキューを防止し、リソース利用率を向上させます。
比較と選択
ビジネスシナリオおよびデータの特性に応じて、適切なシャーディングポリシーを選択してください。両ポリシーの共通の目的は、単一テナントのリクエストおよびデータを 1 つの DN に限定し、最適なパフォーマンスを達成することです。
モード | 説明 | 推奨される利用シーン |
行ベースのシャーディング | 同一テーブル内のテナント ID フィールド(分布列)を用いてデータを区別します。異なるテナントのデータ行を異なる DN に分散します。 |
|
スキーマベースのシャーディング | 各テナントごとに個別のスキーマを作成します。そのスキーマ全体のデータを特定の DN にルーティングします。 |
|
行ベースのシャーディング
テナント ID 列を分布列として使用し、行単位でテナントデータを隔離します。
ステップ 1:分散テーブルの作成
テナント ID 列(例:tenant_id)を含むテーブルを作成します。その後、create_distributed_table 関数を呼び出して、この列を分散キーとして使用する 分散テーブル に変換します。
-- 1. テーブルを作成します。tenant_id 列はテナントを区別するために使用されます。
CREATE TABLE test_table (tenant_id text primary key, data text);
-- 2. test_table を分散テーブルとして設定し、tenant_id を分布列として指定します。
SELECT create_distributed_table('test_table', 'tenant_id');ステップ 2:クエリルーティングの確認
特定のテナント向けにクエリを実行し、クエリプランを確認して、リクエストが単一の DN にルーティングされていることを検証します。返されたクエリプランにおいて、Task Count が 1 の場合、クエリは正常に単一の DN へプッシュダウンされています。本例では、対象ノードは 10.0.0.1:5432 です。これにより、ブロードキャストクエリが回避されます。
-- company1 テナント向けのクエリプランを表示します。
EXPLAIN SELECT * FROM test_table WHERE tenant_id = 'company1';
-- サンプル結果:
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Custom Scan (PolarCluster Adaptive) (cost=0.00..0.00 rows=0 width=0)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=10.0.0.1 port=5432 dbname=testdb
-> Index Scan using test_table_pkey_102185 on test_table_102185 test_table (cost=0.15..2.37 rows=1 width=64)
Index Cond: (tenant_id = 'company1'::text)
(7 rows)スキーマベースのシャーディング
この方法では、各テナントごとに個別の分散スキーマを作成することで、テナントデータを隔離します。
ステップ 1:スキーマの作成と分散化
単一テナント向けに専用のスキーマ(例:company_test_1)を作成し、これを 分散スキーマ として設定します。この操作により、当該スキーマ下のすべてのデータおよび操作が単一の DN にルーティングされます。
-- 1. company_test_1 テナント向けのスキーマを作成します。
CREATE SCHEMA company_test_1;
-- 2. スキーマを分散スキーマとして設定します。
SELECT polar_cluster_schema_distribute('company_test_1');ステップ 2:テナントスキーマ内でのテーブル作成
search_path を対象テナントのスキーマに切り替え、そのスキーマ内に業務テーブルを作成します。
-- 1. company_test_1 テナントのスキーマに切り替えます。
SET search_path TO company_test_1;
-- 2. このスキーマ内に業務テーブルを作成します。
CREATE TABLE users (id SERIAL, name TEXT);
CREATE TABLE orders (id SERIAL, user_id INT);ステップ 3:クエリルーティングの確認
search_path をテナントのスキーマに設定した後、クエリを実行し、クエリプランを確認して、リクエストが単一の DN にルーティングされていることを検証します。返されたクエリプランで Task Count が 1 である場合、当該テナントに関するすべての操作が単一ノード上で隔離されています。本例では、対象ノードは 10.0.0.1:5432 です。
-- 1. search_path が対象テナントに正しく設定されていることを確認します。
SET search_path TO company_test_1;
-- 2. クエリプランを表示します。
EXPLAIN SELECT * FROM users WHERE id = 1;
-- サンプル結果:
QUERY PLAN
--------------------------------------------------------------------------------
Custom Scan (PolarCluster Adaptive) (cost=0.00..0.00 rows=0 width=0)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=10.0.0.1 port=5432 dbname=testdb
-> Seq Scan on users_102191 users (cost=0.00..25.88 rows=6 width=36)
Filter: (id = 1)
(7 rows)