oracle之使用Oracle Developer對SQL進行簡單調優(二)


使用Oracle DeveloperSQL進行簡單調優

         Oracle Developer是Oracle提供的免費數據庫連接工具,行內數據中心生產操作間默認使用該工具執行SQL,如遇到現場需要對生產SQL進行優化查詢的需要熟悉Oracle Developer的基本使用,本文結合Oracle Developer工具展示如何查看SQL,如果進行基本優化。

一、 Oracle Developer  Oracle 命令

1. Oracle Developer

    SQL解釋

    Oracle Developer工具里面的“解釋”功能只針對當前的sql進行了一個預估的資源消耗以及執行路徑,參考數據是系統里存在的表統計信息。結果顯示與實際執行可能存在差異,且表的詳細信息,在其它功能下顯示更為詳細。

    SQL優化指導

    Oracle Developer工具里面的sql優化指導功能,對要優化分析的sql進行了真實的執行,該功能展示的結果,包含了部分解釋功能的結果,也就是根據表里面的統計信息預估的執行計划;它一般還包含優化建議;另外還展示了該sql的實際執行計划和並行執行時的sql性能結果。 

    SQL跟蹤

    Oracle Developer工具里面的sql跟蹤功能,對要優化分析的sql進行了實際的執行,詳細的展示了執行過程中對 索引 CPU 緩存IO和塊的改變情況,也列出了執行過程中涉及的數據量和資源消耗;此功能包含了sql解釋中的表統計信息。

2. Oracle命令

     autotrace

            Oracle命令 autotrace是分析sql真實執行計划,查看sql執行效率的一個比較簡單又方便的工具。它實際上是對sql實際執行過程信息的一個收集和信息統計。

            set autotrace on開啟autotrace后面執行sql語句會自動顯示sql執行結果和跟蹤信息

            set auto traceonly; 僅顯示跟蹤信息。

            set auto on explain; 僅顯示跟蹤的explain信息。

         set auto on statistics 僅顯示跟蹤的統計信息。

         set autotrace off關閉跟蹤

    explain plan for

          Oracle命令explain查看執行計划時oracle沒有真實執行sql語句。所以生成的執行計划未必是真實的,而且還必須借助plan_table才能看到詳細信息,具體使用方式如下:

         explain plan for + select * from table where ...

         select * from TABLE(DBMS_XPLAN.DISPLAY);

二、 掃的SQL

1. 解釋計划

  在查詢界面選中一條sql,按F10,或者右鍵點擊解釋選項,出現該sql的解釋計划:

     此處顯示Oracle估算后給出的解釋計划:

     雙擊表名打開表的詳細統計信息,此部分提供了表的數據,約束條件,字段定義類型,索引,分區等詳細信息。

 

 

 

        注意:預估的解釋計划和實際的執行計划可能不相同,預估的解釋計划是oracle根據最新的統計信息產生的執行計划,實際sql執行時oracle會根據當時系統的負載情況(可能不是最新的統計信息),涉及的數據量,是否有綁定變量,有沒有物理讀等信息,通過優化器進行的執行策略選擇。所以采用dbms_xplan.display_cursor(sql_id,child_number,format)函數查看實際的sql執行計划;通過查看預估的執行計划確定統計信息的新舊。

2. SQL優化指導

   選中sql點擊右鍵,選中優化指導,出現執行計划信息

 

      優化指導內容解析,基本信息區域:

 

   優化建議區域:當Oracle分析執行的SQL后發現有更優的解釋計划時會在優化建議區給出提示:

 

 

 

 

   解釋計划區域,hash值與解釋計划里面的一樣,該部分顯示包括了解釋計划的信息:

 

    推薦的sql優化修改,該信息可以作為參考,本示例種給出的優化方案是開啟sql的並行

 

 

 

 

     PX COORDINATOR 並行執行協調者,屬於並行執行的第一步,負責並行語句的初始化,且將並行操作分解,按照一定策略將分解后的子任務下發給並行服務會話。

     PX SEND QC(RANDOM) 並行服務進程通過表隊列將數據隨機發給協調者

     PX BLOCK ITERATOR 並行顆粒度,block iterator把表分割成多個塊,每個塊由涉及的並行服務進程中的一個去處理。它常和TABLE ACCESS FULL成對出現,意味着全表掃描。

     TABLE ACCESS FULL 全表掃描

