先說結論:
1.就OR跟UNION ALL而言,是否走全表掃描與返回的資料量有關,若資料量大則走全表掃描,否則走索引(若Where子句的欄位有建立索引),所以不是OR就代表會走全表掃描。
2.會說使用UNION ALL比OR好並不是因為OR會走全表掃描,而是使用OR會較容易使查詢計畫出現filter(尤其使用子查詢時)。如前篇所述,查詢計畫出現filter應消除filter,與是否會全表掃描無關。
(Oracle SQL版本在10g以上,且優化器是基於CBO的前提之下才適用。以後相關SQL的文章,若沒特別說明皆是基於這個前提之下)
如下圖,SQL使用OR並沒有導致全表掃描,因為返回資料量少的關係,所以優化器會選擇走索引掃描。
INDEX SKIP SCAN為索引跳躍掃描,理想的情況應是走INDEX RANGE SCAN,也就是索引範圍掃描。
優化器會使用索引跳躍掃描的原因是,pmda_t該表使用複數索引,但引導索引是pmdaent而不是pmdadocno。
(就上圖的而言,這樣的索引建立方式就是非常不OK的索引,因為pmdaent的value重複性很高,並不適合當複合索引中的引導索引)
出現索引跳躍掃描的解決方式:
1.增加一個使用pmdadocno的查詢索引,或
2.在SQL的where子句,謂詞要多pmdaent的引導索引的條件,如下圖。
如此一來,就會使用索引範圍掃描囉~~~~
另外使用UNION ALL的存取路徑與表連接方式都跟OR一樣(下圖與第一張圖),所以若沒有使用到子查詢,是不用太在意要用UNION ALL或是OR的。資料量多寡也不在考量範圍內,因為一但返回資料量大,不潤是UNION ALL還是OR都會走全表掃描。
重點:
1.返回資料量大=>走全表掃描,返回資料量小=>走索引掃描
2.索引範圍掃描優於索引跳躍掃描