查詢含函數運算列(如 WHERE UPPER(NAME)='SMITH')時,普通索引失效,需全表掃描執行函數。函數索引預計算函數值存入索引,查詢直接走索引範圍掃描,性能提升數量級。
場景:狀態列 STATUS 僅 'Y'/'N',99% 為 'Y',業務只查 'N'。
CREATE INDEX IDX_T_STATUS_N ON T(DECODE(STATUS,'N','N'));
DECODE 將 'Y' 映射為 NULL,不進索引;'N' 映射為 'N' 入索引。WHERE STATUS='N' 改寫為 WHERE DECODE(STATUS,'N','N')='N' 秒級返回。場景:專案表,STATUS='ACTIVE' 時專案名唯一,INACTIVE 允許重名。
CREATE UNIQUE INDEX UX_PROJ_ACTIVE_NAME ON T(DECODE(STATUS,'ACTIVE',NAME));
| 現象 | 原因 | 對策 |
|---|---|---|
WHERE COL IS NULL 不走索引 | NULL 不進 B 樹 | 建立函數索引 NVL(COL,'NULL') 或位圖索引 |
| 複合索引含 NULL 列,唯一約束失效 | (NULL,NULL) 不存索引,可重複插入 | 列定義 NOT NULL 或函數索引映射 |
COUNT(*) 不走可空列索引 | 索引行數 < 表行數 | 索引建立在 NOT NULL 列或加 /*+ INDEX */ 強制 |
WHERE X=5 AND Y='M' UNION ALL WHERE X=5 AND Y='F' 走索引。WHERE NUM_COL='123' 觸發 TO_NUMBER,索引失效。代碼中嚴禁字符串比較數字列。TRUNC(DT)=TRUNC(SYSDATE) → DT >= TRUNC(SYSDATE) AND DT < TRUNC(SYSDATE)+1,利用範圍掃描。DBMS_STATS.GATHER_TABLE_STATS,優化器依賴統計信息決策,非 Bug。