自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

游標(biāo)腳本性能問題詳解之案例實踐篇

數(shù)據(jù)庫 SQL Server 數(shù)據(jù)庫運(yùn)維
關(guān)系數(shù)據(jù)庫中的操作會對整個行集起作用。由 SELECT 語句返回的行集包括滿足該語句的 WHERE 子句中條件的所有行。這種由語句返回的完整行集稱為結(jié)果集。應(yīng)用程序并不總能將整個結(jié)果集作為一個單元來有效地處理。這些應(yīng)用程序需要一種機(jī)制以便每次處理一行或一小部分行。游標(biāo)不僅可提供這種機(jī)制,而且是對結(jié)果集的一種擴(kuò)展。

游標(biāo)類型對性能影響的實例。下面的兩個游標(biāo)腳本分別創(chuàng)建并執(zhí)行了dynamic和fast forward only兩種類型的游標(biāo)。

知識補(bǔ)充:

關(guān)系數(shù)據(jù)庫中的操作會對整個行集起作用。由 SELECT 語句返回的行集包括滿足該語句的 WHERE 子句中條件的所有行。這種由語句返回的完整行集稱為結(jié)果集。應(yīng)用程序并不總能將整個結(jié)果集作為一個單元來有效地處理。這些應(yīng)用程序需要一種機(jī)制以便每次處理一行或一小部分行。游標(biāo)不僅可提供這種機(jī)制,而且是對結(jié)果集的一種擴(kuò)展。

游標(biāo)通過執(zhí)行以下操作來擴(kuò)展結(jié)果集處理:

  1. 允許定位在結(jié)果集的特定行。
  2. 從結(jié)果集的當(dāng)前位置檢索一行或一部分行。
  3. 支持對結(jié)果集中當(dāng)前位置的行進(jìn)行數(shù)據(jù)修改。
  4. 為由其他用戶對顯示在結(jié)果集中的數(shù)據(jù)庫數(shù)據(jù)所做的更改提供不同級別的可見性支持。

不理想的游標(biāo)類型:(dynamic游標(biāo))

  1. declare @p1 int  set @p1=NULL    
  2. declare @p2 int  set @p2=0    
  3. declare @p5 int  set @p5=4098  
  4. declare @p6 int  set @p6=8193    
  5. declare @p7 int  set @p7=0    
  6.  
  7. exec sp_cursorprepexec @p1 output,@p2 output,N'@P1 varchar(30),@P2 varchar(15)',  
  8. N'  
  9. SELECT       T1.CONFLICT_ID  
  10. FROM         dbo.S_AUDIT_ITEM T1              
  11. LEFT OUTER JOIN dbo.S_USER T2   
  12. ON T1.USER_ID = T2.PAR_ROW_ID      
  13. WHERE  ((T1.BC_BASE_TBL = @P1)    
  14. AND  (T1.RECORD_ID = @P2))      
  15. ORDER BY  T1.OPERATION_DT DESC    
  16. OPTION (FAST 40)  
  17. ',  
  18. @p5 output,@p6 output,@p7 output,'1-10350J','S_PARTY'    
  19.  
  20. print 'fetch' 
  21. exec sp_cursorfetch @p2,2,4,1    
  22.  
  23. exec sp_cursorclose @p2 

理想的游標(biāo)類型(fast forward only游標(biāo))

  1. declare @p1 int  set @p1=NULL    
  2. declare @p2 int  set @p2=0    
  3. declare @p5 int  set @p5=4112  
  4. declare @p6 int  set @p6=8193    
  5. declare @p7 int  set @p7=0    
  6.  
  7. exec sp_cursorprepexec @p1 output,@p2 output,N'@P1 varchar(30),@P2 varchar(15)',  
  8. N'  
  9. SELECT       T1.CONFLICT_ID  
  10. FROM         dbo.S_AUDIT_ITEM T1              
  11. LEFT OUTER JOIN dbo.S_USER T2   
  12. ON T1.USER_ID = T2.PAR_ROW_ID      
  13. WHERE  ((T1.BC_BASE_TBL = @P1)    
  14. AND  (T1.RECORD_ID = @P2))      
  15. ORDER BY  T1.OPERATION_DT DESC    
  16. OPTION (FAST 40)  
  17. ',  
  18. @p5 output,@p6 output,@p7 output,'S_SRV_REQ','1-WUQTM6'    
  19.  
  20. select @p1, @p2, @p5, @p6, @p7  
  21.  
  22. print '2' 
  23. exec sp_cursorfetch @p2,2,1,1    
  24. print '3' 
  25. exec sp_cursorclose @p2 

注:腳本中用到的和游標(biāo)有關(guān)的存儲過程,請參考:http://jtds.sourceforge.net/apiCursors.html#_sp_cursorprepexec

