游標生命週期包含 7 個階段,每階段皆消耗 CPU/記憶體資源。理解各階段角色,可針對性消除冗餘操作,大幅提升 PL/SQL 效能。
-- 原寫法:迴圈內 OPEN/PARSE/CLOSE
FOR i IN 1..1000 LOOP
l_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(...);
...
DBMS_SQL.CLOSE_CURSOR(l_cursor);
END LOOP;
-- 優化:移出迴圈
l_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(l_cursor, 'SELECT ... WHERE ename != :b1', DBMS_SQL.NATIVE);
FOR i IN 1..1000 LOOP
DBMS_SQL.BIND_VARIABLE(l_cursor, ':b1', TO_CHAR(i));
l_retval := DBMS_SQL.EXECUTE(l_cursor);
WHILE DBMS_SQL.FETCH_ROWS(l_cursor) > 0 LOOP ... END LOOP;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(l_cursor);
效果:OPEN_CURSOR 耗時歸零,PARSE 耗時大幅下降。
SQL 文本固定,僅綁定變數值改變 → 軟解析,Library Cache 直接重用 Shared Cursor。若動態拼接 SQL 字串 ('... != ' || i) 則每次硬解析,極度消耗 Shared Pool Latch。
ARRAYSIZE)DBMS_SQL.DEFINE_ARRAY(..., cnt => 100, ...) 一次取 100 列,減少 FETCH 呼叫次數與網路往返。實測 cnt=1 → cnt=100 總耗時再降 30%+。
DEFINE_ARRAY count / BULK COLLECT LIMIT。V$SQLAREA.PARSE_CALLS vs EXECUTIONS,比值接近 1 表示硬解析過多。