DECLARE - Amazon Redshift

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

DECLARE

定義新的資料指標。使用資料指標可從完整查詢的結果集中一次擷取幾個資料列。

擷取資料指標的第一列時,整個結果集會在領導節點上、記憶體中或磁碟上具體化 (如有需要)。由於在大型結果集內使用資料指標可能會對效能造成負面影響,因此建議您盡量使用替代方式。如需詳細資訊,請參閱使用游標時的效能考量

您必須在交易區塊內宣告資料指標。每個工作階段中一次只能開啟一個資料指標。

如需詳細資訊,請參閱 FETCHCLOSE

語法

DECLARE cursor_name CURSOR FOR query

參數

cursor_name

新資料指標的名稱。

query

填入游標的SELECT陳述式。

DECLARE CURSOR 用量備註

如果您的用戶端應用程式使用ODBC連線,且查詢建立的結果集太大而無法容納記憶體,您可以使用游標將結果集串流至用戶端應用程式。當您使用資料指標時,整個結果集會在領導節點上具體化,然後您的用戶端就能以遞增方式擷取結果。

注意

若要ODBC在 Microsoft Windows 中啟用游標,請在ODBCDSN您用於 Amazon Redshift 的 中啟用 Use Declare/Fetch 選項。我們建議您使用ODBCDSN選項對話方塊中的快取大小欄位,在多節點叢集上將ODBC快取大小設定為 4,000 或更高,以將往返次數降至最低。在單一節點叢集上,將 Cache Size (快取大小) 設定為 1,000。

由於使用資料指標可能會對效能造成負面影響,因此建議您盡量使用替代方式。如需詳細資訊,請參閱使用游標時的效能考量

在滿足以下限制的情況下,可支援 Amazon Redshift 資料指標:

  • 每個工作階段中一次只能開啟一個資料指標。

  • 游標必須在交易 (BEGIN ... ) 中使用END。

  • 所有資料指標累積的結果集大小上限受限於叢集節點類型。若您需要更大的結果集,可將大小調整為 XL 或 8XL 節點組態。

    如需詳細資訊,請參閱游標限制條件

游標限制條件

擷取資料指標的第一列時,整個結果集會在領導節點上具體化。若結果集無法納入記憶體內,則會視需要寫入磁碟中。為保護領導節點的完整性,Amazon Redshift 會根據叢集的節點類型對所有資料指標結果集的大小強制執行限制條件。

下表說明每個叢集節點類型的結果集大小總計上限。結果集大小上限的單位是 MB。

節點類型 每個叢集的結果集上限 (MB)

DC2 Large 多個節點

192,000

DC2 Large 單一節點

8,000

DC2 8XL 多個節點

3,200,000

RA3 16XL 多個節點

14,400,000

RA3 4XL 多個節點

3,200,000

RA3 XLPLUS 多個節點

1,000,000

RA3 XLPLUS 單一節點

64,000

RA3 LARGE 多個節點

240,000

RA3 LARGE 單一節點

8,000

Amazon Redshift Serverless

150,000

若要檢視叢集的使用中資料指標組態,請以超級使用者身分查詢 STV_CURSOR_CONFIGURATION 系統資料表。若要檢視使用中資料指標的狀態,請查詢 STV_ACTIVE_CURSORS 系統資料表。使用者只能看見自己擁有之資料指標的資料列,但超級使用者可檢視所有資料指標。

使用游標時的效能考量

由於資料指標會在開始傳回結果至用戶端之前,於領導節點上將整個結果集具體化,因此在非常大型的結果集內使用資料指標會對效能產生負面影響。強烈建議您不要在非常大型的結果集內使用資料指標。在某些情況下,例如當您的應用程式使用ODBC連線時,游標可能是唯一可行的解決方案。不過我們建議您盡量使用以下替代方式:

  • 使用 UNLOAD 匯出大型資料表。當您使用 時UNLOAD,運算節點會平行運作,以將資料直接傳輸至 Amazon Simple Storage Service 上的資料檔案。如需詳細資訊,請參閱在 Amazon Redshift 卸載數據

  • 在用戶端應用程式中設定JDBC擷取大小參數。如果您使用 JDBC 連線且遇到用戶端 out-of-memory錯誤,您可以透過設定JDBC擷取大小參數,讓用戶端以較小的批次擷取結果集。如需詳細資訊,請參閱設定JDBC擷取大小參數

DECLARE CURSOR 範例

下列範例宣告名為 的游標,LOLLAPALOOZA以選取 Lollapalooza 事件的銷售資訊,然後使用游標從結果集擷取資料列:

-- 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;

下列範例會使用資料表中的所有結果在參考游標上循環:

CREATE TABLE tbl_1 (a int, b int); INSERT INTO tbl_1 values (1, 2),(3, 4); CREATE OR REPLACE PROCEDURE sp_cursor_loop() AS $$ DECLARE target record; curs1 cursor for select * from tbl_1; BEGIN OPEN curs1; LOOP fetch curs1 into target; exit when not found; RAISE INFO 'a %', target.a; END LOOP; CLOSE curs1; END; $$ LANGUAGE plpgsql; CALL sp_cursor_loop(); SELECT message from svl_stored_proc_messages where querytxt like 'CALL sp_cursor_loop()%'; message ---------- a 1 a 3