亚马逊AWS官方博客

使用 Amazon Redshift 通过配额机制监控及控制 schema 存储空间

Original URL:https://aws.amazon.com/cn/blogs/big-data/monitor-and-control-the-storage-space-of-a-schema-with-quotas-with-amazon-redshift/

Yelp的使命,是将人们与当地的优秀企业联系起来。自2004年成立以来,Yelp已经从仅为总部所在地旧金山提供服务,发展成为一家覆盖30多个国家/地区大都市区域的跨国企业。凭借着基于高效广告与交易的商业模式,该公司在2015年获得超过5亿美元收入,较上一年增长了46%。Yelp已经发展成为一家以移动设备为中心的公司,其搜索量占比超过70%,来自移动端的内容占比亦超过58%。

Yelp公司使用Amazon Redshift分析移动应用的使用情况与客户群组数据,并据此整理广告竞拍与宣传指标。而随着Amazon Redshift全新schema存储配额功能的推出,Yelp公司的业务也得到显著收益。

Yelp公司Metrics平台(这套平台专门为Yelp工程技术团队提供长期持久数据存储与SQL查询功能)首席工程师Steven Moy表示,“Amazon Redshift是一项托管数据仓库服务,帮助Yelp专注于数据分析本身,而无需耗费时间管理数据库运营。我们在数据仓库用户快速迭代中采取的一项关键策略,就是建立起一种名为「tmp」的可写Schema,供用户对各种表模式进行原型设计。但有时候,我们也会面临查询执行过程中没有足够可用空间所带来的挑战,这会严重影响到整体数据仓库查询操作的性能。借助新的schema配额功能,我们可以在「tmp」架构上设置存储配额上限,借此保护存储失控问题。我们也期待将Amazon Redshift提供的所有自治功能陆续引入Yelp业务体系。”

目前,越来越多的组织开始转向自助服务分析,即由不同的职能角色针对持续变化的数据量、类型与速度建立起自己的见解,借此跟上业务的快速发展步伐。这种数据大众化趋势的全面实现,又对数据治理、成本控制以及数据管理能力提出了更高的要求。在这一领域,控制不同职能角色的存储配额,已经成为数据治理与数据存储操作中的重大挑战。在本文中,我们将展示如何通过不同的角色设置Amazon Redshift存储配额。

先决条件

在开始本轮演练之前,大家需要满足以下先决条件:

  • 拥有一套Amazon Redshift集群。这里推荐使用美国东部(北弗吉尼亚)区域,因为我们需要从 us-east-1中的Amazon Simple Storage Service(Amazon S3)中加载数据。
  • 一个拥有超级用户权限的数据库用户。

设置并测试schema配额

要配置环境并测试用例,我们需要完成以下操作步骤:

  • 使用您的首选客户端,以超级用户或者具备CREATE SCHEMA权限的用户身份接入Amazon Redshift集群。
  • 使用以下代码创建sales用户:
    CREATE USER sales WITH password 'Abcd1234!';

