View a markdown version of this page

Aurora PostgreSQL Limitless Database 的 DDL 限制和其他信息 - Amazon Aurora

Aurora PostgreSQL Limitless Database 的 DDL 限制和其他信息

以下主题描述了 Aurora PostgreSQL Limitless Database 中的 DDL SQL 命令的限制或提供了更多信息。

ALTER TABLE

Aurora PostgreSQL Limitless Database 通常支持 ALTER TABLE 命令。有关更多信息,请参阅 PostgreSQL 文档中的 ALTER TABLE。

限制

对于受支持的选项,ALTER TABLE 具有以下限制。

移除一列
  • 在分片表上,您无法移除属于分片键的列。

  • 在引用表上,您无法移除主键列。

更改列的数据类型
  • 不支持 USING 表达式。

  • 在分片表上,您无法更改属于分片键的列类型。

添加或移除约束

有关不支持的内容的详细信息,请参阅约束。

更改列的默认值

支持默认值。有关更多信息,请参阅 默认值。

不支持的选项

不支持某些选项,因为它们依赖于不支持的功能,例如触发器。

不支持以下 ALTER TABLE 的表级选项:

  • ALL IN TABLESPACE

  • ATTACH PARTITION

  • DETACH PARTITION

  • ONLY 标志

  • RENAME CONSTRAINT

不支持以下 ALTER TABLE 的列级选项:

  • ADD GENERATED

  • DROP EXPRESSION [ IF EXISTS ]

  • DROP IDENTITY [ IF EXISTS ]

  • RESET

  • RESTART

  • SET

  • SET COMPRESSION

  • SET STATISTICS

CREATE DATABASE

在 Aurora PostgreSQL Limitless Database 中,仅支持无限数据库。

运行 CREATE DATABASE 时,在一个或多个节点中成功创建的数据库可能会在其他节点中失效,因为数据库创建是一项非事务性操作。在这种情况下,成功创建的数据库对象将在预定时间内自动从所有节点中移除,以保持数据库分片组的一致性。在此期间,重新创建同名数据库可能会导致错误,提示该数据库已存在。

支持以下选项:

  • 排序规则:

    CREATE DATABASE name WITH [LOCALE = locale] [LC_COLLATE = lc_collate] [LC_CTYPE = lc_ctype] [ICU_LOCALE = icu_locale] [ICU_RULES = icu_rules] [LOCALE_PROVIDER = locale_provider] [COLLATION_VERSION = collation_version];
  • CREATE DATABASE WITH OWNER:

    CREATE DATABASE name WITH OWNER = user_name;

不支持以下选项:

  • CREATE DATABASE WITH TABLESPACE:

    CREATE DATABASE name WITH TABLESPACE = tablespace_name;
  • CREATE DATABASE WITH TEMPLATE:

    CREATE DATABASE name WITH TEMPLATE = template;

CREATE INDEX

分片表支持 CREATE INDEX CONCURRENTLY:

CREATE INDEX CONCURRENTLY index_name ON table_name(column_name);

所有表类型都支持 CREATE UNIQUE INDEX:

CREATE UNIQUE INDEX index_name ON table_name(column_name);

不支持 CREATE UNIQUE INDEX CONCURRENTLY:

CREATE UNIQUE INDEX CONCURRENTLY index_name ON table_name(column_name);

有关更多信息,请参阅 UNIQUE。有关创建索引的一般信息,请参阅 PostgreSQL 文档中的 CREATE INDEX。

显示索引

当您使用 \d table_name 或类似命令时,并非所有索引在路由器上都可见。相反,可以使用 pg_catalog.pg_indexes 视图获取索引,如以下示例中所示。

SET rds_aurora.limitless_create_table_mode='sharded'; SET rds_aurora.limitless_create_table_shard_key='{"id"}'; CREATE TABLE items (id int PRIMARY KEY, val int); CREATE INDEX items_my_index on items (id, val); postgres_limitless=> SELECT * FROM pg_catalog.pg_indexes WHERE tablename='items'; schemaname | tablename | indexname | tablespace | indexdef ------------+-----------+----------------+------------+------------------------------------------------------------------------ public | items | items_my_index | | CREATE INDEX items_my_index ON ONLY public.items USING btree (id, val) public | items | items_pkey | | CREATE UNIQUE INDEX items_pkey ON ONLY public.items USING btree (id) (2 rows)

CREATE SCHEMA

不支持带有架构元素的 CREATE SCHEMA:

CREATE SCHEMA my_schema CREATE TABLE (column_name INT);

这将生成类似于以下内容的错误:

ERROR: CREATE SCHEMA with schema elements is not supported

CREATE TABLE

不支持 CREATE TABLE 语句中的关系,例如:

CREATE TABLE orders (orderid int, customerId int, orderDate date) WITH (autovacuum_enabled = false);

不支持 IDENTITY 列,例如:

CREATE TABLE orders (orderid INT GENERATED ALWAYS AS IDENTITY);

Aurora PostgreSQL Limitless Database 支持最多 54 个字符作为分片表名称。

CREATE TABLE AS

要使用 CREATE TABLE AS 创建表,必须使用 rds_aurora.limitless_create_table_mode 变量。对于分片表,您还必须使用 rds_aurora.limitless_create_table_shard_key 变量。有关更多信息,请参阅 使用变量创建无限表。

