国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫技術|

服務器之家 - 數(shù)據(jù)庫 - Sql Server - SQLServer 參數(shù)化查詢經驗分享

SQLServer 參數(shù)化查詢經驗分享

2019-11-24 16:42MSSQL教程網 Sql Server

本篇文章將介紹參數(shù)化查詢。我將討論如果一個查詢可以被參數(shù)化,那么SQL Server優(yōu)化器怎樣嘗試將其參數(shù)化,以及你可以怎樣建立你自己的參數(shù)化查詢。

什么是參數(shù)化查詢? 
  一個簡單理解參數(shù)化查詢的方式是把它看做只是一個T-SQL查詢,它接受控制這個查詢返回什么的參數(shù)。通過使用不同的參數(shù),一個參數(shù)化查詢返回不同的結果。要獲得一個參數(shù)化查詢,你需要以一種特定的方式來編寫你的代碼,或它需要滿足一組特定的標準。

  有兩種不同的方式來創(chuàng)建參數(shù)化查詢。第一個方式是讓查詢優(yōu)化器自動地參數(shù)化你的查詢。另一個方式是通過以一個特定方式來編寫你的T-SQL代碼,并將它傳遞給sp_executesql系統(tǒng)存儲過程,從而編程一個參數(shù)化查詢。這篇文章的后面部分將介紹這個方法。

  參數(shù)化查詢的關鍵是查詢優(yōu)化器將創(chuàng)建一個可以重用的緩存計劃。通過自動地或編程使用參數(shù)化查詢,SQL Server可以優(yōu)化類似T-SQL語句的處理。這個優(yōu)化消除了對使用高貴資源為這些類似T-SQL語句的每一次執(zhí)行創(chuàng)建一個緩存計劃的需求。而且通過創(chuàng)建一個可重用計劃,SQL Server還減少了存放過程緩存中類似的執(zhí)行計劃所需的內存使用。

  現(xiàn)在讓我們看看使得SQL Server創(chuàng)建參數(shù)化查詢的不同方式。

  參數(shù)化查詢是怎樣自動創(chuàng)建的?

  微軟編寫查詢優(yōu)化器代碼的人竭盡全力地優(yōu)化SQL Server處理你的T-SQL命令的方式。我想這是查詢優(yōu)化器名稱的由來。這些盡量減少資源和最大限度地提高查詢優(yōu)化器執(zhí)行性能的方法之一是查看一個T-SQL語句并確定它們是否可以被參數(shù)化。要了解這是如何工作的,讓我們看看下面的T-SQL語句:


 SELECT * 
  FROM AdventureWorks.Sales.SalesOrderHeader 
  WHERE SalesOrderID = 56000; 
  GO

在這里,你可以看到這個命令有兩個特點。第一它簡單,第二它在WHERE謂詞中包含一個用于SalesOrderID值的指定值。查詢優(yōu)化器可以識別這個查詢比較簡單以及SalesOrderID有一個參數(shù)(“56000”)。因此,查詢優(yōu)化器可以自動地參數(shù)化這個查詢。

  如果你使用下面的SELECT語句來查看一個只包含用于上面語句的緩存計劃的、干凈的緩沖池,那么你會看到查詢優(yōu)化器將T-SQL查詢重寫為一個參數(shù)化T-SQL語句:

 


SELECT stats.execution_count AS cnt, 
  p.size_in_bytes AS [size], 
  [sql].[text] AS [plan_text] 
  FROM sys.dm_exec_cached_plans p 
  OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql 
  JOIN sys.dm_exec_query_stats stats 
  ON stats.plan_handle = p.plan_handle; 
  GO

當我在一個SQL Server 2008實例上運行這個命令時,我得到下面的輸出,(注意,輸出被重新格式化了,以便它更易讀):

  cnt size plan_text

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

  1 49152 (@1 int)SELECT * FROM [AdventureWorks].[Sales].[SalesOrderHeader]

  WHERE [SalesOrderID]=@1

  如果你看看上面輸出中的plan_text字段,你會看到它不像原來的T-SQL文本。如前所述,查詢優(yōu)化器將這個查詢重新編寫為一個參數(shù)化T-SQL語句。在這里,你可以看到它現(xiàn)在有一個數(shù)據(jù)類型為(int)的變量(@1),它在之前的SELECT語句中被定義的。另外在plan_text的末尾, 值“56000”被替換為變量@1。既然這個T-SQL語句被重寫了,而且被存儲為一個緩存計劃,那么如果未來一個T-SQL命令和它大致相同,只有SalesOrderID字段被賦的值不同的話,它就可以被用于重用。讓我們在動作中看看它。

如果我在我的機器上運行下面的命令: 


