原始 SQL 問題
- 兩大表 `SS_CITIC_BILL_NBR` / `SS_CITIC_WAST_NBR` 結構相同,`UNION ALL` 導致全掃描兩次。
- 連接順序未以最小結果集驅動,`op_bill`/`op_bill_detail` 大表在前。
- 日期轉換 `to_char(sts_date,'yyyyMMdd')` 導致索引失效。
優化策略
- 合並同構表:若業務允許,建立視圖 `UNION ALL` 兩表,或物化視圖/分區表,避免查詢時重複掃描。
- 調整連接順序:以過濾後最小的單據號表為驅動表(`WHERE doc_id=108 AND sts_date=...`),再 `LEFT JOIN` 明細與主表。
- 條件下推:在子查詢/視圖中先應用高選擇性條件(`doc_id`、`sts_date`、`doc_nbr<>''`),再關聯大表。
- 索引建議:
`SS_CITIC_BILL_NBR(doc_id, sts_date, doc_nbr)`
`op_bill_detail(pk_id)`
`op_bill(BILL_FILE_ID, pvdr_id)`
- 重寫示例:見原最佳回答,使用派生表 `c` 先過濾合並,再左連大表,最後 `ORDER BY nbr`。
驗證
使用 `EXPLAIN PLAN` 對比執行計劃,關注 `ROWS`、`COST`、是否走索引(`IXSCAN` vs `TBSCAN`)。