日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle 多表 连接 顺序 与 性能关系 测试

發布時間:2023/12/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle 多表 连接 顺序 与 性能关系 测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

. 創建表并insert 數據

create table ta (id number,name varchar2(10));

create table tb(id number,job varchar2(10));

?

begin

for i in 1..1000000 loop

begin

insert into ta values(i,'dave');

commit;

end;

end loop;

end;

?

begin

for i in 1..1000000 loop

begin

if i<10 then

insert into tb values(i,'boy');

elsif i<20 and i>10 then

insert into tb values(i,'girl');

commit;

end if;

end;

end loop;

end;

?

.在沒有索引的情況關聯ta tb 查詢

?

相關鏈接:

?????? Oracle Optimizer CBO RBO

?????? http://blog.csdn.net/tianlesoftware/archive/2010/08/19/5824886.aspx

?

?????? 多表連接的三種方式詳解 HASH JOIN MERGE JOIN NESTED LOOP

?????? http://blog.csdn.net/tianlesoftware/archive/2010/08/21/5826546.aspx

?

?????? Oracle Hint

?????? http://blog.csdn.net/tianlesoftware/archive/2010/08/23/5833020.aspx

?

2.1? optimizer選擇 CBO10g 默認)

--ta 在前

select ta.id, ta.name,tb.job from ta,tb where ta.id=tb.id;

?

?

--tb 在前

select ta.id, ta.name,tb.job from tb,ta where ta.id=tb.id;

?

總結:????

?????? 兩條SQL 執行計劃是一樣的, tatb 的順序沒有影響。

?????? 因為tatb 的記錄相差較大,ta100萬,tb 只有20條。 所以這里CBO 選擇使用Hash Join

?????? CBO 選擇2個表中記錄較小的表tb,將其數據放入內存,對Join key構造hash 表,然后去掃描大表ta 找出與散列表匹配的行。

?

2.2 tatb ID b-tree 索引后在查看

?

--建索引

create index idx_ta_id on ta(id);

create index idx_tb_id on tb(id);

?

--tb 在前

select ta.id, ta.name,tb.job from tb,ta where ta.id=tb.id;

?

?

--ta 在前

select ta.id, ta.name,tb.job from ta,tb where ta.id=tb.id;

?

總結:

?????? 執行計劃還是一樣,不同的是表之間的關聯模式發生的改變,從Hash Join 變成了Nested Loops

?????? Nested loop一般用在連接的表中有索引,并且索引選擇性較好的時候. 在我們這個示例中,CBO 選擇把返回結果集較小的表tb 作為outer tableCBO 下,默認把outer table 作為驅動表,然后用outer table 的每一行與inner table(我們這里是ta)進行Join,去匹配結果集。 由此可見,在tbinner table 有索引的情況,這種匹配就非常快。

?

?????? 這種情況下整個SQLcost

?????? cost = outer access cost + (inner access cost * outer cardinality)

?

?????? 從某種角度上看,可以把Nested loop 看成2for 循環。

?

?

2.3 使用RBO 查看

?????? 10g里,optimizer 默認已經使用CBO了,如果我們想使用RBO 只能通過Hint 來實現。

??????

-- ta 在前

select /*+rule*/ta.id, ta.name,tb.job from ta,tb where ta.id=tb.id;

?

?

SYS@anqing2(rac2)> select /*+rule*/ta.id, ta.name,tb.job from ta,tb where ta.id<100 and? ta.id=tb.id;

Elapsed: 00:00:00.00

-- 注意這個SQL里,我們加了ta.id<100 的條件

Execution Plan

----------------------------------------------------------

Plan hash value: 3943212106

?

---------------------------------------------------

| Id? | Operation???????????????????? | Name????? |

---------------------------------------------------

|?? 0 | SELECT STATEMENT????????????? |?????????? |

|?? 1 |? TABLE ACCESS BY INDEX ROWID? | TB??????? |

|?? 2 |?? NESTED LOOPS??????????????? |?????????? |

|?? 3 |??? TABLE ACCESS BY INDEX ROWID| TA??????? |

|*? 4 |???? INDEX RANGE SCAN????????? | IDX_TA_ID |

|*? 5 |??? INDEX RANGE SCAN?????????? | IDX_TB_ID |

---------------------------------------------------

-- 當我們加上條件之后,就先走ta了,而不是tb 因為先走ta,用ta的限制條件過濾掉一部分結果,這樣剩下的匹配工作就會減少。

Predicate Information (identified by operation id):

---------------------------------------------------

?

?? 4 - access("TA"."ID"<100)

?? 5 - access("TA"."ID"="TB"."ID")

?

Note

-----

?? - rule based optimizer used (consider using cbo)

?

--tb 在前

select /*+rule*/ta.id, ta.name,tb.job from tb,ta where ta.id=tb.id;

?

?

?

總結:

?????? 2個就區別很明顯。 因為Oraclesql的解析是從后向前的。 那么當先遇到tb時,那么會對tb進行全表掃描,然后用這個結果匹配ta。因為ta有索引,所以通過索引去匹配。