-- Set the variables. SET rds_aurora.limitless_create_table_mode='sharded'; SET rds_aurora.limitless_create_table_shard_key='{"a"}'; CREATE TABLE ctas_table AS SELECT 1 a; -- "source" is the source table whose columns and data types are used to create the new "ctas_table2" table. CREATE TABLE ctas_table2 AS SELECT a,b FROM source;

您无法使用 CREATE TABLE AS 创建引用表,因为它们需要主键约束。CREATE TABLE AS 不会将主键传播到新表。

有关常规信息,请参阅 PostgreSQL 文档中的 CREATE TABLE AS。

DROP DATABASE

您可以删除已创建的数据库。

DROP DATABASE 命令在后台异步运行。在运行时,如果您尝试创建具有相同名称的新数据库,您将收到一条错误消息。

SELECT INTO

SELECT INTO 在功能上类似于 CREATE TABLE AS。您必须使用 rds_aurora.limitless_create_table_mode 变量。对于分片表,您还必须使用 rds_aurora.limitless_create_table_shard_key 变量。有关更多信息,请参阅 使用变量创建无限表。

-- Set the variables. SET rds_aurora.limitless_create_table_mode='sharded'; SET rds_aurora.limitless_create_table_shard_key='{"a"}'; -- "source" is the source table whose columns and data types are used to create the new "destination" table. SELECT * INTO destination FROM source;

当前,SELECT INTO 操作通过路由器执行,而不直接通过分片执行。因此,性能可能会有局限性。

有关常规信息,请参阅 PostgreSQL 文档中的 SELECT INTO。

约束

以下限制适用于 Aurora PostgreSQL Limitless Database 中的约束。

CHECK

支持涉及文字比较运算符的简单约束。不支持需要函数验证的更复杂表达式和约束,如以下示例所示。

CREATE TABLE my_table ( id INT CHECK (id > 0) -- supported , val INT CHECK (val > 0 AND val < 1000) -- supported , tag TEXT CHECK (length(tag) > 0) -- not supported: throws "Expression inside CHECK constraint is not supported" , op_date TIMESTAMP WITH TIME ZONE CHECK (op_date <= now()) -- not supported: throws "Expression inside CHECK constraint is not supported" );

您还可以为约束提供显式名称,如以下示例所示。

CREATE TABLE my_table ( id INT CONSTRAINT positive_id CHECK (id > 0) , val INT CONSTRAINT val_in_range CHECK (val > 0 AND val < 1000) );

您还可以将表级约束语法与 CHECK 约束一起使用,如以下示例所示。

CREATE TABLE my_table ( id INT CONSTRAINT positive_id CHECK (id > 0) , min_val INT CONSTRAINT min_val_in_range CHECK (min_val > 0 AND min_val < 1000) , max_val INT , CONSTRAINT max_val_in_range CHECK (max_val > 0 AND max_val < 1000 AND max_val > min_val) );
EXCLUDE

Aurora PostgreSQL Limitless Database 不支持排除约束。

FOREIGN KEY

有关更多信息,请参阅 外键。

NOT NULL

支持 NOT NULL 约束,无任何限制。

PRIMARY KEY

主键意味着唯一约束,因此对唯一约束的相同限制也适用于主键。这意味着:

  • 如果将表转换为分片表,则分片键必须是主键的子集。也就是说,主键包含分片键的所有列。

  • 如果将表转换为引用表,则该表必须具有主键。

以下示例演示了如何使用主键。

-- Create a standard table. CREATE TABLE public.my_table ( item_id INT , location_code INT , val INT , comment text ); -- Change the table to a sharded table using the 'item_id' and 'location_code' columns as shard keys. CALL rds_aurora.limitless_alter_table_type_sharded('public.my_table', ARRAY['item_id', 'location_code']);

正在尝试添加不包含分片键的主键:

-- Add column 'item_id' as the primary key. -- Invalid because the primary key doesnt include all columns from the shard key: -- 'location_code' is part of the shard key but not part of the primary key ALTER TABLE public.my_table ADD PRIMARY KEY (item_id); -- ERROR -- add column "val" as primary key -- Invalid because primary key does not include all columns from shard key: -- item_id and location_code iare part of shard key but not part of the primary key ALTER TABLE public.my_table ADD PRIMARY KEY (item_id); -- ERROR

正在尝试添加包含分片键的主键:

-- Add the 'item_id' and 'location_code' columns as the primary key. -- Valid because the primary key contains the shard key. ALTER TABLE public.my_table ADD PRIMARY KEY (item_id, location_code); -- OK -- Add the 'item_id', 'location_code', and 'val' columns as the primary key. -- Valid because the primary key contains the shard key. ALTER TABLE public.my_table ADD PRIMARY KEY (item_id, location_code, val); -- OK

将标准表更改为引用表。

-- Create a standard table. CREATE TABLE zipcodes (zipcode INT PRIMARY KEY, details VARCHAR); -- Convert the table to a reference table. CALL rds_aurora.limitless_alter_table_type_reference('public.zipcode');

有关创建分片表和引用表的更多信息,请参阅创建 Aurora PostgreSQL Limitless Database 表。

UNIQUE

在分片表中,唯一键必须包含分片键,也就是说,分片键必须是唯一键的子集。将表类型更改为分片表时会检查此项。在引用表中没有任何限制。

