關於T-SQL重編譯那點事,內聯函數和表值函數在編譯生成執行計劃的區別

来源:http://www.cnblogs.com/wy123/archive/2017/01/10/6266724.html
-Advertisement-
Play Games

本文出處:http://www.cnblogs.com/wy123/p/6266724.html 最近在學習 WITH RECOMPILE和OPTION(RECOMPILE)在重編譯上的區別的時候,無意中發現表值函數和內聯表值函數編譯生成執行計劃的區別下文中將會對此問題展開討論。簡單地說就是:同樣一 ...


 

本文出處:http://www.cnblogs.com/wy123/p/6266724.html 

 

最近在學習 WITH RECOMPILE和OPTION(RECOMPILE)在重編譯上的區別的時候,無意中發現表值函數和內聯表值函數編譯生成執行計劃的區別
下文中將會對此問題展開討論。
簡單地說就是:同樣一句SQL,分別寫成內聯函數和表值函數,然後執行對Function的查詢,發現其執行計劃和執行計劃緩存是不一樣的,
根據某些測試的一些共同規律發現,內聯函數的編譯很有可能與Parameter Embedding Optimization 有關
關於Parameter Embedding Optimization,我在http://www.cnblogs.com/wy123/p/6262800.html寫了一個案例
在發生Parameter Embedding Optimization做編譯優化的時候,跟普通的編譯優化機制還是有很大差異的。

 

概念解釋:內聯用戶定義函數和表值用戶定義函數

  SQL Server中的表值函數分為“內聯用戶定義函數”和“表值用戶定義函數”。

 

內聯用戶定義函數(Inline User-Defined Functions):
  不上MDSN上搬概念了,簡單地說,內聯函數的特點就是就是返回類型為table,返回的結果是一個查詢語句
  如下,dbo.fn_InlineFunction即為內聯用戶定義函數,當然後面要與表值用戶定義函數作比較,就能看出來區別了

create function dbo.fn_InlineFunction
(
    @p_parameter     varchar(500)
)
returns table
as
return
(
    SELECT id,col2
    FROM [dbo].[TestTableValueFunction] 
    where ( col2  = @p_id or @p_id is null)      
)
GO

 

 

表值用戶定義函數(Table-Valued User-Defined Functions),
  與內聯函數區別在於,表值用戶定義函數返回的是一個表變數,在函數體中,通過賦值給這個表變數,然後返回表變數
  如下dbo.fn_TableValuedFunction即為內聯用戶定義函數,

create function fn_TableValuedFunction
(
    @p_paramter      varchar(500)
)
RETURNS @Result TABLE
(
    id int ,
    value char(5000)
)
as
begin
    
    insert into @Result
    select id,col2
    from [dbo].[TestTableValueFunction] 
    where ( col2  = @p_id or @p_id is null)   
      
    return
end

  熟悉sqlserver的同學可能已經知道這兩者的區別了,關於內聯用戶定義函數和表值用戶定義函數就先這麼簡單說一下區別
  雖然內聯函數和表值函數在功能上和使用上是有一些差異的,但是有一部分查詢,用兩種方式都可以實現,也就說兩者在功能上有差異也有交集。

 

開始本文主題

 

同樣的SQL語句,使用內聯函數和使用表值函數查詢生成執行計劃的區別

  按照慣例,先造一個測試表,char(500)的欄位可以是的表以及索引占用空間變大,後面對比測試的效果變得更加明顯。

create table TestTableValueFunction
(
    id int IDENTITY(1,1),
    col2 char(500)
)
GO

INSERT INTO TestTableValueFunction VALUES (NEWID())
GO 1000000

CREATE INDEX idx_col2 on TestTableValueFunction(col2)
GO

  同樣的查詢條件下,分別用內聯函數和表值函數查詢,查看其性能

  

  首先使用內聯函數的方式查詢,用插入數據中的一條值做查詢,最直觀的方式去看SSMS的執行時間,顯示為0秒,本機測試幾乎是瞬間就出來結果了
  可以看到執行計划走的是原始表TestTableValueFunction上idx_col2索引查找Index Seek

 

觀察IO,發現發生了8次IO

  使用表值函數的方式查詢,使用上面同樣的條件做查詢,SSMS顯式耗時4秒(本機測試的,可以忽略測試環境的外界影響因素)
  但是使用表值函數無法直接觀察查詢的執行計劃和IO信息,這兩個信息後面從計劃緩存中查詢

   

  其顯示的IO信息應該也不是原始的SQL的IO,應該是表變數的IO,原始SQL語句的IO和執行計劃信息暫時看不到,後面再說

   

 

