首次Oracle SQL Tuning經歷

2021-05-24 01:43:01 字數 4464 閱讀 3755

原來的sql是這樣的:一共牽涉5張表,表名和 每張表的索引情況如下:

tableindex nameindex infomation

table_item

item_pk

primary key (id)

table_item

item_lm_idx

last_modified asc

table_attr

attr_pk

primary key (id)

table_desc

desc_pk

primary key (id)

table_delay

delay_pk

primary key (id, partition_key)

table_product

product_p_pk

primary key(product_id)

select … from , table_desc , table_product , table_attr , table_delayed

where

(table_item.id = table_desc.id)

and (table_item.product_id = table_product.product_id(+))

and (table_item.id = table_attr.id(+))

and (table_item.id = table_delay.id(+))

and (table_item.last_modified between to_date( :start_time, 『yyyy-mm-dd hh24:mi:ss』 )

and to_date( :end_time , 『yyyy-mm-dd hh24:mi:ss』 ) 

)order by table_item.last_modified;

使用的db hint 是:

/*+ index(table_item item_lm_idx) use_nl(table_delay) index(table_delay delay_pk) */

sql>  explain plan for

select …

sql>  @?/rdbms/admin/utlxpls

由於列印格式不同,我就不把執行計畫貼出來了,執**況良好:

所有的表都使用的了索引,index range scan或者index unique scan

執行join的時候使用了nested loops或者nested loops outer

沒有發現sort join和merge join沒有發現table access full –> full table scan

我們發現即使在sql中有order by table_item.last_modified,在sql執行計畫中也沒有出現任何sort有關的資訊,一般在sql中盡量不要使用order by,因為在db server端進行sort是很耗費資源的。但是有乙個例外,就是表中的資料已經排好序的情況下,我們這裡就是這樣的哦情況,執行計畫中沒有sort是因為當從table_item表中以 table_item.last_modified between :start_time and :end_time取資料時,走的是item_lm_idx –>last_modified asc, 所以取出來的資料本身已經按照last_modified 排好序了。

但是我更改過的sql是這樣的:

where table_item.last_modified=:start_time and table_item.id>:last_id order by table_item.id

讓我悲哀的是這條修改過的sql在有些資料庫伺服器上的執行計畫是好的,有些不好。dba給我的解釋是並不是所有的表的統計資訊都是更新過的,於是在那些統計資訊沒有更新的表上的執行計畫很有可能就不對了。不如說這個:

00 select statement

01     merge join outer

02         nested loops outer(將item,product,desc的結果和table_delay進行nested join)

03             merge join(由兩個sort join的結果組成,得到item,product,desc3張表的join結果)

04                 sort join(將table_item和table_product的結果按照id進行排序)

05                    nested loops outer(將table_item和table_product進行nested outer join)

06                         table access by index rowid   –> table_item

07                             index range scan                 –> item_lm_idx(使用item_lm_idx索引)

08                         table access by index rowid   –> table_product

09                             index unique scan               –>  product_p_pk

10                 sort join(將table_desc滿足條件的記錄按照id進行排序)

11                    table access by index rowid       –> table_desc

12                          index range scan                   –>  rtable_desc_pk

13             partition range all

14                 table access by local index rowid  –> table_delay

15                     index range scan                         –> delay_pk

16         sort join

17             table access full                                –> table_attr

注意到使用了很多merge sort,而處理table_attr的時候更是出現了full table scan,更本就不使用索引。這裡說句老實話,我不知道是不是應該dba更新統計資訊,重新給相關的表更新一下統計資訊,還是就趕緊改一下db hint把自己的事情做完就算。不過我也理解的,ebay的資料庫太大了,不是隨便想做什麼就行的,最後我還是選擇了修改db hint.

ticket resolve的結果是,修改db hint :

/*+

index_asc(table_attr attr_pk)

index(table_item item_lm_idx)

use_nl(table_item table_attr table_desc table_delayed table_product) index(table_delay delay_pk)

index(table_product product_p_pk)

index(table_desc rtable_desc_pk)

*/ 給所有的表都制定index,建議oracle對所有的表都使用nested loops join。重新看一下執行計畫:

00  select statement

01      sort order by

02          nested loops outer

03              nested loops outer

…(以下省略)

可以看到,修改db hint以後,只有對最後的結果進行sort,這也是我們的初衷。沒有sort join和merge join了。速度也快了很多。因為ebay的db是split的,dba為了保險,幫我把這條修改過的sql對該資料庫所有的splits都執行了一次,才把ticket標識成resolved.

我剛把**改了,新增了判斷,如果執行新的sql就使用修改的hint。待會給qa測試,idc的sunil還不肯發bug給我,因為他在qa環境沒有觀察到這個問題,甚至的production standby db也不能重現。這一點只能用樓上dba的話來解釋了:雖然是同乙個db的不同的split,但是不同的splits之間資料還是有差異,統計資料也不同,結果是影響oracle做出判斷,所以他們做sql review的時候都是要執行一下的,而不是光看看執行計畫。

謝謝coc dba team的amao和alex給我上了一課。          

mysql首次 mysql 首次安裝及問題解決

2017年9月27日 安裝並配置mysql 安裝路徑為d mysql 5.7.19 winx64 2.生成mysql的配置檔案my.ini 放置路徑為d mysql 5.7.19 winx64 3.my.ini 配置資訊 mysql 設定mysql客戶端預設字符集 default character...

首次接觸DirectDraw

directdraw 1.directdraw可能是directx中最重要的技術,因為它溝通了2d圖形的顯示和direct3d所依賴的真緩衝層。只要掌握了directdraw,就能夠編寫各種在dos16 32下編寫的圖形應用程式。directdraw是理解directx中許多概念的關鍵,所以要特別注...

GDrive首次現身!

還記得gdrive麼?自從它第一次出現在google的洩露文件上,它就成為了世界關注的焦點。根據傳言,gdrive將會是google要推出的網路儲存服務,類似於網路硬碟,但它的容量是無限的。在這個訊息洩露後,google馬上把相關的文件給刪除了,這反而令人覺得gdrive並非只是謠言。隨後微軟自己也...