OLTP 系統大量重複 SQL 僅綁定變數不同,CURSOR_SHARING=SIMILAR/FORCE 雖能強制共享,但優化器在「偷窺」首次綁定值後產生的執行計畫,可能不適合後續截然不同的綁定值(如 DSS 環境:小範圍走索引、大範圍走全表掃描)。Oracle 11g 引入 Adaptive Cursor Sharing (ACS),動態判斷是否需要新的子游標,實現「有選擇地共享」。
首次硬解析時優化器偷窺綁定值,標記游標為 IS_BIND_SENSITIVE='Y',記錄謂詞選擇率資訊,作為後續比較基準。
當後續執行的綁定值導致「顯著不同的選擇率」(超出現有選擇性立方體範圍),優化器將游標標記為 IS_BIND_AWARE='Y',並產生新的子游標與執行計畫。同一 SQL 可擁有多個子游標,各自對應不同綁定值範圍。
| 視圖 | 用途 |
|---|---|
V$SQL | 新增 IS_BIND_SENSITIVE、IS_BIND_AWARE 欄位,快速識別 ACS 候選語句。 |
V$SQL_CS_HISTOGRAM | 子游標執行次數分佈(Bucket 0/1/2 對應低/中/高選擇率),觀察負載傾斜。 |
V$SQL_CS_SELECTIVITY | 記錄各子游標的謂詞高/低值範圍(選擇性立方體),判斷新綁定值是否落入現有範圍。 |
V$SQL_CS_STATISTICS | 子游標執行統計:PEEKED、EXECUTIONS、ROWS_PROCESSED、BUFFER_GETS、CPU_TIME。 |
VAR cust_start NUMBER; VAR cust_end NUMBER;
VAR time_start DATE; VAR time_end DATE;
BEGIN
:cust_start := 2; :cust_end := 38;
:time_start := '01-JAN-1998'; :time_end := '31-MAR-1998';
SELECT SUM(amount_sold), SUM(quantity_sold)
INTO :total_sold, :total_qty
FROM sh.sales
WHERE cust_id BETWEEN :cust_start AND :cust_end
AND time_id BETWEEN :time_start AND :time_end;
END;
→ 產生 Child 0,IS_BIND_SENSITIVE=Y、IS_BIND_AWARE=N,直方圖 Bucket 1 計數=1。
-- Execution #2:大範圍跨年
:cust_start := 42999; :cust_end := 50000;
:time_start := '01-JAN-1997'; :time_end := '31-MAR-1998';
-- Execution #3:中等範圍
:cust_start := 1000; :cust_end := 1400;
:time_start := '01-JAN-1996'; :time_end := '31-MAR-1997';
→ 產生 Child 1,IS_BIND_AWARE=Y,V$SQL_CS_SELECTIVITY 記錄新謂詞範圍。優化器自動維護極少數必要子游標,避免爆炸性增長。
CURSOR_SHARING 無關,即使 EXACT 也生效。_OPTIMIZER_ADAPTIVE_CURSOR_SHARING=FALSE 可關閉(隱藏參數,不建議)。OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE 時,ACS 產生的多個子游標皆會被捕獲為 Plan Baseline。DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE 批次載入所有子游標計畫。ACS 解決「綁定變數偷窺單一計畫不適用多場景」的核心痛點,透過選擇性立方體與直方圖動態判斷,**在保持游標共享優勢的同時,為顯著不同的綁定值集合自動生成最優執行計畫**,大幅提升 OLTP/DSS 混合負載的穩定性與效能。