一、如何解讀游標(biāo)的類型

  1. sp_cursorprepexec [@handle =] statement_handle OUTPUT,  
  2.      [@cursor =] cursor_handle OUTPUT,  
  3.      [@paramdef =] N'parameter_name data_type, [,...n]'   
  4.      [@stmt =] N'stmt',  
  5.      [, [@scrollopt =] scroll_options OUTPUT]  
  6.      [, [@ccopt =] concurrency_options OUTPUT]  
  7.      [, [@rowcount =] rowcount OUTPUT]  
  8.  
  9. @scrollopt  

 

[@ccopt

 

@p5=4098 轉(zhuǎn)成16進(jìn)制就是1002,對應(yīng)的游標(biāo)類型為Parameterized query + Dynamic cursor

@p5=4112 轉(zhuǎn)成16進(jìn)制就是1010,對應(yīng)的游標(biāo)類型為Parameterized query + Fast forward-only cursor

問題的現(xiàn)象是,左邊的游標(biāo)類型下,該腳本執(zhí)行時間遠(yuǎn)大于右邊的游標(biāo)類型。

#p#

二、如何比較兩個不同執(zhí)行計劃的優(yōu)劣

在繼續(xù)以下內(nèi)容之前,這里要介紹一些查看和比較語句執(zhí)行計劃的知識。通常情況下,我們從management studio中輸出圖形界面的執(zhí)行計劃進(jìn)行直觀的比較,查看每個表用的訪問方式,使用index還是table scan,使用了哪個index,表和表之間使用的join 方式有什么不一樣。但是如果是一個復(fù)雜的語句,在不同的數(shù)據(jù)庫上使用了不同的執(zhí)行計劃,對于同樣表的訪問,使用了不同的index,如何比較哪種執(zhí)行計劃更加優(yōu)化呢?比較整個語句的執(zhí)行時間是一種方法,但是這個比較的結(jié)果并不準(zhǔn)確。語句的執(zhí)行時間很容易受到其他外在因素的影響:

1. 不同機(jī)器上CPU,memory和disk的性能會影響執(zhí)行時間。

2. 測試的時候有沒有其他人在使用同樣的數(shù)據(jù)造成阻塞

3. 其他人堆數(shù)據(jù)庫的使用占用了系統(tǒng)資源

以上這些原因都有可能影響的語句的執(zhí)行時間,從而影響到我們對語句性能結(jié)果的比較。因此我們不能把語句的執(zhí)行時間作為衡量語句性能的標(biāo)準(zhǔn)。

這里介紹一種比較語句cost的方法。我們對于語句cost的衡量,主要是通過比對語句總的logical reads.

我們可以通過在management studio里的query window 執(zhí)行”set statistics io on” ,在當(dāng)前窗口中對所有執(zhí)行的語句輸出信息:

  1. set statistics io on 
  2. select * from dbo.test_TicketFact  
  3. set statistics io on 

執(zhí)行語句兩次,以消除physical reads和read-ahead reads的影響。

輸出的結(jié)果如下:

  1. (320 row(s) affected)  
  2. Table 'test_TicketFact'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.  

這里打印出來了語句中訪問過的table的訪問次數(shù),總共的logical reads,physical reads等信息

這里我們需要關(guān)注的是logic reads的值,這個值實際上決定了對于IO和DISK以及內(nèi)存的消耗。當(dāng)語句是第一次執(zhí)行,我們會看到physical reads的數(shù)字,以,而當(dāng)語句第二次執(zhí)行的時候,這些數(shù)據(jù)已經(jīng)被讀到memory里面了,因此我們會看到physical read和read-ahead reads都變?yōu)?,而logical reads的值就變成了語句所有使用的data的量。

為什么logic reads是我們需要關(guān)注的值呢?因為logic reads決定了語句要訪問數(shù)據(jù)的量。如果我們的系統(tǒng)瓶頸在IO上,一旦語句需要訪問的數(shù)據(jù)從內(nèi)存里面清除,這個語句原本所有的logic reads會全部轉(zhuǎn)為physical reads.因此那些大量使用logic reads就是可能導(dǎo)致大量physical reads的元兇。如果我們的bottleneck是CPU,這些做大量logical reads的語句同樣有可能導(dǎo)致大量的memory 讀,而讀memory是需要消耗CPU資源的。因此,無論是CPU,memory還是DISK的瓶頸,那些做大量logical reads的語句都非??赡苁窃斐蓡栴}的原因。

由以上內(nèi)容,我們可以得出結(jié)論,語句的性能好壞,取決與這個語句做了多少logical reads.因此,如果同樣的語句,使用了不同的執(zhí)行計劃,那么總的logical reads低的那個執(zhí)行計劃就是相對優(yōu)化的。

#p#

三、分析本案例中兩種游標(biāo)的執(zhí)行計劃

現(xiàn)在我們回到需要研究的腳本,在這里,語句是一樣的,不同的只是游標(biāo)的類型。不同的執(zhí)行時間說明很可能這個語句使用了不同的執(zhí)行計劃?,F(xiàn)在問題變成了,同樣語句使用了不同的執(zhí)行計劃,得到了不同的執(zhí)行時間。我們首先從”set statistics io on” 的結(jié)果入手:

