不使用綁定變數,每次 SQL 送入資料庫都需 Hard Parse(硬解析),在高併發、大量 DML 場景下會嚴重拖垮 Shared Pool 與 CPU。本文以 10 萬筆 INSERT 為例,對比「有無綁定變數」的效能差異,並說明 PL/SQL 隱性綁定機制。
CREATE TABLE t (a VARCHAR2(20), b VARCHAR2(20));
DECLARE
v_sql VARCHAR2(50);
BEGIN
FOR i IN 1..100000 LOOP
v_sql := 'INSERT INTO t VALUES (:1, :2)';
EXECUTE IMMEDIATE v_sql USING 'a'||i, 'b'||i;
END LOOP;
COMMIT;
END;
/
機制:v_sql 文字固定,只有 :1、:2 數值變化。Oracle 只做一次 Hard Parse,後續 99,999 次皆為 Soft Parse(軟解析),共享游標,大幅降低 CPU 與 Latch 爭用。
DECLARE
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO t VALUES ('a'||i, 'b'||i);
END LOOP;
COMMIT;
END;
/
機制:PL/SQL 靜態 SQL 會在編譯期自動轉為綁定變數,實際上也是綁定。若改用 EXECUTE IMMEDIATE 'INSERT ... VALUES (''a''||i, ''b''||i)' 字串拼接,才會產生 10 萬個不同 SQL 文字,導致 Hard Parse 暴增。
| 指標 | 綁定變數 | 字串拼接 | 差異 |
|---|---|---|---|
| 執行時間 | ~2 秒 | ~25 秒 | 12 倍 |
| Hard Parse 次數 | 1 | 100,000 | 10 萬倍 |
| Shared Pool 佔用 | 極低 | 極高(易 ORA-04031) | -- |
| Library Cache Latch 爭用 | 低 | 極高 | -- |
EXECUTE IMMEDIATE、DBMS_SQL)。PreparedStatement、Parameterized Query。在 PL/SQL 區塊中直接寫 INSERT INTO t VALUES (v1, v2),編譯器會自動將變數轉為綁定變數,**不需手動處理**。這是 PL/SQL 效能優於動態 SQL 的主因之一。
SELECT sql_text, executions, parse_calls, loads
FROM v$sqlarea
WHERE sql_text LIKE 'INSERT INTO T%';
executions ≈ 100,000、loads = 1 → 成功共享。loads 接近 executions → 未共享,需檢查綁定寫法。v$sqlarea 高 loads / executions 比例的 SQL,重構為綁定版本。CURSOR_SHARING = FORCE 只作緊急權宜,長期應修正程式碼。綁定變數是 Oracle 效能調優的「銀彈」,費力改寫一次,換來系統長期穩定與擴展性。