DBCC FREEPROCCACHE; 
  GO 
  SELECT * 
  FROM AdventureWorks.Sales.SalesOrderHeader 
  WHERE SalesOrderID = 56000; 
  GO 
  SELECT * 
  FROM AdventureWorks.Sales.SalesOrderHeader 
  WHERE SalesOrderID = 56001; 
  GO 
  SELECT stats.execution_count AS cnt, 
  p.size_in_bytes AS [size], 
  [sql].[text] AS [plan_text] 
  FROM sys.dm_exec_cached_plans p 
  OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql 
  JOIN sys.dm_exec_query_stats stats 
  ON stats.plan_handle = p.plan_handle; 
  GO 
  我從最后的SELECT語句得到下面的輸出,(注意,輸出被重新格式化以便它更易讀): 
  cnt size plan_text 
  --- -------- -------------------------------------------------------------- 
  2 49152 (@1 int)SELECT * FROM AdventureWorks].[Sales].[SalesOrderHeader] 
  WHERE [SalesOrderID]=@1


在這里,我首先釋放過程緩存,然后我執(zhí)行兩個不同、但卻類似的非參數(shù)化查詢來看看查詢優(yōu)化器是會創(chuàng)建兩個不同的緩存計劃還是創(chuàng)建用于這兩個查詢的一個緩存計劃。在這里,你可以看到查詢優(yōu)化器事實上很聰明,它參數(shù)化第一個查詢并緩存了計劃。然后當?shù)诙€類似、但有一個不同的SalesOrderID值的查詢發(fā)送到SQL Server時,優(yōu)化器可以識別已經緩存了一個計劃,然后重用它來處理第二個查詢。你可以這么說是因為“cnt”字段現(xiàn)在表明這個計劃被用了兩次。

  數(shù)據(jù)庫配置選項PARAMETERIZATION可以影響T-SQL語句怎樣被自動地參數(shù)化。對于這個選項有兩種不同的設置,SIMPLE和FORCED。當PARAMETERIZATION設置被設置為SIMPLE時,只有簡單的T-SQL語句才會被參數(shù)化。要介紹這個,看下下面的命令:


SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = 56000


這個查詢類似于我前面的示例,除了在這里我添加了一個額外的JOIN標準。當數(shù)據(jù)庫AdventureWorks的PARAMETERIZATION選項被設置為SIMPLE時,這個查詢不會被自動地參數(shù)化。SIMPLE PARAMETERIZATION設置告訴查詢優(yōu)化器只參數(shù)化簡單的查詢。但是當選項PARAMETERIZATION被設置為FORCED時,這個查詢將被自動地參數(shù)化。

  當你設置數(shù)據(jù)庫選項為使用FORCE PARAMETERIZATION時,查詢優(yōu)化器試圖參數(shù)化所有的查詢,而不僅僅是簡單的查詢。你可能會認為這很好。但是在某些情況下,當數(shù)據(jù)庫設置PARAMETERIZATION為FORCED時,查詢優(yōu)化器將選擇不是很理想的查詢計劃。當數(shù)據(jù)庫設置PARAMETER為FORCED時,它改變查詢中的字面常量。這可能導致當查詢中涉及計算字段時索引和索引視圖不被選中參與到執(zhí)行計劃中,從而導致一個無效的計劃。FORCED PARAMETERIZATION選項可能是改進具有大量類似的、傳遞過來的參數(shù)稍有不同的查詢的數(shù)據(jù)庫性能的一個很好的解決方案。一個在線銷售應用程序,它的客戶對你的產品執(zhí)行大量的類似搜索, 產品值不同,這可能是一個能夠受益于FORCED PARAMETERIZATION的很好的應用程序類型。

不是所有的查詢從句都會被參數(shù)化。例如查詢的TOP、TABLESAMPLE、 HAVING、GROUP BY、ORDER BY、OUTPUT...INTO或FOR XML從句不會被參數(shù)化。

  使用sp_execute_sql來參數(shù)化你的T-SQL

  你不需要依賴于數(shù)據(jù)庫的PARAMETERIZATION選項來使得查詢優(yōu)化器參數(shù)化一個查詢。你可以參數(shù)化你自己的查詢。你通過重新編寫你的T-SQL語句并使用“sp_executesql”系統(tǒng)存儲過程執(zhí)行重寫的語句來實現(xiàn)。正如已經看到的,上面包括一個“JOIN”從句的SELECT語句在數(shù)據(jù)庫的PARAMETERIZATION設置為SIMPLE時沒有被自動參數(shù)化。讓我重新編寫這個查詢以便查詢優(yōu)化器將創(chuàng)建一個可重用的參數(shù)化查詢執(zhí)行計劃。

  為了說明,讓我們看兩個類似的、不會被自動參數(shù)化的T-SQL語句,并創(chuàng)建兩個不同的緩存執(zhí)行計劃。然后我將重新編寫這兩個查詢使得它們都使用相同的緩存參數(shù)化執(zhí)行計劃。

  讓我們看看這個代碼:


 DBCC FREEPROCCACHE 
  GO 
  SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = 56000 
  GO 
  SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = 56001 
  GO 
  SELECT stats.execution_count AS cnt, 
  p.size_in_bytes AS [size], 
  LEFT([sql].[text], 200) AS [plan_text] 
  FROM sys.dm_exec_cached_plans p 
  OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql 
  JOIN sys.dm_exec_query_stats stats ON stats.plan_handle = p.plan_handle; 
  GO