CREATE TABLE customer ( customer_id INT NOT NULL , zipcode INT , email TEXT UNIQUE );

支持表级 UNIQUE 约束,如以下示例所示。

CREATE TABLE customer ( customer_id INT NOT NULL , zipcode INT , email TEXT , CONSTRAINT zipcode_and_email UNIQUE (zipcode, email) );

以下示例显示了如何同时使用主键和唯一键。两个键都必须包含分片键。

SET rds_aurora.limitless_create_table_mode='sharded'; SET rds_aurora.limitless_create_table_shard_key='{"p_id"}'; CREATE TABLE t1 ( p_id BIGINT NOT NULL, c_id BIGINT NOT NULL, PRIMARY KEY (p_id), UNIQUE (p_id, c_id) );

有关更多信息,请参阅 PostgreSQL 文档中的 Constraints。

默认值

Aurora PostgreSQL Limitless Database 支持默认值中的表达式。

以下示例显示如何使用默认值。

CREATE TABLE t ( a INT DEFAULT 5, b TEXT DEFAULT 'NAN', c NUMERIC ); CALL rds_aurora.limitless_alter_table_type_sharded('t', ARRAY['a']); INSERT INTO t DEFAULT VALUES; SELECT * FROM t; a | b | c ---+-----+--- 5 | NAN | (1 row)

支持表达式,如以下示例所示。

CREATE TABLE t1 (a NUMERIC DEFAULT random());

以下示例添加了一个新列,该列为 NOT NULL 且具有默认值。

ALTER TABLE t ADD COLUMN d BOOLEAN NOT NULL DEFAULT FALSE; SELECT * FROM t; a | b | c | d ---+-----+---+--- 5 | NAN | | f (1 row)

以下示例使用默认值更改现有列。

ALTER TABLE t ALTER COLUMN c SET DEFAULT 0.0; INSERT INTO t DEFAULT VALUES; SELECT * FROM t; a | b | c | d ---+-----+-----+----- 5 | NAN | | f 5 | NAN | 0.0 | f (2 rows)

以下示例删除默认值。

ALTER TABLE t ALTER COLUMN a DROP DEFAULT; INSERT INTO t DEFAULT VALUES; SELECT * FROM t; a | b | c | d ---+-----+-----+----- 5 | NAN | | f 5 | NAN | 0.0 | f | NAN | 0.0 | f (3 rows)

有关更多信息,请参阅 PostgreSQL 文档中的 Default values。

扩展程序

Aurora PostgreSQL Limitless Database 支持以下 PostgreSQL 扩展:

Aurora PostgreSQL Limitless Database 目前不支持大多数 PostgreSQL 扩展。但是,您仍然可以使用 shared_preload_libraries(SPL)配置设置将扩展加载到 Aurora PostgreSQL 主数据库集群中。它们还会加载到 Aurora PostgreSQL Limitless Database 中,但可能无法正常运行。

例如,您可以加载 pg_hint_plan 扩展,但加载它并不能保证使用查询注释中传递的提示。

注意

您无法修改与 pg_stat_statements 扩展关联的对象。有关安装 pg_stat_statements 的信息,请参阅 limitless_stat_statements。

您可以使用 pg_available_extensions 和 pg_available_extension_versions 函数查找 Aurora PostgreSQL Limitless Database 中支持的扩展。

扩展支持以下 DDL:

CREATE EXTENSION

您可以像在 PostgreSQL 中那样创建扩展。

CREATE EXTENSION [ IF NOT EXISTS ] extension_name [ WITH ] [ SCHEMA schema_name ] [ VERSION version ] [ CASCADE ]

有关更多信息,请参阅 PostgreSQL 文档中的 CREATE EXTENSION。

ALTER EXTENSION

支持以下 DDL:

ALTER EXTENSION name UPDATE [ TO new_version ] ALTER EXTENSION name SET SCHEMA new_schema

有关更多信息,请参阅 PostgreSQL 文档中的 ALTER EXTENSION。

DROP EXTENSION

您可以像在 PostgreSQL 中那样删除扩展。

DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]

有关更多信息,请参阅 PostgreSQL 文档中的 DROP EXTENSION。

扩展不支持以下 DDL:

ALTER EXTENSION

您无法添加或删除扩展中的成员对象。

ALTER EXTENSION name ADD member_object ALTER EXTENSION name DROP member_object

Aurora PostgreSQL Limitless Database 中的 pg_buffercache 差异

在 Aurora PostgreSQL Limitless Database 中,当您安装 pg_buffercache 扩展并使用 pg_buffercache 视图时,您只能从当前连接的节点接收与缓冲区相关的信息:路由器。同样,使用函数 pg_buffercache_summary 或 pg_buffercache_usage_counts 仅提供来自所连接节点的信息。

您可能有多个节点,可能需要从任意节点访问缓冲区信息才能有效诊断问题。因此,Limitless Database 提供以下函数:

  • rds_aurora.limitless_pg_buffercache(subcluster_id)

  • rds_aurora.limitless_pg_buffercache_summary(subcluster_id)

  • rds_aurora.limitless_pg_buffercache_usage_counts(subcluster_id)

通过输入任何节点(无论是路由器还是分片)的子集群 ID,您可以轻松访问该节点的特定缓冲区信息。当您在无限数据库中安装 pg_buffercache 扩展时,这些函数可以直接使用。