為什麼同樣的查詢,使用表值函數,性能差異居然有這麼大?

  對於表值函數,由於無法直接觀察到其實際執行計劃和IO信息,那麼我們去查詢其緩存的執行計劃和IO信息
  如下,sys.dm_exec_query_stats系統表中查詢到其最近一次執行的IO信息,76997,遠遠大於上面的8次IO
  查看緩存的執行計劃

  

  從緩存中的執行計劃可以看到,其執行計劃為全表掃描

  

  到這裡就有意思了,既然是一樣的SQL,寫成內聯函數和表值函數,兩者的執行計劃不一樣,
  那麼就可以推斷出,SQL Server對內聯函數和表值函數的編譯處理方式是不一樣的。
  同時,上面的內聯函數是可以知道看到實際執行計劃的,顯示為Index Seek,
  但是在觀察緩存計劃的時候,是沒有查到的,如下截圖,也就是說內聯函數dbo.fn_InlineFunction對應的SQL的執行計劃是沒有被緩存起來的
  種種跡象不由的使我想到上一篇關於T-SQL重編譯那點事中,OPTION(RECOMPILE)的The Parameter Embedding Optimization編譯優化機制
  從內聯函數的SQL的執行計劃發現,編譯過程中是對SQL語句做植入參數優化+簡化,又因為沒有緩存執行計劃,那麼很有可能是發生了重編譯
  從個這兩點來看,跟OPTION(RECOMPILE)強制重編譯中的The Parameter Embedding Optimization編譯優化機制基本上是吻合的

  

  回頭再說表值函數為什麼是全表掃描?參考下圖,正常情況下這種查詢邏輯就是走的全表掃描
  只不過是內聯函數裡面,編譯優化機制對這種寫法做了專門的優化,才能走一個索引查找的方式。
  這也正是內聯函數和表值函數在編譯上最大的區別之一。
  對於為什麼表值函數裡面這種邏輯會在造成全表掃描在上一篇也解釋了,這裡就不啰嗦了。

如上,同樣的T-SQL查詢,在末尾加上OPTION(RECOMPILE),執行計劃也變成了Index Seek,跟內聯函數的執行計劃一致(都是index Seek),當然內聯函數中是沒有加OPTION(RECOMPILE)的

因此這裡有理由懷疑,內聯函數的編譯,是類似等價於加了OPTION(RECOMPILE)的

  之前只是瞭解過內聯函數和表值函數在預估方面的區別(不過記得好像是SQL Server2012之後對錶值函數的預估計算方式也做了更新),
   除此之外,從來沒有註意到也沒有考慮過兩者在編譯以及計劃緩存方面的區別
   工作中見到過有人使用內聯函數做複雜的查詢,並且是查詢條件是(col2 =@p_parameter or @p_parameter is null)這種方式
   如果是在存儲過程中,這種方式是會抑制到索引的使用的,之前“理所當然地”認為,寫成內聯函數,肯定也會抑制索引的使用
  不過從這個測試case來看,內聯函數這種寫法,確實可以正常使用索引

 

總結
  本文通過一個簡單的case,來演示了內聯函數和表值函數在編譯上的一些差別,優化器對內聯函數進行專門的優化處理,而不會去對錶值函數做特別的優化。
  在對內聯函數做特殊優化的時候,雖然沒有明確執行強制重編譯,但等效於存在類似於option(recompile)的基於sql語句級的強制重編譯優化機制。

 

 

   


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這個效果的完成主要分為兩個部分 1. 自定義view作為listview的列表項 一個view裡面包括 顯示頭像,名字,消息內容等的contentView和滑動才能顯示出來的刪除,置頂的右邊菜單menuView 在手指移動的時候同時改變這兩個視圖的位置 2. 重寫listview 判斷item向左還 ...
  • 概述 VS自2015把Xamarin集成進去後搞Android開發就爽了,不過這安裝VS2015完成的時候卻是長了不知道多少。廢話少說進正題,VS2015安裝時註意把Android相關的組件勾選安裝,別組件都沒安裝就來用VS搞Android開發。 VS2015的Android組件安裝完成後並不是什麼 ...
  • 數據稽核及處理技術方案 數據稽核及處理技術方案 編寫與審核人 編寫 審核 日期 備註 劉嘉勁、韋譽、溫智勇 陶心萬 2016-12-28 修改歷史 日期 版本 作者 修改內容 更改請求號 註釋:“更改請求號”為文檔正式發佈後需要變更時的編號。 編寫與審核人 編寫 審核 日期 備註 劉嘉勁、韋譽、溫智 ...
  • 一、數據備份(導出) 1、exp命令導出dmp文件(exp -help查看幫助信息) 命令:exp username/[email protected]/orcl file=C:\jds.dmp log=C:\jds.log tables=tablename...;(不寫tables ...
  • 前言 應用系統承載著大量的業務,隨之而來的是複雜的業務邏輯,在資料庫上的表現就是有著大量的不同種類的SQL語句。 SQL語句執行的快慢又與阻塞等待有著密不可分的原因。 系統慢可能有很多種原因,硬體資源不足,語句不優化,結構設計不合理,缺少必要的運維方式。所有的這些問題都可以在阻塞與等待中看出端倪,發 ...
  • Sqlserver 高併發和大數據存儲方案 隨著用戶的日益遞增,日活和峰值的暴漲,資料庫處理性能面臨著巨大的挑戰。下麵分享下對實際10萬+峰值的平臺的資料庫優化方案。與大家一起討論,互相學習提高! 案例:游戲平臺. 1、解決高併發 當客戶端連接數達到峰值的時候,服務端對連接的維護與處理這裡暫時不做討 ...
  • 今天使用SQLCMD導入到SQL SERVER資料庫中,看著數據文件都成功執行,但是意外發現有一個文件數據沒有成功導入,但執行不報錯,很容易導致問題被忽略。 使用存在問題的文件做下測試,從界面上看幾行腳本沒有任何問題: 4條INSERT語句“幾乎”一樣,區別在於最上面三行的部分文字是我從問題語句中粘 ...
  • 未來的BI市場是巨大的,涉及的觸角也會越來越多。就我觀察到的企業應用以及數據類產品中發現,很多企業通過數據介面引入了更多外部的數據來完善分析,也有部分企業私有化部署的BI產品在往雲BI方向發展。與R語言、數據挖掘類技術的集成,也將進一步提高數據分析的深度。 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...