成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Oracle優化查詢中所用到的語句有哪些?

數據庫 Oracle
我們今天主要和大家分享的是Oracle優化查詢的實際操作步驟,以及在實際操作中那些的語句是我們所能用到的,以下就是文章的具體內容的介紹。

以下的文章主要講述的是Oracle優化查詢的實際操作我們首先是假設LARGE_TABLE是一個表(較大型),而且username列上是沒有相關索引的,那么它在實際的操作中要用到的語句有那些?下面就是對其語句的描述:

 

  1. SQL> SELECT * FROM LARGE_TABLE where USERNAME = ‘TEST';   
  2. Query Plan   
  3. SELECT STATEMENT Optimizer=CHOOSE (Cost=1234 Card=1 Bytes=14)   
  4. TABLE ACCESS FULL LARGE_TABLE [:Q65001] [ANALYZED] 

在這個例子中,TABLE ACCESS FULL LARGE_TABLE是第一個操作,意思是在LARGE_TABLE表上做全表掃描。當這個操作完成之后,產生的row source中的數據被送往下一步驟進行處理,在此例中,SELECT STATEMENT操作是這個Oracle優化查詢語句的最后一步。

Optimizer=CHOOSE 指明這個查詢的optimizer_mode,即optimizer_mode初始化參數指定的值,它并不是指語句執行時真的使用了該優化器。決定該語句使用何種優化器的唯一方法是看后面的cost部分。例如,如果給出的是下面的形式,則表明使用的是CBO優化器,此處的cost表示優化器認為該執行計劃的代價:

 

  1. SELECT STATEMENT Optimizer=CHOOSE (Cost=1234 Card=1 Bytes=14

然而假如執行計劃中給出的是類似下面的信息,則表明是使用RBO優化器,因為cost部分的值為空,或者壓根就沒有cost部分。

  1. SELECT STATEMENT Optimizer=CHOOSE Cost=   
  2. SELECT STATEMENT Optimizer=CHOOSE 

這樣我們從Optimizer后面的信息中可以得出執行該語句時到底用了什么樣的優化器。特別的,如果Optimizer=ALL_ROWS| FIRST_ROWS| FIRST_ROWS_n,則使用的是CBO優化器;如果Optimizer=RULE,則使用的是RBO優化器。

cost屬性的值是一個在Oracle內部用來比較各個執行計劃所耗費的代價的值,從而使優化器可以選擇最好的執行計劃。不同語句的cost值不具有可比性,只能對同一個語句的不同執行計劃的cost值進行比較。

[:Q65001] 表明該部分查詢是以并行方式運行的。里面的數據表示這個操作是由并行Oracle優化查詢的一個slave進程處理的,以便該操作可以區別于串行執行的操作。

[ANALYZED] 表明操作中引用的對象被分析過了,在數據字典中有該對象的統計信息可以供CBO使用。

例2:

假定A、B、C都是不是小表,且在A表上一個組合索引:A(a.col1,a.col2) ,注意a.col1列為索引的引導列。考慮下面的查詢:

 

  1. select A.col4   
  2. from A , B , C   
  3. where B.col3 = 10 and A.col1 = B.col1 and A.col2 = C.col2 and C.col3 = 5   
  4. Execution Plan   
  5. SELECT STATEMENT Optimizer=CHOOSE   
  6. 0  MERGE JOIN   
  7. 1 SORT (JOIN)   
  8. 2  NESTED LOOPS   
  9. 3 TABLE ACCESS (FULL) OF 'B'   
  10. 3 TABLE ACCESS (BY INDEX ROWID) OF 'A'   
  11. 5  INDEX (RANGE SCAN) OF 'INX_COL12A' (NON-UNIQUE)   
  12. 1 SORT (JOIN)   
  13. 7  TABLE ACCESS (FULL) OF 'C'  
  14. Statistics   
  15. 0 recursive calls   
  16. 8 db block gets   
  17. 6 consistent gets   
  18. 0 physical reads   
  19. 0 redo size   
  20. 551  bytes sent via SQL*Net to client   
  21. 430  bytes received via SQL*Net from client   
  22. 2 SQL*Net roundtrips to/from client   
  23. 2 sorts (memory)   
  24. 0 sorts (disk)   
  25. 6 rows processed  

 

在表做連接時,只能2個表先做連接,然后將連接后的結果作為一個row source,與剩下的表做連接,在上面的例子中,連接順序為B與A先連接,然后再與C連接:
B  <--->  A  <--->  C
col3=10  col3=5

如果沒有執行計劃,分析一下,上面的3個表應該拿哪一個作為第一個驅動表?從SQL語句看來,只有B表與C表上有限制條件,所以第一個驅動表應該為這2個表中的一個,到底是哪一個呢?

B表有謂詞B.col3 = 10,這樣在對B表做全表掃描的時候就將where子句中的限制條件(B.col3 = 10)用上,從而得到一個較小的row source, 所以B表應該作為第一個驅動表。而且這樣的話,如果再與A表做關聯,可以有效利用A表的索引(因為A表的col1列為leading column)。

當然上面的Oracle優化查詢中C表上也有謂詞(C.col3 = 5),有人可能認為C表作為第一個驅動表也能獲得較好的性能。讓我們再來分析一下:如果C表作為第一個驅動表,則能保證驅動表生成很小的row source,但是看看連接條件A.col2 = C.col2,此時就沒有機會利用A表的索引,因為A表的col2列不為leading column,這樣nested loop的效率很差,從而導致查詢的效率很差。

所以對于NL連接選擇正確的驅動表很重要。

因此上面查詢比較好的連接順序為(B - - > A) - - > C。如果數據庫是基于代價的優化器,它會利用計算出的代價來決定合適的驅動表與合適的連接順序。一般來說,CBO都會選擇正確的連接順序,如果CBO選擇了比較差的連接順序,我們還可以使用Oracle提供的hints來讓CBO采用正確的連接順序。如下所示:

 

  1. select /*+ ordered */ A.col4   
  2. from B,A,C   
  3. where B.col3 = 10   
  4. and A.col1 = B.col1   
  5. and A.col2 = C.col2   
  6. and C.col3 = 5 

既然選擇正確的驅動表這么重要,那么讓我們來看一下執行計劃,到底各個表之間是如何關聯的,從而得到執行計劃中哪個表應該為驅動表:在執行計劃中,需要知道哪個操作是先執行的,哪個操作是后執行的,這對于判斷哪個表為驅動表有用處。

判斷之前,如果對表的訪問是通過rowid,且該rowid的值是從索引掃描中得來得,則將該索引掃描先從執行計劃中暫時去掉。然后在執行計劃剩下的部分中,判斷執行順序的指導原則就是:最右、最上的操作先執行。具體解釋如下:

得到去除妨礙判斷的索引掃描后的執行計劃:

  1. Execution Plan    
  2. SELECT STATEMENT Optimizer=CHOOSE   
  3. 0  MERGE JOIN   
  4. 1 SORT (JOIN)   
  5. 2  NESTED LOOPS   
  6. 3 TABLE ACCESS (FULL) OF 'B'   
  7. 3 TABLE ACCESS (BY INDEX ROWID) OF 'A'   
  8. 1 SORT (JOIN)   
  9. 7  TABLE ACCESS (FULL) OF 'C' 

看執行計劃的第3列,即字母部分,每列值的左面有空格作為縮進字符。在該列值左邊的空格越多,說明該列值的縮進越多,該列值也越靠右。如上面的執行計劃所示:第一列值為6的行的縮進最多,即該行最靠右;第一列值為4、5的行的縮進一樣,其靠右的程度也一樣,但是第一列值為4的行比第一列值為5的行靠上;談論上下關系時,只對連續的、縮進一致的行有效。

從這個圖中我們可以看到,對于NESTED LOOPS部分,最右、最上的操作是TABLE ACCESS (FULL) OF 'B',所以這一操作先執行,所以該操作對應的B表為第一個驅動表(外部表),自然,A表就為內部表了。

從圖中還可以看出,B與A表做嵌套循環后生成了新的row source ,對該row source進行來排序后,與C表對應的排序了的row source(應用了C.col3 = 5限制條件)進行MSJ連接操作。所以從上面可以得出如下事實:B表先與A表做嵌套循環,然后將生成的row source與C表做排序—合并連接。

通過分析上面的執行計劃,我們不能說C表一定在B、A表之后才被讀取,事實上,B表有可能與C表同時被讀入內存,因為將表中的數據讀入內存的操作可能為并行的。事實上許多操作可能為交叉進行的,因為Oracle讀取數據時,如果就是需要一行數據也是將該行所在的整個數據塊讀入內存,而且還有可能為多塊讀。

看執行計劃時,我們的關鍵不是看哪個操作先執行,哪個操作后執行,而是關鍵看表之間連接的順序(如得知哪個為驅動表,這需要從操作的順序進行判斷)、使用了何種類型的關聯及具體的存取路徑(如判斷是否利用了索引)

在從執行計劃中判斷出哪個表為驅動表后,根據我們的知識判斷該表作為驅動表(就像上面判斷ABC表那樣)是否合適,如果不合適,對SQL語句進行更改,使優化器可以選擇正確的驅動表。

對于RBO優化器:

在Oracle文檔上說:對于RBO來說,以from 子句中從右到左的順序選擇驅動表,即最右邊的表為第一個驅動表,這是其英文原文:All things being equal RBO chooses the driving order by taking the tables in the FROM clause RIGHT to LEFT。

不過,在我做的測試中,從來也沒有驗證過這種說法是正確的。我認為,即使在RBO中,也是有一套規則來決定使用哪種連接類型和哪個表作為驅動表,在選擇時肯定會考慮當前索引的情況,還可能會考慮where 中的限制條件,但是肯定是與where中限制條件的位置無關。

測試 :如果我創建3個表:

  1. create table A(col1 number(4,0),col2 number(4,0), col4 char(30));   
  2. create table B(col1 number(4,0),col3 number(4,0), name_b char(30));   
  3. create table C(col2 number(4,0),col3 number(4,0), name_c char(30));   
  4. create index inx_col12A on a(col1,col2); 

執行Oracle優化查詢:

  1. select A.col4   
  2. from B, A, C   
  3. where B.col3 = 10   
  4. and A.col1 = B.col1   
  5. and A.col2 = C.col2   
  6. and C.col3 = 5;   
  7. Execution Plan   
  8. SELECT STATEMENT Optimizer=RULE   
  9. 0  MERGE JOIN   
  10. 1 SORT (JOIN)   
  11. 2  NESTED LOOPS   
  12. 3 TABLE ACCESS (FULL) OF 'B'   
  13. 3 TABLE ACCESS (BY INDEX ROWID) OF 'A'   
  14. INDEX (RANGE SCAN) OF 'INX_COL12A' (NON-UNIQUE)   
  15. 1 SORT (JOIN)   
  16. 7  TABLE ACCESS (FULL) OF 'C'  
  17. select A.col4   
  18. from B, A, C   
  19. where A.col1 = B.col1   
  20. and A.col2 = C.col2;   
  21. Execution Plan   
  22. SELECT STATEMENT Optimizer=RULE   
  23. 0  MERGE JOIN   
  24. 1 SORT (JOIN)   
  25. 2  NESTED LOOPS   
  26. 3 TABLE ACCESS (FULL) OF 'B'   
  27. 3 TABLE ACCESS (BY INDEX ROWID) OF 'A'   
  28. 5  INDEX (RANGE SCAN) OF 'INX_COL12A' (NON-UNIQUE)   
  29. 1 SORT (JOIN)   
  30. 7  TABLE ACCESS (FULL) OF 'C'  

 

將A表上的索引inx_col12A刪除后:

  1. select A.col4   
  2. from B, A, C   
  3. where A.col1 = B.col1   
  4. and A.col2 = C.col2;   
  5. Execution Plan   
  6. SELECT STATEMENT Optimizer=RULE   
  7. MERGE JOIN   
  8. 1 SORT (JOIN)   
  9. 2  MERGE JOIN   
  10. 3 SORT (JOIN)   
  11. 4  TABLE ACCESS (FULL) OF 'C'   
  12. 3 SORT (JOIN)   
  13. 6  TABLE ACCESS (FULL) OF 'A'   
  14. 1 SORT (JOIN)   
  15. 8  TABLE ACCESS (FULL) OF 'B' 

通過上面的這些例子,使我對Oracle文檔上的” All things being equal RBO chooses the driving order by taking the tables in the FROM clause RIGHT to LEFT”這句話持懷疑態度。此時,我也不能使用hints來強制優化器使用nested loop,如果使用了hints,這樣就自動使用CBO優化器,而不是RBO優化器了。

【編輯推薦】

  1. Oracle數據庫的統計數據與其生成的具體方式
  2. Oracle加速計劃與推出的新門戶網站簡介
  3. Oracle數據庫提升效率,用3PAR
  4. 支付寶如何用Oracle 11g創建新一代數據的分析
  5. Oracle企業的績效管理統升級版簡介
責任編輯:佚名 來源: 博客園
相關推薦

2010-04-20 09:06:25

Oracle優化

2010-04-27 09:38:57

Oracle修改表ow

2010-05-12 10:17:59

MySQL數據庫優化

2010-05-10 18:38:08

Oracle分頁語句

2017-08-07 15:52:33

Oracleonnect by優化

2010-04-13 15:04:16

Oracle優化

2010-11-18 13:32:12

Oracle分頁查詢

2011-09-08 16:30:59

SQL Server查詢

2010-10-27 10:11:07

Oracle分頁查詢

2009-04-09 13:14:09

Oracle分頁查詢CBO

2011-08-11 17:17:56

Java

2009-01-04 17:41:07

2010-05-04 15:15:39

Oracle分頁查詢

2010-10-27 15:34:37

oracle查詢

2009-03-04 09:06:56

優化sqlOracle

2010-04-02 10:04:21

Oracle結構

2010-04-20 15:58:15

Oracle 語句

2010-05-07 11:00:25

Oracle多表查詢

2010-04-12 17:47:01

Oracle多表查詢

2010-05-21 09:13:01

MySQL數據庫查詢
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产亚洲二区 | 亚洲一区二区三区在线视频 | 日韩精品视频在线 | 99免费在线视频 | 一区二区精品 | 日韩精品区 | 成人在线国产 | 久热伊人 | 99精品九九 | 欧美一区二区二区 | 日韩精品一区二区三区视频播放 | 91在线播 | 午夜伦理影院 | 国产精品日韩一区二区 | 成人精品福利 | 精品无码久久久久久国产 | 亚洲视频www | 一级毛片免费完整视频 | 免费在线观看av网址 | 日韩高清一区 | 日韩毛片 | 亚洲精品99 | 成人av色| 国产欧美在线观看 | 久久久久久国产一区二区三区 | 午夜影院网站 | 欧美一级二级在线观看 | 嫩呦国产一区二区三区av | 99色在线视频 | 四虎影视免费在线 | 91最新视频 | 中文字幕在线观看一区二区 | 国产成人精品一区二区三区在线 | 亚洲福利精品 | 成人亚洲精品久久久久软件 | www.久久久久久久久久久久 | 成人一区二区视频 | 国产精品爱久久久久久久 | 日韩有码一区 | 久久久久久国产免费视网址 | 精品国产一区二区三区日日嗨 |