深入理解Oracle表 2 驅動表的那些事兒

2021-08-27 09:26:15 字數 2332 閱讀 9577

以乙個比較兩本字典來做例子:

一本字典有索引目錄(dict a), 一本沒有(dict b)

現在要找出所有a開頭的單詞的異同

那麼比較的時候,你會怎麼比較?

合理的做法應該是以沒有索引的字典dict b開始, 找到a開頭的那一頁, 然後對於每個單詞, 通過使用索引在dict a中找到相應的條目

如果反過來, 效率會相同嗎?

驅動表,通俗的講就是先從哪個表開始檢索,良好的驅動表是成功優化的一半

例如:select * from a,b where a.id = b.id and a.姓名 = '美格瑞恩' and b.性別 = '女';

在a,b表同等數量級的情況下,顯然用a表做為驅動表比較好

因為姓名相對於性別來說可以過濾掉更多的資料

所以想辦法使你的執行計畫先掃瞄a表再通過nest loop與b表關連比較理想

一般而言,2個表的時候,選擇小表;3個或者以上的時候,選擇關聯比較多的表作為驅動表

不過,事無絕對,看個案例先:

有兩個表t1和t2,可以假設t1存放姓名、id這些基本資訊,每行較短

而t2也有id列和一些說明、備註類資訊,每行長的可能有一兩千個位元組

對於這兩個表,使用巢狀迴圈連線,t1表佔的塊數比較少,是小表

而t2表佔的塊數幾倍於t1,是大表。那麼,應該t1做驅動表更好一些,但實際卻是t2大表做驅動表更好

乙個不知道dba還是開發,不知道這一點,為了強制小表t1做驅動表,寫了類如下語句:

select /*+ ordered use_nl(t1,t2) */ from t2,t1 where t1.id=t2.id;

後來這個語句造成了一些效能問題。通過了解巢狀迴圈的工作方式,發現這裡的確是大表做驅動表好一些

這裡就說明了乙個問題,都說巢狀迴圈要小表做驅動表,如果不知道這是為什麼,這很容易造**雲亦雲

這樣只知其表,而不知其裡,很容易影響以後在某些問題上做出的判斷

驅動表(driving table/outer table)又稱為外層表,驅動表僅僅用於nested_loop join 和 hash join

驅動表是用來驅動查詢的

在cbo中,優化器會根據cost自動選擇驅動表,與表的順序無關

通常情況下,驅動表的選擇性較高(該列唯一鍵與列的比值較高),where中的限制條件較多,返回的行數較少的表適合做驅動表

事實上,大表有時候也會做驅動表,只要在大表上面限制條件較多,從大表上面返回的行數較少的話,大表也適合做驅動表

始終要記住的就是返回的結果集(某個表被過濾後的資料,或者某些表join 產生的資料)較小的表適合做驅動表

也就是說,哪個返回資料少 ,哪個就做驅動表,即連線操作應從返回較少行上驅動

我們在看執行計畫的時候,離nested loops,hash join 近的表就是驅動表,也就是說執行計畫中靠上的表是驅動表

以下是幾個快速判斷驅動表的經驗,可能有錯哦:

(1)用於連線的子句的列應被索引、在where子句中應盡量利用索引,而不是避開索引

(2)連線操作應從返回較少行上驅動

(3)如果所連線的表a和b,a表長度遠遠大於b表,建議從較大的a表上驅動

(4)如果where子句中含有選擇性條件,where no=20,將最具有選擇性部分放在表示式最後

(5)如果只有乙個表有索引,另一表無索引,無索引的表通常作為驅動表。如a表的no列以被索引

而b表的no列沒被索引,則應當b表作為驅動表,a表作為被驅動表

rule 下所謂驅動表

我們以 nested loop 為例:

如果兩個表連線欄位都沒有索引(通常這個時候是 sort merge / hash join),則驅動表會選擇後者

若兩個表其中有乙個有索引而另外乙個沒有索引,則驅動表是沒有索引那乙個,跟順序無關

若兩個表都有索引,則驅動表為 後面 那乙個表

所以事實上,rule下,只有在兩個表都存在連線欄位的索引的情況下才需要考慮順序問題

也就是小表放在後面大表放在前面(當然到底哪個好這實際上還跟符合條件的記錄數、資料分布等因素相關!,所以應該以實際測試為準)

而如果是 cbo 下,則跟順序無關

關鍵的是明白執行計畫,而不在於記住什麼規則

例如,表連線返回一條記錄

存在2張表,乙個10條記錄,乙個1000萬條記錄

若2表都存在連線字段索引,

以小表為驅動表,則代價為:

10*(通過索引在大表查詢一條記錄的代價)

以大表為驅動表,則代價為:

1000萬*(通過索引在小表查詢一條記錄的代價)

通過索引獲取一條記錄,10rows的表,代價通常在3 blocks,索引2塊,表1塊

而如果是1000萬的表,索引可能達到4塊,表1塊,速度·掰著腳趾頭都知道了哈

深入理解Oracle表 2 驅動表的那些事兒

以乙個比較兩本字典來做例子 一本字典有索引目錄 dict a 一本沒有 dict b 現在要找出所有a開頭的單詞的異同 那麼比較的時候,你會怎麼比較?合理的做法應該是以沒有索引的字典dict b開始,找到a開頭的那一頁,然後對於每個單詞,通過使用索引在dict a中找到相應的條目 如果反過來,效率會...

C 深入理解虛表

虛表是記錄本類中所有虛函式位址的乙個 如下,我們設計了乙個類,存在兩個虛函式。class a virtual void fun2 通過a例項化a,再看看a的記憶體結構。vfptr就是虛表!可以把它看成存放了void 型物件的陣列。而 vfptr的兩個成員分別代表fun1函式的指標和fun2函式的指標...

深入理解SQL表連線(join)

關聯式資料庫中最重要的兩個概念,當屬表連線和聚合。表連線將一條資料分開成多條,表聚合將多條合成一條。這一分一合,形成了關聯式資料庫強大的邏輯表達能力,這篇文章講表連線,關於聚合請移步 深入理解sql分組聚合 內連線 外連線 左外連線 右外連線 全連線 交叉連線 自然連線 這麼多種連線方式,你是不是已...