注意

Aurora PostgreSQL Limitless Database 支持 pg_buffercache 扩展版本 1.4 及更高版本的函数。

limitless_pg_buffercache 视图中显示的列与 pg_buffercache 视图中显示的列略有不同:

  • bufferid – 与 pg_buffercache 保持不变。

  • relname – 与 pg_buffercache 中显示文件节点编号不同,limitless_pg_buffercache 如果在当前数据库或共享系统目录中可用,则显示相关的 relname,否则为 NULL。

  • parent_relname – 如果 relname 列中的值代表分区表(在分片表的情况下)pg_buffercache 列中没有的这一新列会显示父 relname。否则,将显示 NULL。

  • spcname – 与 pg_buffercache 中显示表空间对象标识符(OID)不同,limitless_pg_buffercache 显示表空间名称。

  • datname – 与 pg_buffercache 中显示数据库 OID 不同,limitless_pg_buffercache 显示数据库名称。

  • relforknumber – 与 pg_buffercache 保持不变。

  • relblocknumber – 与 pg_buffercache 保持不变。

  • isdirty – 与 pg_buffercache 保持不变。

  • usagecount – 与 pg_buffercache 保持不变。

  • pinning_backends – 与 pg_buffercache 保持不变。

limitless_pg_buffercache_summary 和 limitless_pg_buffercache_usage_counts 视图中的列分别与常规 pg_buffercache_summary 和 pg_buffercache_usage_counts 视图中的列相同。

通过使用这些功能,您可以访问 Limitless Database 环境中所有节点的详细缓冲区缓存信息,从而更有效地诊断和管理数据库系统。

Aurora PostgreSQL Limitless Database 中的 pgstattuple 差异

在 Aurora PostgreSQL 中,pgstattuple 扩展目前不支持外部表、分区表或分区索引。但是,在 Aurora PostgreSQL Limitless Database 中,用户创建的对象通常属于这些不受支持的类型。虽然有常规表和索引(例如,目录表及其索引),但大多数对象都驻留在外部节点上,这使得它们成为路由器的外部对象。

我们认识到此扩展对于获取元组级统计数据的重要性,这对于消除膨胀和收集诊断信息等任务至关重要。因此,Aurora PostgreSQL Limitless Database 为无限数据库中的 pgstattuple 扩展提供了支持。

Aurora PostgreSQL Limitless Database 在 rds_aurora 架构中包含以下函数:

元组级统计函数

rds_aurora.limitless_pgstattuple(relation_name)

  • 用途:提取标准表及其索引的元组级统计数据

  • 输入:relation_name(文本)– 关系的名称

  • 输出:与 Aurora PostgreSQL 中 pgstattuple 函数返回的列一致

rds_aurora.limitless_pgstattuple(relation_name, subcluster_id)

  • 用途:提取引用表、分片表、目录表及其索引的元组级统计数据

  • 输入:

    • relation_name(文本)– 关系的名称

    • subcluster_id(文本)– 要提取统计数据的节点的子集群 ID

  • 输出:

    • 对于引用表和目录表(包括其索引),列与 Aurora PostgreSQL 中的列一致。

    • 对于分片表,统计数据仅表示位于指定子集群上的分片表的分区。

索引统计函数

rds_aurora.limitless_pgstatindex(relation_name)

  • 用途:提取标准表上的 B 树索引的统计数据

  • 输入:relation_name(文本)– B 树索引的名称

  • 输出:返回除 root_block_no 外的所有列。返回的列与 Aurora PostgreSQL 中的 pgstatindex 函数一致

rds_aurora.limitless_pgstatindex(relation_name, subcluster_id)

  • 用途:提取引用表、分片表和目录表的 B 树索引的统计数据。

  • 输入:

    • relation_name(文本)– B 树索引的名称

    • subcluster_id(文本)– 要提取统计数据的节点的子集群 ID

  • 输出:

    • 对于引用表和目录表索引,将返回所有列(除 root_block_no 外)。返回的列与 Aurora PostgreSQL 一致

    • 对于分片表,统计数据仅表示位于指定子集群上的分片表索引的分区。tree_level 列显示请求的子集群上所有表切片的平均值。

rds_aurora.limitless_pgstatginindex(relation_name)

  • 用途:提取标准表上通用倒排索引(GIN)的统计数据

  • 输入:relation_name(文本)– GIN 的名称

  • 输出:与 Aurora PostgreSQL 中 pgstatginindex 函数返回的列一致

rds_aurora.limitless_pgstatginindex(relation_name, subcluster_id)

  • 用途:提取引用表、分片表和目录表的 GIN 索引的统计数据。

  • 输入:

    • relation_name(文本)– 索引的名称

    • subcluster_id(文本)– 要提取统计数据的节点的子集群 ID

  • 输出:

    • 对于引用表和目录表 GIN 索引,列与 Aurora PostgreSQL 中的列一致。

    • 对于分片表,统计数据仅表示位于指定子集群上的分片表索引的分区。

rds_aurora.limitless_pgstathashindex(relation_name)

  • 用途:提取标准表上的哈希索引的统计数据

  • 输入:relation_name(文本)– 哈希索引的名称

  • 输出:与 Aurora PostgreSQL 中 pgstathashindex 函数返回的列一致