?????? 如果先遇到ta,那么就會對ta進行全表掃描。 因為2個表的差距很大,所以全表掃描的成本也就很大。

?????? 所以在RBO 下,大表在前,小表在后。這樣就會先遇到小表,后遇到大表。 如果有指定限定的where 條件,會先走限定條件的表。

?

?

2.4 drop 索引之后,在走RBO

?

drop index idx_ta_id;

drop index idx_tb_id;

?

?

--ta 在前

select /*+rule*/ta.id, ta.name,tb.job from ta,tb where ta.id=tb.id;

--tb 在前

select /*+rule*/ta.id, ta.name,tb.job from tb,ta where ta.id=tb.id;

?

總結:

?????? 這里選擇了Sort Merge Join 來連接2張表。Sort Merge join 用在沒有索引,并且數據已經排序的情況.

??????

?????? 我們表中的記錄是按照順序插敘的,所以符合這個條件。 SQL 的解析還是按照從后往前,所以這里tatb 在前先掃描的順序不一樣,不過都是全表掃描。 效率都不高。

?

?

2.5 ?引深一個問題:使用 字段名 代替 *

?????? * 能方便很多,但在ORACLE解析的過程中, 會通過查詢數據字典,會將’*’ 依次轉換成所有的列名,這就需要耗費更多的時間. 從而降低了效率。

?

SYS@anqing2(rac2)> set timing on

SYS@anqing2(rac2)> select * from ta where rownum=1;

??????? ID NAME

---------- ----------

???????? 1 dave

?

Elapsed: 00:00:00.03

SYS@anqing2(rac2)> desc ta

?Name???????????????? Null???? Type

?----------------------------------------- -------- ----------------------------

?ID?????????????????????????? NUMBER

?NAME?????? ????????????????VARCHAR2(10)

?

SYS@anqing2(rac2)> select id,name from ta where rownum=1;

?

??????? ID NAME

---------- ----------

???????? 1 dave

?

Elapsed: 00:00:00.02

?????????????????????????????????????

時間已經縮短。 但不明顯,用Toad 來查看一下:

?

寫全字段,執行時間是161 毫秒,用* 561毫秒。 差距很明顯。

?

查看一下他們的執行計劃:

SYS@anqing2(rac2)> select * from ta where rownum=1;

Elapsed: 00:00:00.00

?

Execution Plan

----------------------------------------------------------

Plan hash value: 761731071

?

---------------------------------------------------------------------------

| id? | operation????????? | name | rows ?| bytes | cost (%cpu)| time???? |

---------------------------------------------------------------------------

|?? 0 | select statement?? |????? |???? 1 |??? 20 |???? 7? (72)| 00:00:01 |

|*? 1 |? count stopkey?? |????? |?????? |????? |???????? ??|???????? |

|?? 2 |?? table access full| ta?? |?? 890k|??? 16m|???? 7? (72)| 00:00:01 |

---------------------------------------------------------------------------

?

Predicate Information (identified by operation id):

---------------------------------------------------

?

?? 1 - filter(ROWNUM=1)

?

Note

-----

?? - dynamic sampling used for this statement

?

SYS@anqing2(rac2)> select id,name from ta where rownum=1;

Elapsed: 00:00:00.00

Execution Plan

----------------------------------------------------------

Plan hash value: 761731071

?

---------------------------------------------------------------------------

| id? | operation????????? | name | rows? | bytes | cost (%cpu)| time???? |

---------------------------------------------------------------------------

|?? 0 | select statement?? |????? |???? 1 |??? 20 |???? 7? (72)| 00:00:01 |

|*? 1 |? count stopkey?? |????? |?????? |????? |?????????? |??????? |

|?? 2 |?? table access full| ta?? |?? 890k|??? 16m|???? 7? (72)| 00:00:01 |

---------------------------------------------------------------------------

?

Predicate Information (identified by operation id):

---------------------------------------------------

?

?? 1 - filter(ROWNUM=1)

?

Note

-----

?? - dynamic sampling used for this statement

?

?

注意:

?????? 使用 * 和 寫全字段名,他們的執行計劃是一樣的,但是執行時間不一樣。

?

?

?

?

?

?

?

-------------------------------------------------------------------------------------------------------

Blog http://blog.csdn.net/tianlesoftware

Email: dvd.dba@gmail.com

DBA1 群:62697716(滿);?? DBA2 群:62697977(滿)?? DBA3 群:62697850(滿)??

DBA 超級群:63306533(滿);? DBA4 群: 83829929? DBA5群: 142216823???

DBA6 群:158654907? 聊天 群:40132017?? 聊天2群:69087192

--加群需要在備注說明Oracle表空間和數據文件的關系,否則拒絕申請

轉載于:https://www.cnblogs.com/zlja/archive/2011/06/16/2449636.html

總結

以上是生活随笔為你收集整理的Oracle 多表 连接 顺序 与 性能关系 测试的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。