在這里,我釋放了過程緩存,然后運行這兩個包含一個JOIN的、不同的非簡單的T-SQL語句。然后我將檢查緩存計劃。這是這個使用DMV 的SELECT語句的輸出(注意,輸出被重新格式化了,以便它更易讀):


cnt size plan_text 
  --- ----------- ------------------------------------------------------------------------------- 
  1 49152 SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D 
  ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = 56001 
  1 49152 SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D 
  ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = 56000

正如你從這個輸出看到的,這兩個SELECT語句沒有被查詢優(yōu)化器參數(shù)化。優(yōu)化器創(chuàng)建了兩個不同的緩存執(zhí)行計劃,每一個都只被執(zhí)行了一次。我們可以通過使用sp_executesql系統(tǒng)存儲過程來幫助優(yōu)化器為這兩個不同的SELECT語句創(chuàng)建一個參數(shù)化執(zhí)行計劃。
下面是上面的代碼被重新編寫來使用sp_executesql 系統(tǒng)存儲過程:


 DBCC FREEPROCCACHE; 
  GO 
  EXEC sp_executesql N'SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = @SalesOrderID', N'@SalesOrderID INT', @SalesOrderID = 56000; 
  GO 
  EXEC sp_executesql N'SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = @SalesOrderID', N'@SalesOrderID INT', @SalesOrderID = 56001; 
  GO 
  SELECT stats.execution_count AS exec_count, 
  p.size_in_bytes AS [size], 
  [sql].[text] AS [plan_text] 
  FROM sys.dm_exec_cached_plans p 
  OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql 
  JOIN sys.dm_exec_query_stats stats ON stats.plan_handle = p.plan_handle; 
  GO

如同你所看到的,我重新編寫了這兩個SELECT語句,使它們通過使用“EXEC sp_executesql”語句來執(zhí)行。對這些EXEC語句中的每一個,我都傳遞三個不同的參數(shù)。第一個參數(shù)是基本的SELECT語句,但是我將SalesOrderID的值用一個變量(@SalesOrderID)替代。在第二個參數(shù)中,我確定了@SalesOrderID的數(shù)據(jù)類型,在這個例子中它是一個integer。然后在最后一個參數(shù)中,我傳遞了SalesOrderID的值。這個參數(shù)將控制我的SELECT根據(jù)SalesOrderID值所生成的結果。sp_executesql的每次執(zhí)行中前兩個參數(shù)都是一樣的。但是第三個參數(shù)不同,因為每個都有不同的SalesOrderID值。

  現(xiàn)在當我運行上面的代碼時,我從DMV SELECT語句得到下面的輸出(注意,輸出被重新格式化了,以便它更易讀):


cnt size plan_text 
  --- ----------- ----------------------------------------------------------------------------------------- 
  2 49152 (@SalesOrderID INT)SELECT SUM(LineTotal) AS LineTotal 
  FROM AdventureWorks.Sales.SalesOrderHeader H 
  JOIN AdventureWorks.Sales.SalesOrderDetail D ON D.SalesOrderID = H.SalesOrderID 
  WHERE H.SalesOrderID = @SalesOrderID


從這個輸出,你可以看出,我有一個參數(shù)化緩存計劃,它被執(zhí)行了兩次,為每個EXEC語句各執(zhí)行了一次。

  使用參數(shù)化查詢來節(jié)省資源和優(yōu)化性能

  在語句可以被執(zhí)行之前,每個T-SQL語句都需要被評估,而且需要建立一個執(zhí)行計劃。創(chuàng)建執(zhí)行計劃會占用寶貴的CPU資源。當執(zhí)行計劃被創(chuàng)建后,它使用內存空間將它存儲在過程緩存中。降低CPU和內存使用的一個方法是利用參數(shù)化查詢。盡管數(shù)據(jù)庫可以被設置為對所有查詢FORCE參數(shù)化,但是這不總是最好的選擇。通過了解你的哪些T-SQL語句可以被參數(shù)化然后使用sp_executesql存儲過程,你可以幫助SQL Server節(jié)省資源并優(yōu)化你的查詢的性能。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 97视频免费在线观看 | 日韩簧片 | 伊人福利视频 | 午夜国产影院 | 午夜网址 | av伊人网| 日韩在线观看中文字幕 | 男人的天堂在线视频 | 中国毛片基地 | av中文字幕在线播放 | 黄色一区二区三区 | 亚洲高清视频网站 | 久久精品二| 福利国产 | 亚洲国产精品自拍视频 | 国产精品免费一区二区三区四区 | 伊人激情| 午夜精品 | 一级电影中文字幕 | 久久久久久一级片 | 狠狠操电影| 久久男女 | 蜜桃视频 精品区 | 夜夜嗨av色一区二区不卡 | 欧美91| 午夜精品久久久久久久白皮肤 | 中文在线一区 | 91精品视频免费在线观看 | 精品久久久久久久久久久 | 欧美黄色成人 | 一区二区三区影视 | 欧美簧片在线 | 一区免费看| 99伊人| 久久蜜桃精品一区二区三区综合网 | 91一区二区在线 | 亚洲日本va中文字幕 | 亚洲视频一区二区 | 国产欧美精品一区二区三区四区 | 国产一级一级毛片女人精品 | 夜夜操导航 |