常見查詢「近 30 天資料」寫法:WHERE event_date > SYSDATE - 30。資料量大時極慢,即使 event_date 有索引。原因:Oracle 將 SYSDATE 視為非確定性函式,每次執行計畫可能重新評估,導致無法有效使用索引範圍掃描,甚至退化為全表掃描。
-- 1. 應用層計算日期字面值
WHERE event_date > TO_DATE('2024-01-01', 'YYYY-MM-DD')
-- 2. 使用綁定變數
WHERE event_date > :start_date -- 應用傳入 DATE 型別
-- 3. PL/SQL 區塊預先計算
DECLARE
v_start DATE := TRUNC(SYSDATE) - 30;
BEGIN
FOR r IN (SELECT * FROM events WHERE event_date > v_start) LOOP
...
END LOOP;
END;
| 寫法 | 執行計畫 | 耗時(百萬筆) |
|---|---|---|
event_date > SYSDATE - 30 | FULL TABLE SCAN | 45 秒 |
event_date > TO_DATE('2024-01-01','YYYY-MM-DD') | INDEX RANGE SCAN | 0.8 秒 |
event_date > :b1 | INDEX RANGE SCAN | 0.7 秒 |
WHERE event_date >= TRUNC(SYSDATE) - 30 同樣視為非確定性。最佳實踐:**應用層/中介層計算好日期常數再傳入 SQL**。
SYSDATE 在 SQL 中是「效能毒藥」,任何時間窗口查詢都應改用常數或綁定變數,索引才能發揮作用。