以上代码中的用户仅用于本演练目的。大家应该在AWS身份与访问管理(AWS Identity and Access Management,简称IAM)中使用身份联动机制使用企业用户,而非像本示例中这样手动创建新用户。关于更多详细信息,请参阅身份验证说明

  • 使用CREATE SCHEMA设置一项schema配额。详见以下操作代码:
    CREATE SCHEMA [ IF NOT EXISTS ] schema_name [ AUTHORIZATION username ] 
               [ QUOTA {quota [MB | GB | TB] | UNLIMITED} ] [ schema_element [ ... ] 
     
    CREATE SCHEMA AUTHORIZATION username[ QUOTA {quota [MB | GB | TB] | UNLIMITED} ] [ schema_element [ ... ] ]

其中的QUOTA参数用于定义schema所能使用的最大磁盘空间量。

  • 创建schema sales_schema,并为sales用户指定2 GB配额。详见以下操作代码:
    CREATE SCHEMA sales_schema AUTHORIZATION sales QUOTA 2 GB; 
  • 使用以下代码模拟sales用户:
    SET SESSION AUTHORIZATION 'sales';
    SELECT CURRENT_USER;
  • 使用以下代码创建表regionlineitem
    CREATE TABLE sales_schema.region (
      r_regionkey int4,
      r_name char(25),
      r_comment varchar(152)                            
    ) DISTSTYLE EVEN;
     
    CREATE TABLE sales_schema.lineitem (
      l_orderkey int8,
      l_partkey int8,
      l_suppkey int4,
      l_linenumber int4,
      l_quantity numeric(12,2),
      l_extendedprice numeric(12,2),
      l_discount numeric(12,2),
      l_tax numeric(12,2),
      l_returnflag char(1),
      l_linestatus char(1),
      l_shipdate date,
      l_commitdate date,
      l_receiptdate date,
      l_shipinstruct char(25),
      l_shipmode char(10),
      l_comment varchar(44)
    ) DISTSTYLE EVEN;

单语句事务

要对单语句事务用例进行测试,请完成以下操作步骤:

  • 使用以下代码将数据加载至region表中:
COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';

 <Your-IAM-Role> 代表的是您IAM角色的ARN,其中包含与Amazon Redshift集群相关的所有必要权限。

COPY命令应在加载五行之后完成,详见以下代码:

dev=> COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'region' completed, 5 record(s) loaded successfully.
COPY
  • 通过系统视图svv_schema_quota_state检查schema的配额与磁盘使用情况,详见以下代码:
    SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';

此语句应在演练中使用的四节点DC2.large集群之上显示2048 GB磁盘容量配额,当前使用量为30 MB。磁盘使用量会随实例类型与节点数量的不同而有所变化,具体请参阅以下代码:

dev=> SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';
 schema_name  | quota | disk_usage | disk_usage_pct 
--------------+-------+------------+----------------
 sales_schema |  2048 |         30 |           1.46
(1 row)
  • 使用以下代码将数据加载至表lineitem当中:
COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';

这时我们会收到一条错误消息,表示事务由于超出磁盘空间配额而中止。具体参见以下代码:

dev=> COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'lineitem' completed, 59986052 record(s) loaded successfully.
ERROR:  Transaction 40895 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 2048, Current Disk Usage: 2798).
Free up disk space or request increased quota for the schema(s).

在提交事务之前,Amazon Redshift会首先检查每项事务是否与配额定义相冲突。但配额冲突检查发生在事务末尾处,因此在提交之前,事务中的存储空间使用量可能会暂时超过配额。正因为如此,我们才会先看到已经成功加载表lineitem的提示消息。当事务超出配额时,Amazon Redshift会中止该事务、禁止后续加载并还原所有变更,直到释放出足够的磁盘空间为止。

配额冲突信息则被保存在系统表stl_schema_quota_violations当中。

  • 运行以下代码以查看冲突信息:
    SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;

这里应该显示出当前配额、磁盘使用量、超出已配置配额的磁盘使用率百分比以及发生冲突时的时间戳。具体请参阅以下代码:

dev=> SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;
 userid | schema_name  | quota | disk_usage | disk_usage_pct |         timestamp          
--------+--------------+-------+------------+----------------+----------------------------
    104 | sales_schema |  2048 |       2798 |         136.62 | 2020-04-20 20:09:25.494723
(1 row)
  • 使用ALTER SCHEMA将schema配额调整为4 GB。详见以下代码:
    RESET SESSION AUTHORIZATION; 
    ALTER SCHEMA sales_schema QUOTA 4 GB;
    SET SESSION AUTHORIZATION 'sales';
    SELECT CURRENT_USER;

您必须使用数据库超级用户或者是具有CREATE SCHEMA权限的用户,才能在schema创建期间为其设置资源配额。而要在schema运行中调整配额,您必须使用数据库超级用户。我们可以使用RESET SESSION AUTHORIZATION将用户模拟重新设置为原始超级用户。

  • 使用以下代码检查schema中的配额与磁盘使用情况:
    SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';

该语句应在我们的四节点DC2.large集群上返回4096 MB配额与30 MB磁盘使用量。当原始表上有事务被中止时,失败的COPY语句会提前自动回收相应的磁盘空间,具体请参见以下代码:

dev=> SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';
 schema_name  | quota | disk_usage | disk_usage_pct 
--------------+-------+------------+----------------
 sales_schema |  4096 |         30 |           0.73
(1 row)
  • 使用以下代码,重新运行COPY命令以将数据加载至表lineitem当中:
    COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';

上述代码应返回以下提示消息:

Load into table 'lineitem' completed, 59986052 record(s) loaded successfully
  • 使用以下代码,检查schema中的配额与磁盘使用量:
SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';

此语句应在四节点DC2.large集群上返回4096 MB配额与2798 MB磁盘使用量。具体使用量会随实例类型与节点数量的不同而有所变化。具体请参见以下代码:

dev=> SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';
 schema_name  | quota | disk_usage | disk_usage_pct 
--------------+-------+------------+----------------
 sales_schema |  4096 |       2798 |          68.31
(1 row)
  • 重新运行COPY命令向表lineitem当中加载大量数据,并使加载量超出配额。具体参见以下代码:
    COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';

此时应返回错误,提示由于超出磁盘空间配额而导致事务中止。详见以下代码:

dev=# COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'lineitem' completed, 59986052 record(s) loaded successfully.
ERROR:  Transaction 86438 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 4096, Current Disk Usage: 5486).
Free up disk space or request increased quota for the schema(s).
  • 执行以下代码,在引发配额冲突后执行后续小型COPY/INSERT/UPDATE操作:
    COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
    INSERT INTO sales_schema.region VALUES(100, 'Test','This is a test');
    UPDATE sales_schema.region SET r_name = 'Fail' WHERE r_regionkey = 100;

所有语句都应返回错误,理由是事务由于超出磁盘空间配额而中止。具体参见以下代码:

dev=# COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'region' completed, 5 record(s) loaded successfully.
ERROR:  Transaction 86478 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 4096, Current Disk Usage: 5486).
Free up disk space or request increased quota for the schema(s).
dev=# INSERT INTO sales_schema.region VALUES(100, 'Test','This is a test');
ERROR:  Transaction 86479 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 4096, Current Disk Usage: 5486).
Free up disk space or request increased quota for the schema(s).
dev=# UPDATE sales_schema.region SET r_name = 'Fail' WHERE r_regionkey = 100;
ERROR:  Transaction 86483 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 4096, Current Disk Usage: 5486).
Free up disk space or request increased quota for the schema(s).

对于非原始表,尽管超出配额的冲突事务已经被中止(例如指向lineitem表的COPY命令),但该事务仍会占用空间并导致目标schema被阻塞,直到磁盘空间被正常回收为止。正因为如此,后续对region表执行的COPY/INSERT/UPDATE才会被一条条中止。

  • 使用以下代码对系统表中的配额冲突进行再次检查:
    SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;

对于四节点DC2.large集群,返回的结果应该为5486 MB磁盘使用量,具体参见以下代码:

dev=> SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;
 userid | schema_name  | quota | disk_usage | disk_usage_pct |         timestamp          
--------+--------------+-------+------------+----------------+----------------------------
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 21:27:29.653489
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 21:27:29.469287
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 21:27:29.197434
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 20:28:01.344333
    104 | sales_schema |  2048 |       2798 |         136.62 | 2020-04-20 20:09:25.494723
(5 rows)

单语句仅收缩(shrink-only)事务

仅收缩事务,是指仅由特定语句组成的事务,其中各语句有可能直接或间接减少系统中的磁盘空间使用量,例如: DELETE, TRUNCATE, DROP TABLE, VACUUM等等。

要测试单语句仅收缩事务用例,请完成以下操作步骤:

  • 使用以下代码从lineitem表中删除所有数据:
    DELETE sales_schema.lineitem;
    SELECT COUNT(*) FROM sales_schema.lineitem;

上述代码应返回一条计数为0的记录:

dev=> DELETE sales_schema.lineitem;
DELETE 59986052
dev=> SELECT COUNT(*) FROM sales_schema.lineitem;
 count 
-------
     0
(1 row)

尽管超出了schema配额,但由于仅收缩事务属于配额冲突检查中的例外情况,因此DELETE事务将得到正常提交。

相较于使用DELETE命令删除所有数据,TRUNCATE命令的执行效率更高且不需要配合VACUUM与ANALYZE命令。以上代码仅用于演示,不一定符合大家的实际使用情况。

  • 使用以下代码重新运行COPY命令,将数据加载至表lineitem当中:
    COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';

上述代码应返回以下错误消息:

Transaction is aborted due to exceeding the disk space quota

参见以下代码:

dev=> COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'lineitem' completed, 59986052 record(s) loaded successfully.
ERROR:  Transaction 87024 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 4096, Current Disk Usage: 8150).
Free up disk space or request increased quota for the schema(s).

由于DELETE不会自动释放磁盘空间,因此之前的COPY命令仍然超出配额限制,事务将被中止。

  • 使用以下代码再次对系统表进行配额冲突检查:
    SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;

最新行应该在四节点DC2.large集群上返回8150 MB磁盘空间使用量。这表明磁盘使用量随着事务中止而有所增加,具体参见以下代码:

dev=> SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;
 userid | schema_name  | quota | disk_usage | disk_usage_pct |         timestamp          
--------+--------------+-------+------------+----------------+----------------------------
    104 | sales_schema |  4096 |       8150 |         198.97 | 2020-04-20 21:30:54.354669
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 21:27:29.653489
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 21:27:29.469287
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 21:27:29.197434
    104 | sales_schema |  4096 |       5486 |         133.94 | 2020-04-20 20:28:01.344333
    104 | sales_schema |  2048 |       2798 |         136.62 | 2020-04-20 20:09:25.494723
(6 rows)
  • 运行VACUUM命令以释放磁盘空间:
    VACUUM sales_schema.lineitem;

虽然仍然超出schema配额,但由于Amazon Redshift会在某些情况下(例如使用VACUUM命令时)忽略配额冲突并提交事务,因此以上操作能够正常完成、不会引发任何错误。

Amazon Redshift现在会在后台自动运行VACUUM DELETE操作以回收磁盘空间。

  • 使用以下代码再次运行COPY命令,将数据加载至表 lineitem当中:
    COPY sales_schema.lineitem FROM 's3://redshift-downloads/TPC-H/10GB/lineitem/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';

上述代码应返回以下消息:

Load into table 'lineitem' completed, 59986052 record(s) loaded successfully

由于VACUUM回收了磁盘空间,因此COPY命令将得以成功运行。

CREATE TABLE AS (CTAS)ALTER TABLE APPEND语句以及临时schema上的事务

要测试CREATE TABLE AS (CTAS)、ALTER TABLE APPEND语句以及临时schema上的事务,我们需要完成以下操作步骤:

  • 执行CTAS语句以通过查询创建一个新的表,详见以下代码:
    CREATE TABLE sales_schema.lineitem_ctas AS SELECT * FROM sales_schema.lineitem;

上述代码应返回事务中止提示消息,理由是超出磁盘空间配额。CTAS将在同一schema中接受类似的配额检查,详见以下代码:

dev=> CREATE TABLE sales_schema.lineitem_ctas AS SELECT * FROM sales_schema.lineitem;
ERROR:  Transaction 112229 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 4096, Current Disk Usage: 5624).
Free up disk space or request increased quota for the schema(s).
  • 使用以下代码创建一个临时表并进行数据填充:
    CREATE TEMP TABLE lineitem_temp AS SELECT * FROM sales_schema.lineitem;
    SELECT COUNT(*) from lineitem_temp; 

上述代码应返回5998万6052行。这一schema配额不会将临时表创建为临时命名空间或者schema中的组成部分。

  • 使用以下代码在public schema中创建相同的lineitem表,并向其中加载数据:
    CREATE TABLE public.lineitem_ctas AS SELECT * FROM sales_schema.lineitem;
    SELECT COUNT(*) FROM lineitem_ctas;

上述代码应返回5998万6052行。

面向其他不同schema的加载数据Sale_Schema的配额不起作用,事务得到正常提交。

  • 在另一表中使用 ALTER TABLE APPEND,将来自sales_schema的数据添加至lineitem表当中。具体参见以下代码:
    ALTER TABLE sales_schema.lineitem APPEND FROM lineitem_ctas;

上述代码应返回错误,提示由于超出磁盘空间配额而导致事务中止。配额冲突适用于整个schema。

  • 使用以下代码,在public schema当中将来自sales_schema lineitem表的数据添加至另一个表:
    ALTER TABLE lineitem_ctas APPEND FROM sales_schema.lineitem;
    SELECT COUNT(*) FROM sales_schema.lineitem;
    SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';

