一個關於執行計劃的小問題測試(r8筆記第60天)
最近有朋友在微信公眾號後臺留言提了一個問題,問題如下: 執行計劃中,並列的兩條操作比如並列的兩條table access full,上層沒有關聯操作比如hash join,這是什麼意思?
但是兩張表在sql中是有等值連線的,為什麼執行計劃沒有提現連線方式呢? 然後他過了一會附了一張操作截圖。
這個問題一下子看起來就比較清晰了。
為了簡單復現這個問題,在本地做了一個小測試。 為了達到同樣的表結構,我建立了同樣的表。 create table by_fs as select object_id zd_fs, object_name kecheng from all_objects where rownum<11; create table xs_xf as select object_id zd_fs, object_name kecheng from all_objects where rownum<20; 然後啟用trace,得到的執行計劃情況如下:
可以看到是可以復現這個朋友的問題的。這個時候從執行計劃來入手,看到對於表XS_XF走了全表掃描,對於其中的資料在表BY_FS中通過全表掃描進行匹配。
整個執行計劃的關鍵可以看到謂詞資訊:
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("CC"."KECHENG"=:B1)
在by_fs中,會把外層xs_xf的查詢結果通過繫結變數的方式傳入,感覺其實和表關聯的方式應該是一樣的情況。
而如果改為表連線的場景,可以輕鬆實現。改寫為下面的形式繼續檢視。
這個時候可以看到對這兩個表還是走了全表掃描,表連線為hash join的方式,可以看到一致性讀也確實低了不少。
這個地方為什麼看到的是hash join,還是通過謂詞資訊來看。
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("CC"."KECHENG"="AA"."KECHENG")
目前兩個表還是沒有任何索引的,但是通過謂詞資訊可以看到access的字樣,可見是在資料庫內部做了這一層的對映,把兩個表的資料通過hash演算法進行對映。
我們接著建立索引。
create index ind_xs_xf on xs_xf(kecheng);
create index ind_by_fs on by_fs(kecheng);
可以看到CBO還是做了很合理的選擇,對於xs_xf還是使用全表掃描,對於返回的結果集,是通過繫結變數的方式傳入子查詢。 我們更近一步,來看看修改為表關聯的方式,執行計劃的變化。
這種結果就好比下面的形式。
select kecheng,zd_fs from by_fs order by kecheng;
select * from xs_xf order by kecheng;
針對本例,是對by_fs做了全表掃描,對資料進行了排序,然後根據kecheng對結果集進行了匹配和關聯,最後把結果集輸出。
因為merge-sort join確實使用情況會相對比較少,在資料庫中是存在一個隱含引數來控制的。
NAME VALUE ISDEFAULT ISMOD ISADJ
------------------------------------------ --------- ---------- -----
_optimizer_sortmerge_join_enabled TRUE TRUE FALSE FALSE
當然也可以通過Hint /*+use_merge(cc,aa)來進行控制和管理。
當然更多的資訊沒有進行挖掘,不過從我的直觀感受來看,第一個查詢的效果和表關聯的場景還是很類似的。而且通過CBO來做出的最終判定來看,差別很明顯,但是效果基本是一致的。