1.左邊使用dynamic游標(biāo)有大量的邏輯讀,情況如下:

  1. Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.  
  2. Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.  
  3. Table 'S_AUDIT_ITEM'. Scan count 1, logical reads 9770695, physical reads 0, read-ahead reads 1, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.  

2.而右邊使用fast forward only游標(biāo)只有三次邏輯讀,情況為:

  1. Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.  
  2. Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.  
  3. Table 'S_AUDIT_ITEM'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

從這里輸出的結(jié)果的區(qū)別,說明了在table S_AUDIT_ITEM上SQL Server使用了不同的訪問方式

接下來我們分析兩個腳本的執(zhí)行計劃:

1. dynamic游標(biāo)對應(yīng)的不理想的執(zhí)行計劃中,SQL Server選擇了索引掃描(index scan)及索引S_AUDIT_ITEM_M4來查閱S_AUDIT_ITEM表。因此我們會在這里看到大量的IO。

 

這個索引掃描實際上訪問了整張表的數(shù)據(jù)。

2.而fast forward only游標(biāo)對應(yīng)的理想的執(zhí)行計劃中,SQL Server選擇的是索引查找(index seek)及索引S_AUDIT_ITEM_M3來查閱S_AUDIT_ITEM表。所以我們只看到3個邏輯讀。索引S_AUDIT_ITEM_M3包含4個列,第一個列是RECORD_ID。另外,在語句中,有WHERE條件T1.RECORD_ID=@P2

 

#p#

四、嘗試解決問題

首先我們嘗試更新統(tǒng)計信息:UPDATE STATISTICS ON S_AUDIT_ITEM WITH FULLSCAN,但是這個操作在此問題案例中沒有作用。

從以上的分析中,我們已經(jīng)發(fā)現(xiàn),如果使用index S_AUDIT_ITEM_M3訪問S_AUDIT_ITEM表,得到的執(zhí)行計劃非常好,我們可以直接用index hint來解決這個問題:

  1. declare @p1 int set @p1=NULL 
  2.  
  3.   declare @p2 int set @p2=0  
  4.  
  5.   declare @p5 int set @p5=4098  
  6.  
  7.   declare @p6 int set @p6=8193  
  8.  
  9.   declare @p7 int set @p7=0  
  10.  
  11.   exec sp_cursorprepexec @p1 output,@p2 output,N'@P1 varchar(30),@P2 varchar(15)',  
  12.  
  13.   N'  
  14.  
  15.   SELECT T1.CONFLICT_ID  
  16.  
  17.   FROM dbo.S_AUDIT_ITEM T1 with (INDEX=S_AUDIT_ITEM_M3) /* 解決方案2 */  
  18.  
  19.   LEFT OUTER JOIN dbo.S_USER T2  
  20.  
  21.   ON T1.USER_ID = T2.PAR_ROW_ID  
  22.  
  23.   WHERE ((T1.BC_BASE_TBL = @P1)  
  24.  
  25.   AND (T1.RECORD_ID = @P2))  
  26.  
  27.   ORDER BY T1.OPERATION_DT DESC 
  28.  
  29.   OPTION (FAST 40)  
  30.  
  31.   ',  
  32.  
  33.   @p5 output,@p6 output,@p7 output,'1-10350J','S_PARTY' 
  34.  
  35.   print 'fetch' 
  36.  
  37.   exec sp_cursorfetch @p2,2,4,1  
  38.  
  39.   exec sp_cursorclose @p2  
  40.  

 

責(zé)任編輯:艾婧 來源: ITPUB
相關(guān)推薦

2011-04-06 09:30:29

游標(biāo)腳本性能問題

2011-04-07 11:02:52

游標(biāo)

2010-05-26 18:08:30

Linux性能監(jiān)控

2015-09-16 15:48:55

Android性能優(yōu)化電量

2015-09-16 14:37:50

Android性能優(yōu)化運(yùn)算

2015-09-16 13:54:30

Android性能優(yōu)化渲染

2012-09-10 09:39:31

Hadoop成功部署案例eBay

2011-03-02 11:25:10

vsftpd配置

2023-07-10 16:18:18

性能優(yōu)化開發(fā)

2010-02-07 13:55:12

萬兆交換機(jī)

2011-04-18 10:16:30

WEB高性能

2010-05-26 18:21:04

Linux性能監(jiān)控

2010-05-26 18:31:51

Linux性能監(jiān)控

2011-11-08 21:47:37

Linux 監(jiān)控 IO

2010-05-26 18:40:54

Linux性能監(jiān)控

2018-09-03 09:22:25

監(jiān)控服務(wù)器性能

2020-03-17 09:21:20

MariaDBSpider存儲

2012-06-15 10:13:03

2011-07-22 09:50:34

云服務(wù)云計算

2022-05-26 10:12:21

前端優(yōu)化測試
點贊
收藏

51CTO技術(shù)棧公眾號