Amazon Redshift 將不再支援在 2026 年 6 月 30 日之後使用 Python UDFs。我們將開始分階段強制執行。如需 Python 生命週期結束和遷移選項的詳細資訊,請參閱 2025 年 6 月 30 日發佈的部落格文章
本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
DECLARE
定義新的資料指標。使用資料指標可從完整查詢的結果集中一次擷取幾個資料列。
擷取資料指標的第一列時,整個結果集會在領導節點上、記憶體中或磁碟上具體化 (如有需要)。由於在大型結果集內使用資料指標可能會對效能造成負面影響,因此建議您盡量使用替代方式。如需詳細資訊,請參閱使用游標時的效能考量。
您必須在交易區塊內宣告資料指標。每個工作階段中一次只能開啟一個資料指標。
語法
DECLARE cursor_name CURSOR FOR query
Parameters
- cursor_name
-
新資料指標的名稱。
- query
-
填入資料指標的 SELECT 陳述式。
DECLARE CURSOR 使用須知
若您的用戶端應用程式使用 ODBC 連線,且您的查詢建立的結果集太大,無法納入記憶體中,則您可以使用資料指標將結果集串流到用戶端應用程式。當您使用資料指標時,整個結果集會在領導節點上具體化,然後您的用戶端就能以遞增方式擷取結果。
注意
若要在 Microsoft Windows 的 ODBC 中啟用資料指標,請在您用於 Amazon Redshift 的 ODBC DSN 中啟用使用宣告/擷取選項。建議您使用 ODBC DSN 選項對話方塊中的 Cache Size (快取大小) 欄位,將多節點叢集上的 ODBC 快取大小設定為 4,000 或更大的數字,以減少往返次數。在單一節點叢集上,將 Cache Size (快取大小) 設定為 1,000。
由於使用資料指標可能會對效能造成負面影響,因此建議您盡量使用替代方式。如需詳細資訊,請參閱使用游標時的效能考量。
在滿足以下限制的情況下,可支援 Amazon Redshift 資料指標:
-
每個工作階段中一次只能開啟一個資料指標。
-
資料指標必須在交易內使用 (BEGIN … END)。
-
所有資料指標累積的結果集大小上限受限於叢集節點類型。若您需要更大的結果集,可將大小調整為 XL 或 8XL 節點組態。
如需詳細資訊,請參閱游標限制條件。
游標限制條件
擷取資料指標的第一列時,整個結果集會在領導節點上具體化。若結果集無法納入記憶體內,則會視需要寫入磁碟中。為保護領導節點的完整性,Amazon Redshift 會根據叢集的節點類型對所有資料指標結果集的大小強制執行限制條件。
下表說明每個叢集節點類型的結果集大小總計上限。結果集大小上限的單位是 MB。
| Node type | 每個叢集的結果集上限 (MB) |
|---|---|
|
rg.12xlarge 多個節點 |
7,200,000 |
|
rg.4xlarge 多個節點 |
1,600,000 |
|
rg.xlarge 多個節點 |
240,000 |
|
rg.large 多個節點 |
100,000 |
|
ra3.16xlarge 多個節點 |
14,400,000 |
|
ra3.4xlarge 多個節點 |
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 |
|
dc2.8xlarge 多個節點 |
3,200,000 |
|
dc2.large 多個節點 |
192,000 |
|
dc2.large 單一節點 |
8,000 |
若要檢視叢集的使用中資料指標組態,請以超級使用者身分查詢 STV_CURSOR_CONFIGURATION 系統資料表。若要檢視使用中資料指標的狀態,請查詢 STV_ACTIVE_CURSORS 系統資料表。使用者只能看見自己擁有之資料指標的資料列,但超級使用者可檢視所有資料指標。
使用游標時的效能考量
由於資料指標會在開始傳回結果至用戶端之前,於領導節點上將整個結果集具體化,因此在非常大型的結果集內使用資料指標會對效能產生負面影響。強烈建議您不要在非常大型的結果集內使用資料指標。在某些情況下,例如應用程式使用 ODBC 連線時,資料指標可能會是唯一可行的解決方案。不過我們建議您盡量使用以下替代方式:
-
使用 UNLOAD 匯出大型資料表。使用 UNLOAD 時,運算節點會平行運作,將資料直接傳輸至 Amazon Simple Storage Service 上的資料檔案。如需詳細資訊,請參閱在 Amazon Redshift 中卸載資料。
-
在您的用戶端應用程式中設定 JDBC 擷取大小參數。若您使用 JDBC 連線且發生用戶端記憶體不足的錯誤,您可以藉由設定 JDBC 擷取大小參數,讓用戶端分小批擷取結果集。如需詳細資訊,請參閱設定 JDBC 擷取大小參數。
相較於具有類似運算容量的 RA3 節點,RG 節點具有較小的游標結果集大小上限。如果您的游標工作負載接近或超過 RG 節點類型的限制,請考慮下列選項:
-
最佳化結果集大小。套用更多選擇性查詢篩選條件、減少擷取的資料欄數量,或實作應用程式層級分頁,以較小的批次處理結果。
-
遷移至較大的 RG 節點類型。較大的節點類型可提供更高的游標容量。如果您的節點計數允許且工作負載效能不受影響,您可以按比例減少節點數量,以維持相當的總叢集成本。
若要判斷游標結果集的目前大小,請查詢 SYS_QUERY_HISTORY 檢視中與第一個 FETCH 陳述式針對游標執行相關聯的returned_bytes值。如需詳細資訊,請參閱 SYS_QUERY_HISTORY。
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