

 从补丁 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/)。

# EXPLAIN
<a name="r_EXPLAIN"></a>

显示查询语句的执行计划，而不运行查询。有关查询分析工作流程的信息，请参阅[查询分析工作流程](c-query-analysis-process.md)。

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

```
EXPLAIN [ VERBOSE ] query
```

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

VERBOSE   
显示完整的查询计划，而不只是摘要。

 *query*   
要解释的查询语句。查询可以是 SELECT、INSERT、CREATE TABLE AS、UPDATE 或 DELETE 语句。

## 使用说明
<a name="r_EXPLAIN-usage-notes"></a>

在创建临时表时需要花费一定的时间，因此 EXPLAIN 性能有时会受到影响。例如，使用公共子表达式优化的查询需要创建和分析临时表，以返回 EXPLAIN 输出。查询计划依赖于临时表的 schema 和统计数据。因此，此类查询的 EXPLAIN 命令的运行时间可能会超过预期。

您只能对以下命令使用 EXPLAIN：
+ SELECT
+ SELECT INTO
+ CREATE TABLE AS
+ INSERT
+ UPDATE
+ DELETE

如果您对其他 SQL 命令（例如数据定义语言 (DDL) 或数据库操作）使用 EXPLAIN 命令，则该命令将失败。

Amazon Redshift 使用 EXPLAIN 输出相对单位成本来选择查询计划。Amazon Redshift 会比较各种资源估算值的大小来确定计划。

## 查询计划和执行步骤
<a name="r_EXPLAIN-query-planning-and-execution-steps"></a>

特定 Amazon Redshift 查询语句的执行计划会将查询的执行和计算细分为一系列单独的步骤和表操作，它们最后为该查询生成一个最终结果集。有关查询计划的信息，请参阅[查询处理](c-query-processing.md)。

下表提供了步骤的汇总，Amazon Redshift 可以针对用户提交供执行的任何查询，使用这些步骤来制定执行计划。


<table>
<thead>
  <tr><th>EXPLAIN 运算符 </th><th>查询执行步骤 </th><th>描述 </th></tr>