rds_aurora.limitless_pgstathashindex(relation_name, subcluster_id)

  • 用途:提取引用表、分片表和目录表的哈希索引的统计数据。

  • 输入:

    • relation_name(文本)– 索引的名称

    • subcluster_id(文本)– 要提取统计数据的节点的子集群 ID

  • 输出:

    • 对于引用表和目录表哈希索引,列与 Aurora PostgreSQL 一致。

    • 对于分片表,统计数据仅表示位于指定子集群上的分片表索引的分区。

页面计数函数

rds_aurora.limitless_pg_relpages(relation_name)

  • 用途:提取标准表及其索引的页面计数

  • 输入:relation_name(文本)– 关系的名称

  • 输出:指定关系的页面计数

rds_aurora.limitless_pg_relpages(relation_name, subcluster_id)

  • 用途:提取引用表、分片表和目录表(包括其索引)的页面计数

  • 输入:

    • relation_name(文本)– 关系的名称

    • subcluster_id(文本)– 要提取页面计数的节点的子集群 ID

  • 输出:对于分片表,页面计数是指定子集群上所有表切片的页面总和。

近似元组级统计函数

rds_aurora.limitless_pgstattuple_approx(relation_name)

  • 用途:提取标准表及其索引的近似元组级统计数据

  • 输入:relation_name(文本)– 关系的名称

  • 输出:与 Aurora PostgreSQL 中 pgstattuple_approx 函数返回的列一致

rds_aurora.limitless_pgstattuple_approx(relation_name, subcluster_id)

  • 用途:提取引用表、分片表和目录表(包括其索引)的近似元组级统计数据

  • 输入:

    • relation_name(文本)– 关系的名称

    • subcluster_id(文本)– 要提取统计数据的节点的子集群 ID

  • 输出:

    • 对于引用表和目录表(包括其索引),列与 Aurora PostgreSQL 中的列一致。

    • 对于分片表,统计数据仅表示位于指定子集群上的分片表的分区。

注意

目前,Aurora PostgreSQL Limitless Database 不支持实体化视图、TOAST 表或临时表上的 pgstattuple 扩展。

尽管 Aurora PostgreSQL 支持其他格式,但在 Aurora PostgreSQL Limitless Database 中,您必须以文本形式提供输入。

外键

支持外键 (FOREIGN KEY) 约束,但有一些限制:

  • 带 FOREIGN KEY 的 CREATE TABLE 仅支持标准表。要使用 FOREIGN KEY 创建分片表或引用表,请先创建不带外键约束的表。然后使用以下语句对其进行修改:

    ALTER TABLE ADD CONSTRAINT;
  • 当表具有外键约束时,不支持将标准表转换为分片表或引用表。删除约束,在转换后再添加。

  • 以下限制适用于外键约束的表类型:

    • 标准表可以对另一个标准表有外键约束。

    • 如果父表和子表并置且外键是分片键的超集,则分片表可能具有外键约束。

    • 分片表可以对引用表有外键约束。

    • 引用表可以对另一个引用表有外键约束。

外键选项

Aurora PostgreSQL Limitless Database 支持某些 DDL 选项的外键。下表列出了 Aurora PostgreSQL Limitless Database 表之间支持和不支持的选项。

DDL 选项 引用到引用 分片到分片(并置) 分片到引用 标准到标准

DEFERRABLE

支持 是 是 是

INITIALLY DEFERRED

是 是 是 是

INITIALLY IMMEDIATE

是 是 是 是

MATCH FULL

是 是 是 是

MATCH PARTIAL

否 否 否 否

MATCH SIMPLE

是 是 是 是

NOT DEFERRABLE

是 是 是 是

NOT VALID

是 否 否 是

ON DELETE CASCADE

是 是 是 是

ON DELETE NO ACTION

是 是 是 是

ON DELETE RESTRICT

是 是 是 是

ON DELETE SET DEFAULT

否 否 否 否

ON DELETE SET NULL

是 否 否 是

ON UPDATE CASCADE

否 否 否 是

ON UPDATE NO ACTION

是 是 是 是

ON UPDATE RESTRICT

是 是 是 是

ON UPDATE SET DEFAULT

否 否 否 否

ON UPDATE SET NULL

是 否 否 是

示例

  • 标准到标准:

    set rds_aurora.limitless_create_table_mode='standard'; CREATE TABLE products( product_no integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer REFERENCES products (product_no), quantity integer ); SELECT constraint_name, table_name, constraint_type FROM information_schema.table_constraints WHERE constraint_type='FOREIGN KEY'; constraint_name | table_name | constraint_type -------------------------+-------------+----------------- orders_product_no_fkey | orders | FOREIGN KEY (1 row)
  • 分片到分片(并置)

    set rds_aurora.limitless_create_table_mode='sharded'; set rds_aurora.limitless_create_table_shard_key='{"product_no"}'; CREATE TABLE products( product_no integer PRIMARY KEY, name text, price numeric ); set rds_aurora.limitless_create_table_shard_key='{"order_id"}'; set rds_aurora.limitless_create_table_collocate_with='products'; CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer, quantity integer ); ALTER TABLE orders ADD CONSTRAINT order_product_fk FOREIGN KEY (product_no) REFERENCES products (product_no);
  • 分片到引用:

    set rds_aurora.limitless_create_table_mode='reference'; CREATE TABLE products( product_no integer PRIMARY KEY, name text, price numeric ); set rds_aurora.limitless_create_table_mode='sharded'; set rds_aurora.limitless_create_table_shard_key='{"order_id"}'; CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer, quantity integer ); ALTER TABLE orders ADD CONSTRAINT order_product_fk FOREIGN KEY (product_no) REFERENCES products (product_no);
  • 引用到引用:

    set rds_aurora.limitless_create_table_mode='reference'; CREATE TABLE products( product_no integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer, quantity integer ); ALTER TABLE orders ADD CONSTRAINT order_product_fk FOREIGN KEY (product_no) REFERENCES products (product_no);