上述代码应从SELECT COUNT语句返回一条0计数记录,磁盘使用量也随之下降。ALTER TABLE APPEND语句会立即清空该表,并在事务完成之后回收磁盘空间。具体参见以下代码:

dev=> ALTER TABLE lineitem_ctas APPEND FROM sales_schema.lineitem;
INFO:  ALTER TABLE APPEND "lineitem_ctas" from "lineitem" is complete.
ALTER TABLE APPEND and COMMIT TRANSACTION
dev=> SELECT COUNT(*) FROM sales_schema.lineitem;
 count 
-------
     0
(1 row)
 
dev=> SELECT TRIM(SCHEMA_NAME) "schema_name", QUOTA, disk_usage, disk_usage_pct FROM svv_schema_quota_state WHERE SCHEMA_NAME = 'sales_schema';
 schema_name  | quota | disk_usage | disk_usage_pct 
--------------+-------+------------+----------------
 sales_schema |  4096 |         30 |           0.73
(1 row)

并发事务

要测试并发事务用例,请完成以下操作步骤:

  • 使用以下命令将配额提升至6 GB:
    RESET SESSION AUTHORIZATION;
    ALTER SCHEMA sales_schema QUOTA 6 GB;
    SET SESSION AUTHORIZATION 'sales';

我们需要两个接入Amazon Redshift集群的独立SQL客户端会话,且并发运行代码以完成以下测试。

  • 在第一个会话中,输入以下代码:
    CREATE TABLE sales_schema.lineitem_txn1 AS SELECT * FROM lineitem_ctas;
  • 在第一个会话保持运行的同时,在第二个会话中输入以下代码:
    CREATE TABLE sales_schema.lineitem_txn2 AS SELECT * FROM lineitem_ctas;

来自第一个会话的语句应返回以下警告消息:

Schema(s) close to reaching their allocated disk space quotas

这是一条警告消息,表明当前schema的资源使用量已经接近配额,但语句仍可正常完成。详见以下代码:

dev=> CREATE TABLE sales_schema.lineitem_txn1 AS SELECT * FROM lineitem_ctas;
WARNING:  Schema(s) close to reaching their allocated disk space quotas: (Schema: sales_schema, Quota: 6144, Current Disk Usage: 5606).
Free up disk space or request increased quota for the schema(s).
SELECT

来自第二个会话的语句应返回错误,表明由于超出磁盘空间配额,事务已经被中止。由于来自第一个会话的第一项事务被首先提交,所以此时磁盘空间使用量已经提升至接近配额上限的水平。第二项事务在事务提交之前会进行配额冲突检查,并最终导致事务中止。

将配额重置为低于当前磁盘空间使用量的水平

要在现有磁盘空间使用量之下测试配额重置功能,请完成以下操作步骤:

  • 运行以下命令,将配额重置为2 GB:
    RESET SESSION AUTHORIZATION;
    ALTER SCHEMA sales_schema QUOTA 2 GB;
    SET SESSION AUTHORIZATION 'sales';
    CREATE TABLE sales_schema.test AS SELECT 1;

我们可以将配额设置为低于当前磁盘空间使用量;但请注意,这会导致一切后续数据加载事务皆被中止,直至磁盘空间得到释放。具体参见以下代码:

dev=> RESET SESSION AUTHORIZATION;
RESET
dev=# ALTER SCHEMA sales_schema QUOTA 2 GB;
ALTER SCHEMA
dev=# SET SESSION AUTHORIZATION 'sales';
SET
dev=> CREATE TABLE sales_schema.test AS SELECT 1;
ERROR:  Transaction 112557 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 2048, Current Disk Usage: 5610).
Free up disk space or request increased quota for the schema(s).

多语句事务

要测试多语句事务用例,请完成以下操作步骤:

  • 输入以下代码以测试多语句事务:
    BEGIN;
    	DELETE FROM sales_schema.region WHERE r_regionkey = 0;
    	INSERT INTO sales_schema.region VALUES(100, 'Test','This is a test');
    COMMIT;
    BEGIN;
    	DELETE FROM sales_schema.region WHERE r_regionkey = 0;
    	UPDATE sales_schema.region SET r_name = 'Fail' WHERE r_regionkey = 1;
    COMMIT;
    BEGIN;
    	DELETE FROM sales_schema.region WHERE r_regionkey = 0;
    	COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
    COMMIT;