</thead>
<tbody>
  <tr><td colspan="3">SCAN：</td></tr>
  <tr><td> 顺序扫描 </td><td>scan </td><td>Amazon Redshift 关系扫描或表扫描运算符或步骤。从头开始按顺序扫描整个表直至结尾；另外，如果在 WHERE 子句中指定它，则还会评估每一行的查询约束（筛选条件）。它还用于运行 INSERT、UPDATE 和 DELETE 语句。</td></tr>
  <tr><td colspan="3">JOINS：Amazon Redshift 根据要联接的表的物理设计、联接所需的数据位置以及查询本身的特定属性，来使用不同的联接运算符。子查询扫描 – 使用子查询扫描和附加来运行 UNION 查询。</td></tr>
  <tr><td>嵌套循环 </td><td>nloop </td><td>优化程度最差的联接；主要用于交叉联接（笛卡尔积；没有联接条件）和一些不等式联接。</td></tr>
  <tr><td>哈希联接 </td><td>hjoin </td><td>还用于内部联接以及左和右外部联接，速度通常比嵌套循环联接要快。哈希联接读取外部表，对联接列进行哈希处理，然后在内部哈希表查找匹配项。步骤会溢到磁盘。（hjoin 的内部输入是可基于磁盘的哈希步骤。） </td></tr>
  <tr><td>合并联接 </td><td>mjoin </td><td>还用于内部联接和外部联接（用于在联接列上进行分配和排序的联接表）。在不考虑其他成本的情况下，通常这是最快的 Amazon Redshift 联接算法。</td></tr>
  <tr><td colspan="3">AGGREGATION：用于涉及聚合函数以及 GROUP BY 操作的查询的运算符和步骤。</td></tr>
  <tr><td>聚合 </td><td>aggr </td><td>标量聚合函数的运算符/步骤。</td></tr>
  <tr><td>HashAggregate </td><td>aggr </td><td>分组聚合函数的运算符/步骤。可利用哈希表溢到磁盘的优势来从磁盘运行。</td></tr>
  <tr><td>GroupAggregate </td><td>aggr </td><td>有时，force\_hash\_grouping 设置的 Amazon Redshift 配置设置为 off，此时为分组聚合查询选择该运算符。</td></tr>
  <tr><td colspan="3">SORT：在查询必须对结果集进行排序或合并时使用的运算符和步骤。</td></tr>
  <tr><td>排序 </td><td>sort </td><td>排序操作执行 ORDER BY 子句指定的排序，此外还执行其他一些操作，例如 UNION 和联接。可从磁盘运行。</td></tr>
  <tr><td>合并 </td><td>merge </td><td>根据从并行执行的操作得到的临时排序结果，来生成某个查询的最终排序结果。</td></tr>
  <tr><td colspan="3">EXCEPT、INTERSECT 和 UNION 操作：</td></tr>
  <tr><td>SetOp Except [Distinct] </td><td>hjoin </td><td>用于 EXCEPT 查询。可利用输入哈希可基于磁盘的优势来从磁盘运行。</td></tr>
  <tr><td>Hash Intersect [Distinct] </td><td>hjoin </td><td>用于 INTERSECT 查询。可利用输入哈希可基于磁盘的优势来从磁盘运行。</td></tr>
  <tr><td>Append [All \|Distinct] </td><td>save </td><td>附加操作与子查询扫描结合使用，来实施 UNION 和 UNION ALL 查询。可利用“save”操作的优势来从磁盘运行。</td></tr>
  <tr><td colspan="3">杂项/其他：</td></tr>
  <tr><td>哈希 </td><td>hash </td><td>用于内部联接以及左和右外部联接（为哈希联接提供输入）。Hash 运算符为联接运算的内部表创建哈希表。（内部表是用来检查匹配项的表；在联接两个表时，通常是其中较小的那个表。） </td></tr>
  <tr><td>限制 </td><td>limit </td><td>评估 LIMIT 子句。</td></tr>
  <tr><td>具体化 </td><td>save </td><td>具体化嵌套循环联接和某些合并联接的输入中的行。可从磁盘运行。</td></tr>
  <tr><td>-- </td><td>parse </td><td>用于在加载期间解析文字输入数据。</td></tr>
  <tr><td>-- </td><td>project </td><td>用于重新整理列和计算表达式，即项目数据。</td></tr>
  <tr><td>结果 </td><td>-- </td><td>运行不涉及任何表访问的标量函数。</td></tr>
  <tr><td>-- </td><td>return </td><td>将行返回到领导节点或客户端。</td></tr>
  <tr><td>子计划 </td><td>-- </td><td>用于特定的子查询。</td></tr>
  <tr><td>唯一 </td><td>unique </td><td>消除 SELECT DISTINCT 和 UNION 查询中的重复项。</td></tr>
  <tr><td>窗口 </td><td>window </td><td>计算汇总并对窗口函数进行排名。可从磁盘运行。</td></tr>
  <tr><td colspan="3">网络操作：</td></tr>
  <tr><td>网络（广播） </td><td>bcast </td><td>广播也是 Join Explain 运算符和步骤的一个属性。</td></tr>
  <tr><td>网络（分布） </td><td>dist </td><td>将行分布到计算节点，以便由数据仓库集群执行并行处理。</td></tr>
  <tr><td>网络（发送到领导节点） </td><td>return </td><td>将结果发送回领导节点，以待进一步处理。</td></tr>
  <tr><td colspan="3">DML 操作（用于修改数据的运算符）：</td></tr>
  <tr><td>插入（使用结果） </td><td>insert </td><td>插入数据。</td></tr>
  <tr><td>删除（扫描 \+ 筛选） </td><td>delete </td><td>删除数据。可从磁盘运行。</td></tr>
  <tr><td>更新（扫描 \+ 筛选） </td><td>delete、insert </td><td>以删除和插入的方式实施。</td></tr>
</tbody>
</table>


## 将 EXPLAIN 用于 RLS
<a name="r_EXPLAIN-RLS"></a>

如果查询包含受行级别安全性 (RLS) 策略约束的表，则 EXPLAIN 将显示一个特殊的 RLS SecureScan 节点。Amazon Redshift 还会将相同的节点类型记录到 STL\_EXPLAIN 系统表中。EXPLAIN 不会显示应用于 dim\_tbl 的 RLS 谓词。RLS SecureScan 节点类型用作执行计划包含当前用户不可见的其他操作的指示器。

以下示例说明了 RLS SecureScan 节点。

```
EXPLAIN
SELECT D.cint
FROM fact_tbl F INNER JOIN dim_tbl D ON F.k_dim = D.k
WHERE F.k_dim / 10 > 0;
                               QUERY PLAN
------------------------------------------------------------------------
 XN Hash Join DS_DIST_ALL_NONE  (cost=0.08..0.25 rows=1 width=4)
   Hash Cond: ("outer".k_dim = "inner"."k")
   ->  *XN* *RLS SecureScan f  (cost=0.00..0.14 rows=2 width=4)*
         Filter: ((k_dim / 10) > 0)
   ->  XN Hash  (cost=0.07..0.07 rows=2 width=8)
         ->  XN Seq Scan on dim_tbl d  (cost=0.00..0.07 rows=2 width=8)
               Filter: (("k" / 10) > 0)
```

为了能够对受 RLS 约束的查询计划进行全面调查，Amazon Redshift 提供了 EXPLAIN RLS 系统权限。被授予此权限的用户可以检查还包含 RLS 谓词的完整查询计划。

以下示例说明了 RLS SecureScan 节点下方的额外顺序扫描，该顺序扫描还包括 RLS 策略谓词 (k\_dim > 1)。

```
EXPLAIN SELECT D.cint
FROM fact_tbl F INNER JOIN dim_tbl D ON F.k_dim = D.k
WHERE F.k_dim / 10 > 0;
                                   QUERY PLAN
---------------------------------------------------------------------------------
 XN Hash Join DS_DIST_ALL_NONE  (cost=0.08..0.25 rows=1 width=4)
   Hash Cond: ("outer".k_dim = "inner"."k")
   *->  XN RLS SecureScan f  (cost=0.00..0.14 rows=2 width=4)
         Filter: ((k_dim / 10) > 0)*
         ->  *XN* *Seq Scan on fact_tbl rls_table  (cost=0.00..0.06 rows=5 width=8)
               Filter: (k_dim > 1)*
   ->  XN Hash  (cost=0.07..0.07 rows=2 width=8)
         ->  XN Seq Scan on dim_tbl d  (cost=0.00..0.07 rows=2 width=8)
               Filter: (("k" / 10) > 0)
```

在向用户授予 EXPLAIN RLS 权限的同时，Amazon Redshift 会在 STL\_EXPLAIN 系统表中记录包括 RLS 谓词在内的完整查询计划。在未授予此权限时运行的查询将在没有 RLS 内部构件的情况下被记录。授予或删除 EXPLAIN RLS 权限不会改变 Amazon Redshift 为之前的查询记录到 STL\_EXPLAIN 的内容。

### 受 AWS Lake Formation-RLS 保护的 Redshift 关系
<a name="r_EXPLAIN_RLS-LF"></a>

以下示例说明了 LF SecureScan 节点，您可以使用它来查看 Lake Formation-RLS 关系。

```
EXPLAIN
SELECT *
FROM lf_db.public.t_share
WHERE a > 1;
QUERY PLAN
---------------------------------------------------------------
XN LF SecureScan t_share  (cost=0.00..0.02 rows=2 width=11)
(2 rows)
```

## 示例
<a name="r_EXPLAIN-examples"></a>

**注意**  
对于这些示例，输出样本可能有所不同，具体取决于 Amazon Redshift 配置。

以下示例为从 EVENT 和 VENUE 表中选择 EVENTID、EVENTNAME、VENUEID 和 VENUENAME 的查询返回查询计划：

```
explain
select eventid, eventname, event.venueid, venuename
from event, venue
where event.venueid = venue.venueid;
```

```
                                QUERY PLAN
--------------------------------------------------------------------------
XN Hash Join DS_DIST_OUTER  (cost=2.52..58653620.93 rows=8712 width=43)
Hash Cond: ("outer".venueid = "inner".venueid)
->  XN Seq Scan on event  (cost=0.00..87.98 rows=8798 width=23)
->  XN Hash  (cost=2.02..2.02 rows=202 width=22)
->  XN Seq Scan on venue  (cost=0.00..2.02 rows=202 width=22)
(5 rows)
```

以下示例使用详细输出为同一查询返回查询计划：

```
explain verbose
select eventid, eventname, event.venueid, venuename
from event, venue
where event.venueid = venue.venueid;
```

```
                                QUERY PLAN
--------------------------------------------------------------------------
{HASHJOIN
:startup_cost 2.52
:total_cost 58653620.93
:plan_rows 8712
:plan_width 43
:best_pathkeys <>
:dist_info DS_DIST_OUTER
:dist_info.dist_keys (
TARGETENTRY
{
VAR
:varno 2
:varattno 1
...

XN Hash Join DS_DIST_OUTER  (cost=2.52..58653620.93 rows=8712 width=43)
Hash Cond: ("outer".venueid = "inner".venueid)
->  XN Seq Scan on event  (cost=0.00..87.98 rows=8798 width=23)
->  XN Hash  (cost=2.02..2.02 rows=202 width=22)
->  XN Seq Scan on venue  (cost=0.00..2.02 rows=202 width=22)
(519 rows)
```

以下示例返回 CREATE TABLE AS (CTAS) 语句的查询计划：

```
explain create table venue_nonulls as
select * from venue
where venueseats is not null;

QUERY PLAN
-----------------------------------------------------------
XN Seq Scan on venue  (cost=0.00..2.02 rows=187 width=45)
Filter: (venueseats IS NOT NULL)
(2 rows)
```