Oracle
過濾在 Access 謂詞之前執行的謂詞
這是甲骨文 11g。當我嘗試對錶執行選擇查詢時,在解釋計劃選項中,我看到查詢的過濾謂詞(沒有索引的列上的謂詞)在索引訪問謂詞之前執行。我不明白為什麼查詢優化器選擇這個計劃?
我嘗試了 –+ ordered_predicates 選項,但它忽略了這一點。
過濾謂詞和全表掃描一樣可怕,對吧?
編輯查詢和計劃:
從表中選擇 column1、column2、column3,其中 column1 >= :cutoff 和 trunc(column2) = trunc(sysdate-1) 和 column3 = :column_value
索引在第 1 列上定義。
這是查詢計劃:
Plan hash value: 4098448107 ------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1619K| 49M| 4433K (1)| 00:02:54 | |* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TABLE_NAME | 1619K| 49M| 4433K (1)| 00:02:54 | |* 2 | INDEX RANGE SCAN | NAME_OF_THE_INDEX | 87M| | 648K (1)| 00:00:26 | ------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("TABLE_NAME"."column3"=:column_value AND TRUNC(INTERNAL_FUNCTION("TABLE_NAME"."column2"))=TRUNC(SYSDA TE@!-1)) 2 - access("TABLE_NAME"."column1">=TO_NUMBER(:CUTOFF) AND "TABLE_NAME"."column1" IS NOT NULL)
執行計劃中顯示的步驟順序不是執行它們的步驟順序。
數據庫首先使用以下謂詞訪問名為 NAME_OF_THE_INDEX 的索引:
2 - access("TABLE_NAME"."column1">=TO_NUMBER(:CUTOFF) AND "TABLE_NAME"."column1" IS NOT NULL)
然後數據庫使用索引 NAME_OF_THE_INDEX 中的 rowid 使用這些謂詞訪問名為 TABLE_NAME 的表:
1 - filter("TABLE_NAME"."column3"=:column_value AND TRUNC(INTERNAL_FUNCTION("TABLE_NAME"."column2"))=TRUNC(SYSDATE@!-1))
所以它按預期工作,首先使用訪問謂詞,然後使用過濾謂詞。
不幸的是,我在官方文件中找不到一個很好的解釋範例,但我可以推荐一些更好的東西。為了更好地理解執行計劃,請閱讀這些系列(共有 14 個部分):
https://www.red-gate.com/simple-talk/sql/oracle/execution-plans-part-1-finding-plans/