由于赶出配额上限,所有INSERT/UPDATE/COPY事务都应被中止。详见以下代码:

dev=> BEGIN;
BEGIN
dev=> DELETE FROM sales_schema.region WHERE r_regionkey = 0;
DELETE 0
dev=> INSERT INTO sales_schema.region VALUES(100, 'Test','This is a test');
INSERT 0 1
dev=> COMMIT;
ERROR:  Transaction 114291 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 2048, Current Disk Usage: 5606).
Free up disk space or request increased quota for the schema(s).
dev=> BEGIN;
BEGIN
dev=> DELETE FROM sales_schema.region WHERE r_regionkey = 0;
DELETE 0
dev=> UPDATE sales_schema.region SET r_name = 'Fail' WHERE r_regionkey = 1;
UPDATE 1
dev=> COMMIT;
ERROR:  Transaction 114295 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 2048, Current Disk Usage: 5606).
Free up disk space or request increased quota for the schema(s).
dev=> BEGIN;
BEGIN
dev=> DELETE FROM sales_schema.region WHERE r_regionkey = 0;
DELETE 0
dev=> COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'region' completed, 5 record(s) loaded successfully.
COPY
dev=> COMMIT;
ERROR:  Transaction 114303 is aborted due to exceeding the disk space quota in schema(s): (Schema: sales_schema, Quota: 2048, Current Disk Usage: 5624).
Free up disk space or request increased quota for the schema(s).
  • 输入以下代码,对同一事务上的DROP TABLE进行多语句事务测试:
    BEGIN;
    	INSERT INTO sales_schema.region VALUES(100, 'Test','This is a test');
    	UPDATE sales_schema.region SET r_name = 'Fail' WHERE r_regionkey = 100;
    	COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
    	DROP TABLE sales_schema.region;
    COMMIT;

事务应该可以成功提交。指向同一表的COPY/INSERT/DELETE事务将在事务成功提交的同时将该表删除。具体参见以下代码:

dev=> BEGIN;
BEGIN
dev=> INSERT INTO sales_schema.region VALUES(100, 'Test','This is a test');
INSERT 0 1
dev=> UPDATE sales_schema.region SET r_name = 'Fail' WHERE r_regionkey = 100;
UPDATE 3
dev=> COPY sales_schema.region FROM 's3://redshift-downloads/TPC-H/10GB/region/' iam_role '<Your-IAM-Role>' gzip delimiter '|' region 'us-east-1';
INFO:  Load into table 'region' completed, 5 record(s) loaded successfully.
COPY
dev=> DROP TABLE sales_schema.region;
DROP TABLE
dev=> COMMIT;
COMMIT
  • 使用以下代码,在多语句事务当中运行仅收缩语句:
    BEGIN;
    	DELETE FROM sales_schema.lineitem WHERE l_orderkey = 53924162;
    	DROP TABLE sales_schema.lineitem;
    COMMIT;

事务应可以成功提交。包含仅收缩语句的事务不会受到配额冲突问题的影响,具体参见以下代码:

dev=> BEGIN;
BEGIN
dev=> DELETE FROM sales_schema.lineitem WHERE l_orderkey = 53924162;
DELETE 0
dev=> DROP TABLE sales_schema.lineitem;
DROP TABLE
dev=> COMMIT;
COMMIT

最佳实践

