

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# CREATE TABLE AS
<a name="r_CREATE_TABLE_AS"></a>

**Topics**
+ [语法](#r_CREATE_TABLE_AS-synopsis)
+ [参数](#r_CREATE_TABLE_AS-parameters)
+ [CTAS 使用说明](r_CTAS_usage_notes.md)
+ [CTAS 示例](r_CTAS_examples.md)

创建基于查询的新表。此表的所有者为发出命令的用户。

新表与命令的查询定义的数据一起加载。表列具有与查询的输出列关联的名称和数据类型。CREATE TABLE AS (CTAS) 命令创建一个新表并评估查询以加载新表。

## 语法
<a name="r_CREATE_TABLE_AS-synopsis"></a>

```
CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ]
TABLE table_name
[ ( column_name [, ... ] ) ]
[ BACKUP { YES | NO } ]
[ table_attributes ]
AS query

where table_attributes are:
[ DISTSTYLE { AUTO | EVEN | ALL | KEY } ]
[ DISTKEY( distkey_identifier ) ]
[ [ COMPOUND | INTERLEAVED ] SORTKEY( column_name [, ...] ) ]
```

## 参数
<a name="r_CREATE_TABLE_AS-parameters"></a>

LOCAL   
虽然语句中接受此可选关键词，但它在 Amazon Redshift 中没有任何作用。

TEMPORARY \$1 TEMP   
创建一个临时表。在创建临时表的会话结束时将自动删除该临时表。

 *table\$1name*   
要创建的表的名称。  
如果指定以“\$1”开始的表名，表会创建为临时表。例如：  

```
create table #newtable (id) as select * from oldtable;
```
表名称的最大长度为 127 个字节；更长的名称将被截断为 127 个字节。Amazon Redshift 会按节点类型强制执行每个集群的表数量配额。可使用数据库和 schema 名称限定表名，如下表所示。  

```
create table tickit.public.test (c1) as select * from oldtable;
```
在此示例中，`tickit` 为数据库名称，`public` 为 schema 名称。如果数据库或 schema 不存在，此语句将返回错误。  
如果提供 schema 名称，则在该 schema 中创建新表（假定创建者有权访问 schema）。表名称必须是该 schema 中的唯一名称。如果未指定 schema，则可使用当前数据库 schema 创建表。如果您创建的是临时表，则无法指定 schema 名称，因为特定 schema 中存在临时表。  
如果多个同名临时表是在单独的会话中创建的，则这些同名临时表能够同时存在于同一个数据库中。这些表将分配给不同的 schemas。

 *column\$1name*   
新表中的列的名称。如果没有提供列名，则采用查询的输出列名中的列名。默认列名用于表达式。有关有效名称的更多信息，请参阅[名称和标识符](r_names.md)。

BACKUP \$1 YES \$1 NO \$1   
一个子句，指定表是否应包含在自动和手动集群快照中。  
对于不会包含关键数据的表（如暂存表），请指定 BACKUP NO 以节省在创建快照并从快照还原时的处理时间，从而减小在 Amazon Simple Storage Service 上占用的存储空间。BACKUP NO 设置不会影响数据到集群内的其他节点的自动复制，因此当发生节点故障时，指定了 BACKUP NO 的表将被还原。默认值为 BACKUP YES。  
RA3 预调配集群和 Amazon Redshift Serverless 工作组不支持无备份表。在 RA3 集群和 Serverless 工作组中标记为无备份的表将被视为永久表，在拍摄快照时将始终对其进行备份，并在从快照还原时还原该表。要避免无备份表产生快照成本，请在拍摄快照之前将其截断。

DISTSTYLE \$1 AUTO \$1 EVEN \$1 KEY \$1 ALL \$1  
定义整个表的数据分配样式的关键词。Amazon Redshift 会根据为表指定的分配样式将表行分配给计算节点。默认值为 DISTSTYLE AUTO。  
为表选择的分配样式将影响数据库的整体性能。有关更多信息，请参阅 [用于优化查询的数据分配](t_Distributing_data.md)。  
+ AUTO：Amazon Redshift 可基于表数据指定最佳分配方式。要查看应用于表的分配方式，请查询 PG\$1CLASS 系统目录表。有关更多信息，请参阅 [查看分配方式](viewing-distribution-styles.md)。
+ EVEN：表中的数据在轮询分配中跨集群中的节点均匀分布。行 ID 用来确定分配，并且为每个节点分配的行数大致相同。这是默认分配方法。
+ KEY：按 DISTKEY 列中的值分配数据。在您将联接表的联接列设置为分配键时，来自这两个表的联接行将在计算节点上并置。在并置数据时，优化程序可更高效地执行联接。如果您指定 DISTSTYLE KEY，则必须命名 DISTKEY 列。
+  ALL：向每个节点分配整个表的副本。此分配样式可确保任何联接所需的所有行在每个节点上都可用，但这将使存储要求成倍提高，并且会增加表的加载和维护次数。将 ALL 分配样式用于 KEY 分配不适用的部分维度表时会缩短执行时间，但必须针对维护成本来权衡性能改进。

DISTKEY (*column*)  
指定分配键的列名或位置号。使用在表的可选列列表或所选查询列表中指定的名称。或者，使用位置号，其中所选的第一列为 1，所选的第二列为 2，以此类推。一个表中只能有一个列可成为分配键：  
+ 如果将一个列声明为 DISTKEY 列，则必须将 DISTSTYLE 设置为 KEY 或者根本不设置 DISTSTYLE。
+ 如果未声明 DISTKEY 列，则可将 DISTSTYLE 设置为 EVEN。
+ 如果您不指定 DISTKEY 或 DISTSTYLE，CTAS 会根据 SELECT 子句的查询计划确定新表的分配样式。有关更多信息，请参阅 [继承列和表属性](r_CTAS_usage_notes.md#r_CTAS_usage_notes-inheritance-of-column-and-table-attributes)。
您可以将同一个列定义为分配键和排序键；此方法旨在当有问题的列为查询中的联接列时加速联接。

[ COMPOUND \$1 INTERLEAVED ] SORTKEY ( *column\$1name* [, ... ] )  
为表指定一个或多个排序键。在数据加载到表中后，将按指定为排序键的列对数据进行排序。  
您可以选择指定 COMPOUND 或 INTERLEAVED 排序样式。默认为 COMPOUND。有关更多信息，请参阅 [排序键](t_Sorting_data.md)。  
最多可以为每个表定义 400 个 COMPOUND SORTKEY 列或 8 个 INTERLEAVED SORTKEY 列。  
如果您不指定 SORTKEY，CTAS 会根据 SELECT 子句的查询计划的新表排序键。有关更多信息，请参阅 [继承列和表属性](r_CTAS_usage_notes.md#r_CTAS_usage_notes-inheritance-of-column-and-table-attributes)。    
COMPOUND  
指定使用由所有列出的列构成的复合键按这些列的列出顺序对数据进行排序。当查询根据排序列的顺序扫描行时，复合排序键最有用。当查询依赖辅助排序列时，使用复合键进行排序所带来的性能好处会减少。您最多可以为每个表定义 400 个 COMPOUND SORTKEY 列。  
INTERLEAVED  
指定使用交错排序键对数据进行排序。可以为一个交错排序键最多指定 8 个列。  
交错排序为排序键中的每个列或列子集提供了相同的权重，以便查询不会依赖列在排序键中的顺序。当查询使用一个或多个辅助排序列时，交错排序会大大提高查询性能。交错排序产生的数据加载和 vacuum 操作的开销成本较低。

AS *query*   
Amazon Redshift 支持的任何查询（SELECT 语句）。

# CTAS 使用说明
<a name="r_CTAS_usage_notes"></a>

## 限制
<a name="r_CTAS_usage_notes-limits"></a>

Amazon Redshift 会按节点类型强制执行每个集群的表数量配额。

表名的最大字符数为 127。

可在单个表中定义的列的最大数目为 1,600。

## 继承列和表属性
<a name="r_CTAS_usage_notes-inheritance-of-column-and-table-attributes"></a>

CREATE TABLE AS (CTAS) 表不从其父表继承约束、身份列、默认列值或主键。

您不能为 CTAS 表指定列压缩编码。Amazon Redshift 自动分配压缩编码，如下所示：
+ 为定义为排序键的列分配 RAW 压缩。
+ 定义为 BOOLEAN、REAL、DOUBLE PRECISION、GEOMETRY 或 GEOGRAPHY 数据类型的列分配了 RAW 压缩。
+ 定义为 SMALLINT、INTEGER、BIGINT、DECIMAL、DATE、TIME、TIMETZ、TIMESTAMP 或 TIMESTAMPTZ 的列分配了 AZ64 压缩。
+ 定义为 CHAR、VARCHAR 或 VARBYTE 的列分配了 LZO 压缩。

有关更多信息，请参阅[压缩编码](c_Compression_encodings.md)和[数据类型](c_Supported_data_types.md)。

要显式分配列编码，请使用 [CREATE TABLE](r_CREATE_TABLE_NEW.md)。

CTAS 根据 SELECT 子句的查询计划确定新表的分配样式和排序键。

对于复杂查询，如包含连接、聚合、ORDER BY 子句或 LIMIT 子句，CTAS 会尽最大努力基于查询计划选择最佳分配样式和分类键。

**注意**  
对于使用大型数据集或复杂查询实现最佳性能，我们建议使用典型数据集进行测试。

通常，您可以通过检查查询计划查看查询优化器选择哪些列（如果有）进行数据排序和分配，预测 CTAS 将选择哪个分配键和分类键。如果查询计划的顶端节点为一个表（XN 顺序扫描）的简单顺序扫描，则 CTAS 通常使用源表的分配样式和分类键。如果查询计划的顶部节点是除顺序扫描外的任何情况（如 XN 限制、XN 排序、XN HashAggregate 等），CTAS 会尽最大努力根据查询计划选择最佳分配样式和分类键。

例如，假设您使用 SELECT 子句创建了以下五个表：
+ 简单的 SELECT 语句 
+ Limit 子句 
+ 使用 LISTID 的 ORDER BY 子句 
+ 使用 QTYSOLD 的 ORDER BY 子句 
+ 使用 GROUP BY 子句的 SUM 聚合函数。

以下示例显示每个 CTAS 语句的查询计划。

```
explain create table sales1_simple as select listid, dateid, qtysold from sales;
                           QUERY PLAN
----------------------------------------------------------------
 XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=8)
(1 row)


explain create table sales2_limit as select listid, dateid, qtysold from sales limit 100;
                              QUERY PLAN
----------------------------------------------------------------------
 XN Limit  (cost=0.00..1.00 rows=100 width=8)
   ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=8)
(2 rows)


explain create table sales3_orderbylistid as select listid, dateid, qtysold from sales order by listid;
                               QUERY PLAN
------------------------------------------------------------------------
 XN Sort  (cost=1000000016724.67..1000000017155.81 rows=172456 width=8)
   Sort Key: listid
   ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=8)
(3 rows)


explain create table sales4_orderbyqty as select listid, dateid, qtysold from sales order by qtysold;
                               QUERY PLAN
------------------------------------------------------------------------
 XN Sort  (cost=1000000016724.67..1000000017155.81 rows=172456 width=8)
   Sort Key: qtysold
   ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=8)
(3 rows)


explain create table sales5_groupby as select listid, dateid, sum(qtysold) from sales group by listid, dateid;
                              QUERY PLAN
----------------------------------------------------------------------
 XN HashAggregate  (cost=3017.98..3226.75 rows=83509 width=8)
   ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=8)
(2 rows)
```

要查看每个表的分配键和分类键，请查询 PG\$1TABLE\$1DEF 系统目录表，如下所示。

```
select * from pg_table_def where tablename like 'sales%';

      tablename       |   column   | distkey | sortkey
----------------------+------------+---------+---------
 sales                | salesid    | f       |       0
 sales                | listid     | t       |       0
 sales                | sellerid   | f       |       0
 sales                | buyerid    | f       |       0
 sales                | eventid    | f       |       0
 sales                | dateid     | f       |       1
 sales                | qtysold    | f       |       0
 sales                | pricepaid  | f       |       0
 sales                | commission | f       |       0
 sales                | saletime   | f       |       0
 sales1_simple        | listid     | t       |       0
 sales1_simple        | dateid     | f       |       1
 sales1_simple        | qtysold    | f       |       0
 sales2_limit         | listid     | f       |       0
 sales2_limit         | dateid     | f       |       0
 sales2_limit         | qtysold    | f       |       0
 sales3_orderbylistid | listid     | t       |       1
 sales3_orderbylistid | dateid     | f       |       0
 sales3_orderbylistid | qtysold    | f       |       0
 sales4_orderbyqty    | listid     | t       |       0
 sales4_orderbyqty    | dateid     | f       |       0
 sales4_orderbyqty    | qtysold    | f       |       1
 sales5_groupby       | listid     | f       |       0
 sales5_groupby       | dateid     | f       |       0
 sales5_groupby       | sum        | f       |       0
```

下表汇总了结果。为简便起见，我们在说明计划中忽略了成本、行和宽度详细信息。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/redshift/latest/dg/r_CTAS_usage_notes.html)

您可以在 CTAS 语句中明确指定分配样式和分类键。例如，下面的语句使用 EVEN 分配创建了一个表并指定 SALESID 作为分类键。

```
create table sales_disteven
diststyle even
sortkey (salesid)
as
select eventid, venueid, dateid, eventname
from event;
```

## 压缩编码
<a name="r_CTAS_usage_notes_encoding"></a>

ENCODE AUTO 用作表的默认设置。Amazon Redshift 会自动管理表中所有列的压缩编码。

## 分配传入数据
<a name="r_CTAS_usage_notes-distribution-of-incoming-data"></a>

如果传入数据的哈希分配方案与目标表的哈希分配方案匹配，则在加载数据时，没有实际必要的数据物理分配。例如，如果为新表设置分配键并从相同键列上分配的另一个表中插入数据，则使用相同的节点和切片就地加载数据。不过，如果源表和目标表都设置为 EVEN 分配，则数据将重新分配到目标表。

## 自动 ANALYZE 操作
<a name="r_CTAS_usage_notes-automatic-analyze-operations"></a>

Amazon Redshift 自动分析您使用 CTAS 命令创建的表。在最初创建这些表时，您不需要对这些表运行 ANALYZE 命令。如果修改了这些表，则应通过用来分析其他表的方式来分析这些表。

# CTAS 示例
<a name="r_CTAS_examples"></a>

以下示例为 EVENT 表创建名为 EVENT\$1BACKUP 的表：

```
create table event_backup as select * from event;
```

生成的表继承 EVENT 表中的分配键和排序键。

```
select "column", type, encoding, distkey, sortkey
from pg_table_def where tablename = 'event_backup';

column    | type                        | encoding | distkey | sortkey
----------+-----------------------------+----------+---------+--------
catid     | smallint                    | none     | false   |       0
dateid    | smallint                    | none     | false   |       1
eventid   | integer                     | none     | true    |       0
eventname | character varying(200)      | none     | false   |       0
starttime | timestamp without time zone | none     | false   |       0
venueid   | smallint                    | none     | false   |       0
```

以下命令通过选择 EVENT 表中的四个列来创建一个名为 EVENTDISTSORT 的新表。新表按 EVENTID 进行分配并按 EVENTID 和 DATEID 进行排序：

```
create table eventdistsort
distkey (1)
sortkey (1,3)
as
select eventid, venueid, dateid, eventname
from event;
```

结果如下：

```
select "column", type, encoding, distkey, sortkey
from pg_table_def where tablename = 'eventdistsort';

column   |          type          | encoding | distkey | sortkey
---------+------------------------+----------+---------+-------
eventid   | integer               | none     | t       | 1
venueid   | smallint              | none     | f       | 0
dateid    | smallint              | none     | f       | 2
eventname | character varying(200)| none     | f       | 0
```

可通过对分配键和排序键使用列名来创建完全相同的表。例如：

```
create table eventdistsort1
distkey (eventid)
sortkey (eventid, dateid)
as
select eventid, venueid, dateid, eventname
from event;
```

以下语句对表应用 EVEN 分配，但不定义明确的排序键。

```
create table eventdisteven
diststyle even
as
select eventid, venueid, dateid, eventname
from event;
```

该表不继承 EVENT 表 (EVENTID) 中的排序键，因为已为新表指定 EVEN 分配。新表没有排序键和分配键。

```
select "column", type, encoding, distkey, sortkey
from pg_table_def where tablename = 'eventdisteven';

column    |          type          | encoding | distkey | sortkey
----------+------------------------+----------+---------+---------
eventid   | integer                | none     | f       | 0
venueid   | smallint               | none     | f       | 0
dateid    | smallint               | none     | f       | 0
eventname | character varying(200) | none     | f       | 0
```

以下语句应用 EVEN 分配并定义排序键：

```
create table eventdistevensort diststyle even sortkey (venueid)
as select eventid, venueid, dateid, eventname from event;
```

 生成的表具有排序键，但不具有分配键。

```
select "column", type, encoding, distkey, sortkey
from pg_table_def where tablename = 'eventdistevensort';

column    |          type          | encoding | distkey | sortkey
----------+------------------------+----------+---------+-------
eventid   | integer                | none     | f       | 0
venueid   | smallint               | none     | f       | 1
dateid    | smallint               | none     | f       | 0
eventname | character varying(200) | none     | f       | 0
```

以下语句基于来自传入数据（基于 EVENTID 列进行排序）的其他键列重新分配 EVENT 表，但不定义 SORTKEY 列；因此，不会对表进行排序。

```
create table venuedistevent distkey(venueid)
as select * from event;
```

结果如下：

```
select "column", type, encoding, distkey, sortkey
from pg_table_def where tablename = 'venuedistevent';

 column   |            type             | encoding | distkey | sortkey
----------+-----------------------------+----------+---------+-------
eventid   | integer                     | none     | f       | 0
venueid   | smallint                    | none     | t       | 0
catid     | smallint                    | none     | f       | 0
dateid    | smallint                    | none     | f       | 0
eventname | character varying(200)      | none     | f       | 0
starttime | timestamp without time zone | none     | f       | 0
```