函数

Aurora PostgreSQL Limitless Database 支持函数。

函数支持以下 DDL:

CREATE FUNCTION

您可以像在 Aurora PostgreSQL 中那样创建函数,但无法在替换函数时改变其波动性。

有关更多信息,请参阅 PostgreSQL 文档中的 CREATE FUNCTION。

ALTER FUNCTION

您可以像在 Aurora PostgreSQL 中那样更改函数,但无法改变其波动性。

有关更多信息,请参阅 PostgreSQL 文档中的 ALTER FUNCTION。

DROP FUNCTION

您可以像在 Aurora PostgreSQL 中那样删除函数。

DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] [ CASCADE | RESTRICT ]

有关更多信息,请参阅 PostgreSQL 文档中的 DROP FUNCTION。

函数分布

当一个函数的所有语句都针对单个分片时,将整个函数向下推送到目标分片是有益的。然后将结果传播回路由器,无需在路由器上展开该函数。函数和存储过程下推功能对于想要在离数据源(即分片)更近的地方运行其函数或存储过程的客户非常有用。

要分发函数,请先创建该函数,然后调用 rds_aurora.limitless_distribute_function 流程进行分发。该函数使用以下语法:

SELECT rds_aurora.limitless_distribute_function('function_prototype', ARRAY['shard_key'], 'collocating_table');

函数需要以下参数:

  • function_prototype – 要分发的函数。仅提及输入参数,不提及任何输出参数。

    如果有任何参数被定义为 OUT 参数,则不要将其类型包含在 function_prototype 的参数中。

  • ARRAY['shard_key'] – 标识为函数分片键的函数参数列表。

  • collocating_table – 包含目标分片上数据范围的分片表。

为了确定在哪个分片推送该函数以运行,系统会获取 ARRAY['shard_key'] 参数,对其进行哈希处理,然后从 collocating_table 中找到托管包含该哈希值范围的分片。

限制

当您分发函数或流程时,它只处理受该分片中分片键范围限制的数据。如果函数或流程尝试访问来自其他分片的数据,则分布式函数或流程返回的结果与非分布式函数或流程返回的结果会有所不同。

例如,您创建了一个包含查询的函数,这些查询将触及多个分片,随后调用 rds_aurora.limitless_distribute_function 流程进行分发。当您通过为分片键提供参数来调用此函数时,运行该函数的结果很可能会受该分片中存在的值的限制。这些结果不同于在不分配函数的情况下生成的结果。

示例

请查看以下函数 func,其有一个带有分片键 customer_id 的分片表 customers。

postgres_limitless=> CREATE OR REPLACE FUNCTION func(c_id integer, sc integer) RETURNS int language SQL volatile AS $$ UPDATE customers SET score = sc WHERE customer_id = c_id RETURNING score; $$;

现在我们分发这个函数:

SELECT rds_aurora.limitless_distribute_function('func(integer, integer)', ARRAY['c_id'], 'customers');

以下是查询计划示例。

EXPLAIN(costs false, verbose true) SELECT func(27+1,10); QUERY PLAN -------------------------------------------------- Foreign Scan Output: (func((27 + 1), 10)) Remote SQL: SELECT func((27 + 1), 10) AS func Single Shard Optimized (4 rows)
EXPLAIN(costs false, verbose true) SELECT * FROM customers,func(customer_id, score) WHERE customer_id=10 AND score=27; QUERY PLAN --------------------------------------------------------------------- Foreign Scan Output: customer_id, name, score, func Remote SQL: SELECT customers.customer_id, customers.name, customers.score, func.func FROM public.customers, LATERAL func(customers.customer_id, customers.score) func(func) WHERE ((customers.customer_id = 10) AND (customers.score = 27)) Single Shard Optimized (10 rows)

以下示例演示一个以 IN 和 OUT 参数作为参数的存储过程。

CREATE OR REPLACE FUNCTION get_data(OUT id INTEGER, IN arg_id INT) AS $$ BEGIN SELECT customer_id, INTO id FROM customer WHERE customer_id = arg_id; END; $$ LANGUAGE plpgsql;

以下示例仅使用 IN 参数来分发该流程。

EXPLAIN(costs false, verbose true) SELECT * FROM get_data(1); QUERY PLAN ----------------------------------- Foreign Scan Output: id Remote SQL: SELECT customer_id FROM get_data(1) get_data(id) Single Shard Optimized (6 rows)

函数波动性

您可以通过检查 pg_proc 视图中的 provolatile 值来确定函数是不可变、稳定还是波动的。provolatile 值表示函数的结果是仅取决于其输入参数,还是受外部因素的影响。