以下建议,将帮助大家使用存储配额功能实现工作负载优化:

  • 当用户与schema相匹配时,schema功能效果最好——使用schema在逻辑层面进行用户隔离,例如为数据工程师分配面向基础表与聚合表的MAIN  schema,并为数据分析师分配可通过ANALYST  schema查询MAIN中基础数据、并通过存储配额实现存储功能的ANALYST  schema。其中数据分析师只对MAIN  schema拥有读取权限,但对ANALYST  schema同时拥有读取与写入权限。
  • 撤销public schema上的使用量——所有用户都默认在数据库的PUBLIC schema上拥有 CREATEUSAGE权限。由于存储配置在PUBLIC schema上并未默认启用,因此应禁止所有用户在数据库的PUBLIC schema中创建对象。相反,用户可以根据以往最佳实践使用自己的对应schema。我们可以使用REVOKE命令删除这些默认权限。
  • 使用物理表代替临时表——由于临时表不受存储配额的限制,因此请改用物理表。但请注意在事务完成时删除这些物理表。一种可行的替代方案是创建一套独立的专用schema,用于创建具有适当存储配额的临时物理表,借此全面取代临时表。这将简化管理流程,帮助大家定期自动清理此专用schema中的残余表。
  • 使用数据收缩操作——使用DELETEVACUUM DELETEDROP以及TRUNCATE等操作释放磁盘空间,特别是在磁盘空间使用量接近配额上限的情况下。
  • 使用工作负载管理(WLM)配合查询优先级控制不同用户的资源使用量——不同用户在执行数据摄取与聚合操作时可能会占用大量资源,并给集群上运行的其他关键任务负载或查询的吞吐能力造成影响。Amazon Redshift Advisor会自动分析当前WLM使用情况,并提出建议以提升当前集群的吞吐量水平。大家不妨定期查看Advisor建议以持续改进性能表现。

监控

大家应该定期监控是否存在存储配额冲突情况,进而采取纠正措施以提高业务连续性。系统表stl_schema_quota_violations是获取配额冲突事件的良好来源。要查询冲突信息,请输入以下代码:

SELECT userid, TRIM(SCHEMA_NAME) "schema_name", quota, disk_usage, disk_usage_pct, timestamp FROM stl_schema_quota_violations WHERE SCHEMA_NAME = 'sales_schema' ORDER BY timestamp DESC;

大家也可以使用以下解决方案自动执行上述查询,并保证在出现冲突事件时向用户发送通知:

资源清理

在测试工作完成之后,我们可以使用以下代码删除演练中的各对象及用户:

RESET SESSION AUTHORIZATION;
DROP TABLE IF EXISTS sales_schema.lineitem_txn1; 
DROP TABLE IF EXISTS lineitem_temp;
DROP TABLE IF EXISTS lineitem_ctas;
DROP SCHEMA sales_schema;
DROP USER IF EXISTS sales;

总结

Amazon Redshift支持严格的合规性与安全性要求,无需支付任何额外费用,这也使其成为高监管要求行业的理想业务支撑方案。具备配额机制的数据存储操作正是Amazon Redshift核心数据治理框架的组成部分,该框架为客户的合规性与运营效率带来可靠保障。凭借CREATE/ALTER SCHEMA语句中的一条简单QUOTA参数,我们即可启用Amazon Redshift schema上的磁盘配额功能。大家可以将代表组织中不同职能角色的Amazon Redshift数据库用户分配给包含对应配额的不同schema,借此控制他们可以使用的磁盘空间量。这种能力不仅对数据治理及成本控制而言至关重要,同时也能够避免磁盘已满等常见的操作错误,保证及时阻止一切可能导致其他关键数据分析任务陷入停滞的对象创建或摄取操作。

本文还向大家展示了如何轻松在Amazon Redshift schema当中控制存储配额。我们不仅完成了schema之上创建并变更配额,同时授权特定用户使用该schema的操作步骤,同时也探讨了如何将数据导入schema并通过系统视图在多种用例下监控事务结果及磁盘使用量。通过这项强大的功能,相信大家能够通过Amazon Redshift切实满足各类业务需求。

 

本篇作者

BP Yau

AWS公司数据仓库专业解决方案架构师。 他的职责是帮助客户构建起能够大规模处理数据的大数据解决方案。在加入AWS之前,他曾供职于Amazon.com供应链优化技术部门,负责将Oracle数据仓库迁移至Amazon Redshift,并使用AWS技术构建起下一代大数据分析平台。

Ahmad Barghout

Amazon Redshift存储团队软件开发工程师。他长期从事集群规模优化工作,目前主要从事schema配额等功能的易用性优化事务。在此之前,他曾在思科公司担任全栈开发者职务。他拥有渥太华大学硕士学位。

Himanshu Raja

Himanshu Raja 是 Amazon Redshift 的高级产品经理。Himanshu 喜欢解决数据难题,当数据与直觉相悖时,他爱不忍释。在业余时间,Himanshu 喜欢烹饪印度美食和观看动作电影。