Amazon Redshift
数据库开发人员指南 (API Version 2012-12-01)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

DECLARE

定义新游标。使用游标从大型查询的结果集中一次性检索几个行。

在提取游标的第一行时,会在领导节点上、内存中或磁盘上具体化整个结果集(如果需要)。由于将游标用于大型结果集可能会降低性能,因此建议使用备用方法(如果可能)。有关更多信息,请参阅 使用游标时的性能注意事项

您必须在事务块中声明游标。对于每个会话,一次只能打开一个游标。

有关更多信息,请参阅 FETCHCLOSE

语法

Copy
DECLARE cursor_name CURSOR FOR query

参数

cursor_name

新游标的名称。

query

填充游标的 SELECT 语句。

DECLARE CURSOR 使用说明

如果您的客户端应用程序使用 ODBC 连接,并且您的查询创建的结果集太大,无法存储到内存中,则可使用光标将结果集流式传输到客户端应用程序。在使用游标时,会在领导节点上具体化整个结果集,随后您的客户端可按递增方式提取结果。

注意

要在 ODBC for Microsoft Windows 中启用游标,请在用于 Amazon Redshift 的 ODBC DSN 中启用 Use Declare/Fetch 选项。建议使用 ODBC DSN 选项对话框中的 Cache Size 字段将多节点集群中的 ODBC 缓存大小设置为 4000 或更大值,以最大程度地减少往返操作。在单节点集群上,将缓存大小设置为 1000。

由于使用游标可能会对性能产生负面影响,我们建议您尽可能地使用替代方法。有关更多信息,请参阅 使用游标时的性能注意事项

支持 Amazon Redshift 游标,但存在以下限制:

  • 对于每个会话,一次只能打开一个游标。

  • 游标必须在事务内部使用 (BEGIN … END)。

  • 所有游标的累计最大结果集大小受到集群节点类型的限制。如果您需要更大的结果集,可以调整为 XL 和 8XL 节点配置。

    有关更多信息,请参阅 游标约束

游标约束

在提取游标的第一行时,会在领导节点上具体化整个结果集。如果结果集无法存储到内存中,则会根据需要写入磁盘。为了保护领导节点的完整性,Amazon Redshift 会根据集群节点类型对所有游标结果集的大小强制实施约束。

下表显示每个集群节点类型的最大结果集总大小。最大结果集大小以 MB 为单位。

节点类型 每个集群的最大结果集大小 (MB)

DS1 或 DS2 XL 单节点

64000

DS1 或 DS2 XL 多节点

1800000

DS1 或 DS2 8XL 多节点

14400000

DC1 大型单节点

16000

DC1 大型多节点

384000

DC1 8XL 多节点

3000000

要查看某个集群的活动游标配置,请以超级用户身份查询 STV_CURSOR_CONFIGURATION 系统表。要查看活动光标的状态,请查询 STV_ACTIVE_CURSORS 系统表。用户只能看到自己游标所对应的行,而超级用户可以查看所有游标。

使用游标时的性能注意事项

由于在开始将结果返回给客户端之前,游标会在领导节点上具体化整个结果集,因此对超大型结果集使用游标时,会对性能产生负面影响。我们强烈建议不要对超大型结果集使用游标。在一些情况下,例如您的应用程序使用 ODBC 连接时,游标可能是唯一可行的解决方案。我们建议尽可能地利用下面这些备选方案:

  • 使用 UNLOAD 导出大型表。在使用 UNLOAD 时,计算节点将并行工作,从而将数据直接发送到 Amazon Simple Storage Service 上的数据文件。有关更多信息,请参阅 卸载数据

  • 在您的客户端应用程序中设置 JDBC 提取大小参数。如果您使用 JDBC 连接,并且遇到客户端内存不足错误,则可以通过设置 JDBC 提取大小参数,让您的客户端按较小的批次检索结果集。有关更多信息,请参阅 设置 JDBC 提取大小参数

DECLARE CURSOR 示例

以下示例声明一个名为 LOLLAPALOOZA 的游标,以便为 Lollapalooza 事件选择销售信息,然后使用该游标从结果集中提取行:

Copy
-- Begin a transaction begin; -- Declare a cursor declare lollapalooza cursor for select eventname, starttime, pricepaid/qtysold as costperticket, qtysold from sales, event where sales.eventid = event.eventid and eventname='Lollapalooza'; -- Fetch the first 5 rows in the cursor lollapalooza: fetch forward 5 from lollapalooza; eventname | starttime | costperticket | qtysold --------------+---------------------+---------------+--------- Lollapalooza | 2008-05-01 19:00:00 | 92.00000000 | 3 Lollapalooza | 2008-11-15 15:00:00 | 222.00000000 | 2 Lollapalooza | 2008-04-17 15:00:00 | 239.00000000 | 3 Lollapalooza | 2008-04-17 15:00:00 | 239.00000000 | 4 Lollapalooza | 2008-04-17 15:00:00 | 239.00000000 | 1 (5 rows) -- Fetch the next row: fetch next from lollapalooza; eventname | starttime | costperticket | qtysold --------------+---------------------+---------------+--------- Lollapalooza | 2008-10-06 14:00:00 | 114.00000000 | 2 -- Close the cursor and end the transaction: close lollapalooza; commit;