此类值可以是以下任一项:

  • i – 不可变函数,它们始终为相同的输入提供相同的结果

  • s – 稳定函数,其结果(对于固定输入)在扫描中不会改变

  • v – 波动函数,其结果可能随时发生变化。对于有副作用的函数,也要使用 v,这样对它们的调用就不会被优化掉。

以下示例显示了波动函数。

SELECT proname, provolatile FROM pg_proc WHERE proname='pg_sleep'; proname | provolatile ----------+------------- pg_sleep | v (1 row) SELECT proname, provolatile FROM pg_proc WHERE proname='uuid_generate_v4'; proname | provolatile ------------------+------------- uuid_generate_v4 | v (1 row) SELECT proname, provolatile FROM pg_proc WHERE proname='nextval'; proname | provolatile ---------+------------- nextval | v (1 row)

Aurora PostgreSQL Limitless Database 不支持更改现有函数的波动性。这适用于 ALTER FUNCTION 和 CREATE OR REPLACE FUNCTION 命令,如以下示例所示。

-- Create an immutable function CREATE FUNCTION immutable_func1(name text) RETURNS text language plpgsql AS $$ BEGIN RETURN name; END; $$IMMUTABLE; -- Altering the volatility throws an error ALTER FUNCTION immutable_func1 STABLE; -- Replacing the function with altered volatility throws an error CREATE OR REPLACE FUNCTION immutable_func1(name text) RETURNS text language plpgsql AS $$ BEGIN RETURN name; END; $$VOLATILE;

我们强烈建议您为函数分配正确的波动性。例如,如果您的函数使用来自多个表或引用数据库对象的 SELECT,请不要将其设置为 IMMUTABLE。如果表内容发生变化,则不变性就会被打破。

Aurora PostgreSQL 允许在不可变函数内进行 SELECT,但结果可能不正确。Aurora PostgreSQL Limitless Database 可能同时返回错误和错误结果。有关函数波动性的更多信息,请参阅 PostgreSQL 文档中的 Function volatility categories。

序列

命名序列是按升序或降序生成唯一数字的数据库对象。CREATE SEQUENCE 创建新的序列号生成器。序列值保证具有唯一性。

当您在 Aurora PostgreSQL Limitless Database 中创建命名序列时,会创建一个分布式序列对象。然后,Aurora PostgreSQL Limitless Database 在所有分布式事务路由器(路由器)上分发不重叠的序列值块。区块在路由器上以本地序列对象的形式表示;因此,序列操作(如 nextval 和 currval)是在本地运行的。路由器独立运行,并在需要时从分布式序列中请求新的区块。

有关序列的更多信息,请参阅 PostgreSQL 文档中的 CREATE SEQUENCE。

请求新区块

您可以使用 rds_aurora.limitless_sequence_chunk_size 参数配置在路由器上分配的区块的大小。默认值为 250000。每台路由器最初拥有两个区块:活动区块和保留区块。活动区块用于配置本地序列对象(设置 minvalue 和 maxvalue),保留区块存储在内部目录表中。当活动区块达到最小值或最大值时,它会被保留区块所取代。为此,内部使用了 ALTER SEQUENCE,意味着获取了 AccessExclusiveLock。

后台工作程序每隔 10 秒在路由器节点上运行一次,以扫描序列中是否有已使用的保留区块。如果找到了使用过的区块,则工作程序会从分布式序列中请求一个新的区块。确保将区块大小设置得足够大,以便后台工作人员有足够的时间请求新的区块。远程请求永远不会发生在用户会话的上下文中,这意味着您不能直接请求新的序列。

限制

以下限制适用于 Aurora PostgreSQL Limitless Database 中的序列:

  • pg_sequence 目录、pg_sequences 函数和 SELECT * FROM sequence_name 语句都只显示局部序列状态,而不显示分布式状态。

  • 序列值保证是唯一的,并且保证在会话中是单调的。但是,如果这些会话连接到其他路由器,它们可能会与其他会话中运行的 nextval 语句不一致。

  • 确保序列大小(可用值的数量)足够大,以便分布在所有路由器上。使用 rds_aurora.limitless_sequence_chunk_size 参数配置 chunk_size。(每台路由器都有两个区块。)

  • 支持 CACHE 选项,但缓存必须小于 chunk_size。

不支持的选项

Aurora PostgreSQL Limitless Database 中的序列不支持以下选项。

序列操作函数

不支持 setval 函数。有关更多信息,请参阅 PostgreSQL 文档中的 Sequence Manipulation Functions。

CREATE SEQUENCE

不支持以下选项。

CREATE [{ TEMPORARY | TEMP} | UNLOGGED] SEQUENCE [[ NO ] CYCLE]

有关更多信息,请参阅 PostgreSQL 文档中的 CREATE SEQUENCE。

ALTER SEQUENCE

不支持以下选项。

ALTER SEQUENCE [[ NO ] CYCLE]

有关更多信息,请参阅 PostgreSQL 文档中的 ALTER SEQUENCE。

ALTER TABLE

序列不支持 ALTER TABLE 命令。

示例