3. 真實的執行計划

 使用autotrace(注意autotrace traceonlysql會被真實執行如果不想執行請用explain plan for)查詢sql實際執行計划與解釋計划結果一致:

 

 

 

 

    Recursive calls :執行該條語句時,對其他sql語句的調用次數,這種調用包含對該用戶下的sql或者是系統的sql。

    db block gets:Number of times a CURRENT block was requested. non consistent gets)非一致性讀,當前SQL執行時點獲取的塊數,從數據緩沖區中讀取。

    consistent gets:Number of times a consistent read was requested for a block.一致性讀,為了保證數據一致性,在數據緩沖區包括回滾段中讀取的數據塊。

    physical reads:物理讀,從磁盤上讀取的數據塊。

    邏輯讀指的是從數據緩沖區(內存)中讀到的數據塊,由於從內存讀取,因此相對於從磁盤讀取要快的多。

 邏輯讀 = db block gets+ consistent gets

 查詢命中率需要的數據:select name,value from v$sysstat where name in ('db block gets','consistent gets','physical reads');

 命中率=1-(physical reads/(db block gets+ consistent gets))

    Redo size:執行DML語句產生的重做日志大小

    Sorts(memory,disk)在內存或者磁盤中的排序的數量。

  注意:以上信息我們關注的主要是物理讀和命中率,物理讀過多說明從磁盤獲取的數據就多,可能存在全表掃描,使得數據庫的性能下降。命中率過低意味1、物理讀過多2、數據緩沖區設置過小,此時需要確認緩沖區合理大小,該值一般在90%以上。

三、 索引的SQL

1. 解釋計划

 

 

 

 

sql解釋計划不建議在優化中使用,顯示信息量不足。

2. SQL優化指導

 

因為此時走索引,實際的執行計划和預估的解釋情況一致,所以沒有顯示執行計划

 

3. 真實的執行計划

使用dbms_xplan.display_cursor(sql_id,child_number,format)函數查詢結果與執行結果一致。

 

四、 核心系統SQL示例

數據庫表上沒有索引進行如下查詢:

select logId, bxid, txid, logIndex, content as contentByte, status from ensemble.dtp_submitlog where bxid='4AF600F207DF4D07BF45AF7008CFF18B' and status='done' order by logIndex;

1. SQL優化指導

Sql優化給出2條建議,第1條建議走索引:

 

2條建議開啟並行查詢:

 

 

 

 

2. 真實的執行計划

使用“自動跟蹤”查看真實的執行計划:

 

 

 

 

 

 

 

 

 

 

使用dbms.display_cursor也可以查看真實的執行計划:

select sql_id,child_number from v$sql where sql_text like '%from ensemble.dtp_submitlog where bxid=%';

select * from TABLE(DBMS_XPLAN.DISPLAY_CURSOR(sql_id,0));

 

SQL優化給出走索引效率更高,開啟並行查詢走的也是全表掃描,一般不推薦。

經查詢該表上沒有適合的索引:

 

bxid和status上創建組合索引之后再次執行結果如下:

3. 優化后的執行計划

自動跟蹤結果如下:

 

 

 

 

 

 

 

查詢結果:

 

SQL優化該模塊已經沒有創建索引的優化建議了,執行過程也顯示走了索引。

 

 

五、 嵌套循環(nested loops

1. 連接訪問次數

大部分表連接走的都是嵌套循環,但如果兩個表的結果集比較接近,又沒有合適的索引,則可能走哈希索引,本章節以測試表為例,通過hint強制嵌套查詢:

新建測試表mb_ac_hist_test1,mb_acct_test2,數據從mb_acct和mb_tran_hist表中復制,表內數據量如下:

 

通過hint:/*+leading(a) use_nl(b)*/ 強制指定兩個表之間的連接走嵌套循環,為了查看更詳細的執行計划,需要通過sqlplus / as sysdba登錄,並SQL前執行statistics_level = allSQL后執行SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL,'runstats_last'))

select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key;

執行計划如下:

 

1行表示連接方式為NESTED LOOPS,第2、3行屬於同一縮進,同一縮進下執行操作由上到下,第1個表mb_ac_hist_test1(leading(a))是全表掃描(TABLE ACCESS FULL),是驅動表,第2個表mb_acct_test2(use_nl(b))也是全表掃描(TABLE ACCESS FULL),是被驅動表

Starts表示表被訪問了幾次,是主要關注的指標。E-Row表示估算的行數,A-Rows表示實際返回的行數,如果兩者差別較大則說明執行計划有問題,需要更新統計值,A-Time表示實際執行時長,Buffers表示邏輯讀,Reads表示物理讀。

2. 表連接的驅動順序

驅動表和被驅動表的選擇會對SQL效率有很大影響,示例:

select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key;

 

將驅動表和被驅動表進行顛倒:

select /*+leading(b) use_nl(a)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key;

 

小結:驅動表的先后順序影響sql執行的性能,當mb_acct_test2(66萬多數據)表屬於驅動表時,訪問被驅動表次數就是66萬多次,消耗時間3.65s。當mb_ac_test1(6條數據)為驅動表時,時間消耗是0.01s。對比兩次訪問同一個表的時間相差巨大,因此在優化過程中,使用嵌套循環時,我們應該遵循盡量減少被驅動表的訪問次數,結果集小的表做驅動表,結果集大的表做被驅動表,從而提升sql的性能。

3. 嵌套循環的使用場景

限制條件字段創建索引

操作步驟:

1、select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and b.base_acct_no ='1000890001500000403';

 

2、create index index_mb_ac_hist_test1 on ensemble.mb_ac_hist_test1(base_acct_no);//在驅動表上創建索引

3、select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and b.base_acct_no ='1000890001500000403';//限制條件在被驅動表上,查詢走全表掃描。

 

4select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and a.base_acct_no ='1000890001500000403';//限制條件在驅動表上,查詢走索引

 

5、create index index_acct_test2 on ensemble.mb_acct_test2(base_acct_no);//在被驅動表上創建索引

6、select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and a.base_acct_no='1000890001500000403';// 限制條件在被驅動表上,查詢走全表掃描   

7、select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and b.base_acct_no ='1000890001500000403';//限制條件在被驅動表上,查詢走索引

從以上結果來看,索引創建的位置與限制條件所在的表相關,與驅動表和被驅動表無關。在限制條件的表上創建索引之后,性能才有了明顯的提升,不管是執行時間還是buffer的使用,資源使用明顯降低。

連接條件創建索引

嵌套循環驅動表和被驅動表的連接條件上添加索引會有效提高查詢效率,但索引建立在驅動表上還是被驅動表上會提高效率,示例如下:

select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and b.base_acct_no ='1000890001500000403';

 

在被驅動表上建立索引:

create index index_inernal_key on ensemble.mb_acct_test2(INTERNAL_KEY);

重新執行sql語句,執行計划如下:

select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and b.base_acct_no ='1000890001500000403';

 

嵌套查詢中使用了被驅動表的索引有效降低了表的訪問和掃描。

在驅動表的上建立索引:

create index index_inernal_key on ensemble.mb_ac_hist_test1(INTERNAL_KEY);

select /*+leading(a) use_nl(b)*/* from ensemble.mb_ac_hist_test1 a,ensemble.mb_acct_test2 b where a.internal_key=b.internal_key and b.base_acct_no ='1000890001500000403';

 

嵌套查詢依然是全表掃描,驅動表上建立的索引沒有起到作用。

 

 

從建立索引前后的執行結果來看,在被驅動表的連接條件上創建索引之后,性能有明顯提升,因為Oracle先從驅動表里獲取符合條件的記錄,然后根據連接字段,從被驅動表的連接字段上連接查詢,顯然被驅動表連接字段上有索引會大大提升性能。而驅動表的連接字段上新建索引對性能提升沒有明顯效果。

增加索引之后不用hint強制選擇loop循環,系統依然會選擇使用loop循環:

 

 

 

左連接

一般左連接在業務sql中也比較常見,在走嵌套循環的情況下和內連接基本一樣:

沒有索引的時候執行sql:

select * from ensemble.mb_ac_hist_test1 a left outer join ensemble.mb_acct_test2 b on a.internal_key=b.internal_key;

 

在從表的連接字段上新增索引:

create index index_inernal_key on ensemble.mb_ac_hist_test1(INTERNAL_KEY);

重新執行sql:

select * from ensemble.mb_ac_hist_test1 a left outer join ensemble.mb_acct_test2 b on a.internal_key=b.internal_key;

 

從選擇連接方式來看:建立索引前后來看左連接在走全表掃描的情況下選擇hash方式連接,建立索引之后選擇循環連接。

4. 嵌套循環小結

嵌套循環首先關注驅動順序,驅動表的返回結果集應該盡量少,驅動表的限制條件字段上新建索引會有效提高驅動表的性能被驅動表連接字段上新建索引會有效提高被驅動表的性能。

v 嵌套循環對連接條件沒有限制,<>、>、<、like都可以處理。不等值查詢系統默認走嵌套循環。

六、 總結

      如果使用Oracle Developer工具做優化,建議不要使用SQL解釋;直接使用SQL自動跟蹤、SQL優化和執行dbms語句結合使用。SQL自動跟蹤直接體現了實際的執行計划,SQL優化提供了優化建議,dbms的系統存儲過程提供了更豐富的查詢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM