多租户管理

更新时间:
复制为 MD 格式

在多租户应用中,因广播查询导致的性能下降或数据分布不均造成的资源浪费是常见问题。PolarDB PostgreSQL分布式版提供原生的多租户管理能力,支持水平拆分(Row-based Sharding)垂直拆分(Schema-based Sharding)两种模式。该能力可将特定租户的查询请求精确路由到单个DN节点,避免广播查询,实现高效读写。同时通过均衡租户数据分布,防止数据倾斜,提升资源利用率。

方案对比与选择

根据业务场景和数据特点,选择合适的拆分策略。两种策略的核心目标都是将单个租户的请求与数据锁定在单个DN节点上,以获得最佳性能。

模式

说明

推荐场景

水平拆分(Row-based Sharding)

在同一张表中通过租户ID字段(分布列)区分数据,并将不同租户的数据行分布到不同DN节点。

  • 所有租户的表结构完全相同。

  • 租户数量巨大(例如,大于等于10,000个)。

垂直拆分(Schema-based Sharding)

为每个租户创建独立的Schema,并将整个Schema的数据定向分布到特定DN节点。

  • 不同租户的表结构存在差异。

  • 需要在应用层保留原有的Schema隔离逻辑,以降低改造成本。

  • 租户数量较少(例如,小于10,000个)。

水平拆分

通过将租户ID列指定为分布列,实现按行(Row-based)的租户数据隔离。

步骤一:创建分布表

创建一张包含租户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');

步骤二:验证查询路由

执行针对特定租户的查询,并查看其查询计划,以验证请求是否被精确路由到单个DN节点。在返回的查询计划中,若Task Count1,则表明查询已成功下推到单个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)

垂直拆分

通过为每个租户创建独立的分布式Schema,实现按Schema的租户数据隔离。

步骤一:创建并分布Schema

为单个租户(例如 company_test_1)创建一个专属的Schema,并将其设置为分布式Schema。此操作会将该Schema下的所有数据和操作都定向到单个DN节点。

-- 1. 为租户 company_test_1 创建 Schema。
CREATE SCHEMA company_test_1;

-- 2. 将该 Schema 设置为分布式 Schema。
SELECT polar_cluster_schema_distribute('company_test_1');

步骤二:在租户Schema下创建表

将搜索路径(search_path)切换到目标租户的Schema,然后在该Schema下创建业务表。

-- 1. 切换到租户 company_test_1 的 Schema。
SET search_path TO company_test_1;

-- 2. 在该 Schema 下创建业务表。
CREATE TABLE users (id SERIAL, name TEXT);
CREATE TABLE orders (id SERIAL, user_id INT);

步骤三:验证查询路由

在指定租户的search_path下,执行查询并查看其查询计划,以验证请求是否被路由到单个DN节点。在返回的查询计划中,若Task Count1,则表明针对该租户的所有操作都已隔离在单个节点内(示例中节点为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)