CREATE/DROP SEQUENCE
postgres_limitless=> CREATE SEQUENCE s; CREATE SEQUENCE postgres_limitless=> SELECT nextval('s'); nextval --------- 1 (1 row) postgres_limitless=> SELECT * FROM pg_sequence WHERE seqrelid='s'::regclass; seqrelid | seqtypid | seqstart | seqincrement | seqmax | seqmin | seqcache | seqcycle ----------+----------+----------+--------------+--------+--------+----------+---------- 16960 | 20 | 1 | 1 | 10000 | 1 | 1 | f (1 row) % connect to another router postgres_limitless=> SELECT nextval('s'); nextval --------- 10001 (1 row) postgres_limitless=> SELECT * FROM pg_sequence WHERE seqrelid='s'::regclass; seqrelid | seqtypid | seqstart | seqincrement | seqmax | seqmin | seqcache | seqcycle ----------+----------+----------+--------------+--------+--------+----------+---------- 16959 | 20 | 10001 | 1 | 20000 | 10001 | 1 | f (1 row) postgres_limitless=> DROP SEQUENCE s; DROP SEQUENCE
ALTER SEQUENCE
postgres_limitless=> CREATE SEQUENCE s; CREATE SEQUENCE postgres_limitless=> ALTER SEQUENCE s RESTART 500; ALTER SEQUENCE postgres_limitless=> SELECT nextval('s'); nextval --------- 500 (1 row) postgres_limitless=> SELECT currval('s'); currval --------- 500 (1 row)
序列操作函数
postgres=# CREATE TABLE t(a bigint primary key, b bigint); CREATE TABLE postgres=# CREATE SEQUENCE s minvalue 0 START 0; CREATE SEQUENCE postgres=# INSERT INTO t VALUES (nextval('s'), currval('s')); INSERT 0 1 postgres=# INSERT INTO t VALUES (nextval('s'), currval('s')); INSERT 0 1 postgres=# SELECT * FROM t; a | b ---+--- 0 | 0 1 | 1 (2 rows) postgres=# ALTER SEQUENCE s RESTART 10000; ALTER SEQUENCE postgres=# INSERT INTO t VALUES (nextval('s'), currval('s')); INSERT 0 1 postgres=# SELECT * FROM t; a | b -------+------- 0 | 0 1 | 1 10000 | 10000 (3 rows)

顺序视图

Aurora PostgreSQL Limitless Database 为序列提供以下视图。

rds_aurora.limitless_distributed_sequence

此视图显示分布式序列状态和配置。minvalue、maxvalue、start、inc 和 cache 列的含义与 pg_sequences 视图中的含义相同,它们显示了创建序列时使用的选项。lastval 列显示分布式序列对象中最新的分配值或保留值。这并不意味着该值已被使用,因为路由器会在本地保留序列区块。

postgres_limitless=> SELECT * FROM rds_aurora.limitless_distributed_sequence WHERE sequence_name='test_serial_b_seq'; schema_name | sequence_name | lastval | minvalue | maxvalue | start | inc | cache -------------+-------------------+---------+----------+------------+-------+-----+------- public | test_serial_b_seq | 1250000 | 1 | 2147483647 | 1 | 1 | 1 (1 row)
rds_aurora.limitless_sequence_metadata

此视图显示分布式序列元数据并聚合来自集群节点的序列元数据。它使用以下列:

  • subcluster_id – 拥有区块的集群节点 ID。

  • 活动区块 – 正在使用的序列区块 (active_minvalue、active_maxvalue)。

  • 保留区块 – 接下来将使用的本地区块 (reserved_minvalue、reserved_maxvalue)。

  • local_last_value – 本地序列中的最后观测值。

  • chunk_size – 区块的大小,如创建时所配置。

postgres_limitless=> SELECT * FROM rds_aurora.limitless_sequence_metadata WHERE sequence_name='test_serial_b_seq' order by subcluster_id; subcluster_id | sequence_name | schema_name | active_minvalue | active_maxvalue | reserved_minvalue | reserved_maxvalue | chunk_size | chunk_state | local_last_value ---------------+-------------------+-------------+-----------------+-----------------+-------------------+-------------------+------------+-------------+------------------ 1 | test_serial_b_seq | public | 500001 | 750000 | 1000001 | 1250000 | 250000 | 1 | 550010 2 | test_serial_b_seq | public | 250001 | 500000 | 750001 | 1000000 | 250000 | 1 | (2 rows)

对序列问题进行故障排除

序列可能会出现以下问题。

区块大小不够大

如果区块大小设置得不够大,并且事务速率很高,则在活动区块用完之前,后台工作人员可能没有足够的时间请求新的区块。这可能会导致争用和等待事件,例如 LIMITLESS:AuroraLimitlessSequenceReplace、LWLock:LockManager、Lockrelation 和 LWlock:bufferscontent。

增大 rds_aurora.limitless_sequence_chunk_size 参数的值。

序列缓存设置过高

在 PostgreSQL 中,序列缓存发生在会话级别。在一次访问序列对象期间,每个会话都会分配连续的序列值,并相应地增加序列对象的 last_value 值。然后,在该会话中下次使用 nextval 时,只需返回预先分配的值,而无需涉及序列对象。

会话结束时,任何分配但未在会话中使用的数字都将丢失,从而导致序列中出现“空洞”。这可能会快速消耗 sequence_chunk,并导致争用和等待事件,例如 LIMITLESS:AuroraLimitlessSequenceReplace、LWLock:LockManager、Lockrelation 和 LWlock:bufferscontent。

减少序列缓存设置。

下图显示了由序列问题引起的等待事件。

由序列问题引起的等待事件。