婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 執行Insert Exec時的隱藏開銷 分析

執行Insert Exec時的隱藏開銷 分析

熱門標簽:長沙外呼系統平臺 漯河電銷回撥外呼系統 美國地圖標注軟件下載 城市地圖標志怎么標注 怎么修改高德地圖標注 西安電話自動外呼系統 硅基電話機器人官網 合肥crm外呼系統加盟 電話機器人怎么看余額

The Hidden Costs of INSERT EXEC

INSERT and EXEC: relational brothers in arms, helping you get your data and then put it somewhere. But like all brothers, their relationship has its ups and downs and sometimes you need to look just below the surface to see the real issues. In this post I will cover hidden penalties that a decision--seemingly purely aesthetic--can bring to the fore.

To illustrate the first of these examples I will be using the following table:

USE tempdb
GO


CREATE TABLE dbo.MyTable
(
    [SalesOrderID] [int] NOT NULL,
    [SalesOrderDetailID] [int] NOT NULL,
    [CarrierTrackingNumber] [nvarchar](25) NULL,
    [OrderQty] [smallint] NOT NULL,
    [ProductID] [int] NOT NULL,
    [SpecialOfferID] [int] NOT NULL,
    [UnitPrice] [money] NOT NULL,
    [UnitPriceDiscount] [money] NOT NULL,
    [LineTotal] [money] NOT NULL,
    [rowguid] [uniqueidentifier]  NOT NULL,
    [ModifiedDate] [datetime] NOT NULL
)
GO

Consider the following queries, disregarding the fact that this isn't a good dynamic SQL example (I'm trying to keep it simple), and take a moment to think about the differences between them from a behavioral point of view:

EXEC
('
    INSERT dbo.MyTable
    SELECT *
    FROM AdventureWorks.Sales.SalesOrderDetail
')
GO

INSERT dbo.MyTable
EXEC
('
    SELECT *
    FROM AdventureWorks.Sales.SalesOrderDetail
')
GO

It's quite common to insert some data into a table from dynamic SQL, and for as long as I can remember, I've believed the choice between these two forms of the query to be primarily an issue of style. My preference has been for the latter style, as I feel that it's a bit more readable. It also has the benefit of better supporting ownership chains, but that's something that, in most cases, we don't have to worry about any longer in SQL Server 2005 or 2008. But let's move beyond style and potential security issues and get to the substance. What actually happens when we run these two queries?

In the first case--insert done inside of the EXEC--the first step is that the outer statement--the EXEC itself--is parsed and validated. Now we jump down one level of context, into the string that was passed to EXEC, and that string is parsed and validated. The referenced objects are resolved, and the plan cache is checked. If there is no plan, the query is compiled. And then it's executed. Data is streamed from SalesOrderDetail into MyTable and when the query inside of the EXEC is done control returns to the calling context--EXEC--and assuming there were no errors, the EXEC is now completed.

In the second case, something quite a bit different occurs. The insert is parsed and validated, and an INSERT EXEC plan is generated. This plan does not involve SalesOrderDetail, as the query optimizer doesn't know at this point in the process where the data will be inserted from, since that step is dynamic. So the plan references something called the "Parameter Table" (plan truncated for simplicity):

|--Table Insert(OBJECT:([tempdb].[dbo].[MyTable]))
   |--Top(ROWCOUNT est 0)
        |--Parameter Table Scan

Once this plan has been generated, we again jump down one level of context, and the inner string is parsed and validated, the referenced object resolved, the cache checked, and the compiled plan executed. But what is this Parameter Table thing?

Here's where things start really diverging. Data is not, at this point, streamed from SalesOrderDetail directly into MyTable. Rather, it is streamed from SalesOrderDetail into the Parameter Table. And the Parameter Table, as it turns out, is in actuality a hidden temporary table. And not until all of the data has streamed into that hidden temporary table is control resumed by the EXEC context, and only then does the data start moving into its final home.

The natural question you might be asking yourself at this point is, just how much overhead does this Parameter Table introduce into the equation? The answer might just send you racing to check your stored procedures: the additional cost for the Parameter Table is well over 100% as compared with doing the insert inside of the EXEC. The fact that all of the data must be spooled to the Parameter Table before the insert can even begin tells us that this must be true, and it can be verified using a simple check against the sys.dm_exec_requests DMV, as in the following example:

EXEC
('
    INSERT dbo.MyTable
    SELECT *
    FROM AdventureWorks.Sales.SalesOrderDetail
')

SELECT
    r.writes AS [INSERT inside EXEC writes]
FROM sys.dm_exec_requests r
WHERE
    r.session_id = @@SPID
GO

INSERT dbo.MyTable
EXEC
('
    SELECT *
    FROM AdventureWorks.Sales.SalesOrderDetail
')

SELECT
    r.writes AS [INSERT EXEC writes]
FROM sys.dm_exec_requests r
WHERE
    r.session_id = @@SPID
GO

So that's that. We should avoid INSERT EXEC and try to do our inserts in the same context in which the SELECT is running--right?

Well, yes and no. There is another element at play here which I haven't yet mentioned. What if we were only inserting a few rows, and the table we were inserting into looked something like the following:

CREATE TABLE #MyTable
(
    [SalesOrderID] [int] NOT NULL,
    [SalesOrderDetailID] [int] NOT NULL,
    [CarrierTrackingNumber] [nvarchar](25) NULL,
    [OrderQty] [smallint] NOT NULL,
    [ProductID] [int] NOT NULL,
    [SpecialOfferID] [int] NOT NULL,
    [UnitPrice] [money] NOT NULL,
    [UnitPriceDiscount] [money] NOT NULL,
    [LineTotal] [money] NOT NULL,
    [rowguid] [uniqueidentifier]  NOT NULL,
    [ModifiedDate] [datetime] NOT NULL
)
GO

The only difference between this table and the previous one is that this is a temporary table and the other is not. But temporary tables have their own interesting little twists, especially when it comes down to one of the key enemies in a highly-transactional system: recompilation. As it turns out, doing the insert inside the EXEC will cause the internal statement to recompile every time a new temp table is encountered. This means that if you have a stored procedure that creates a temp table, puts together a bit of dynamic SQL, and does an insert inside of that dynamic SQL, you'll now have yourself a recompilation problem.

To see this illustrated, try the following script. Here only a single row is inserted as a result of the dynamic query, but it's complex enough that the compile time more than overshadows the overhead of the Parameter Table:

USE tempdb
GO

DBCC FREEPROCCACHE
GO

CREATE TABLE #AvgTimes
(
    CPU_time DECIMAL(19,4) NOT NULL,
    insert_type VARCHAR(25) NOT NULL
)
GO

CREATE TABLE #MyTable
(
    [SalesOrderID] [int] NOT NULL,
    [SalesOrderDetailID] [int] NOT NULL,
    [CarrierTrackingNumber] [nvarchar](25) NULL,
    [OrderQty] [smallint] NOT NULL,
    [ProductID] [int] NOT NULL,
    [SpecialOfferID] [int] NOT NULL,
    [UnitPrice] [money] NOT NULL,
    [UnitPriceDiscount] [money] NOT NULL,
    [LineTotal] [money] NOT NULL,
    [rowguid] [uniqueidentifier]  NOT NULL,
    [ModifiedDate] [datetime] NOT NULL
)

EXEC
('
    INSERT #MyTable
    SELECT TOP(1)
        sod.*
    FROM AdventureWorks.Sales.SalesOrderDetail sod
    WHERE
        sod.UnitPrice > 10
        AND sod.LineTotal > 100
        AND EXISTS
        (
            SELECT *
            FROM AdventureWorks.Sales.SalesOrderHeader soh
            JOIN AdventureWorks.Person.Contact c ON
                c.ContactID = soh.CustomerID
            WHERE
                soh.SalesOrderID = sod.SalesOrderID
                AND c.LastName LIKE ''Ab%''
        )
        AND EXISTS
        (
            SELECT *
            FROM AdventureWorks.Production.Product p
            WHERE
                p.ProductID = sod.ProductID
                AND p.Color IS NULL
        )
        AND NOT EXISTS
        (
            SELECT *
            FROM AdventureWorks.Sales.SalesOrderHeader soh
            JOIN AdventureWorks.Sales.SalesPerson sp ON
                soh.SalesPersonID = sp.SalesPersonID
            WHERE
                soh.SalesOrderID = sod.SalesOrderID
                AND sp.CommissionPct > 50
        )
')

INSERT #AvgTimes
SELECT
    r.cpu_time,
    'INSERT inside EXEC'
FROM sys.dm_exec_requests r
WHERE
    r.session_id = @@SPID

DROP TABLE #MyTable
GO 5

CREATE TABLE #MyTable
(
    [SalesOrderID] [int] NOT NULL,
    [SalesOrderDetailID] [int] NOT NULL,
    [CarrierTrackingNumber] [nvarchar](25) NULL,
    [OrderQty] [smallint] NOT NULL,
    [ProductID] [int] NOT NULL,
    [SpecialOfferID] [int] NOT NULL,
    [UnitPrice] [money] NOT NULL,
    [UnitPriceDiscount] [money] NOT NULL,
    [LineTotal] [money] NOT NULL,
    [rowguid] [uniqueidentifier]  NOT NULL,
    [ModifiedDate] [datetime] NOT NULL
)

INSERT #MyTable
EXEC
('
    SELECT TOP(1)
        sod.*
    FROM AdventureWorks.Sales.SalesOrderDetail sod
    WHERE
        sod.UnitPrice > 10
        AND sod.LineTotal > 100
        AND EXISTS
        (
            SELECT *
            FROM AdventureWorks.Sales.SalesOrderHeader soh
            JOIN AdventureWorks.Person.Contact c ON
                c.ContactID = soh.CustomerID
            WHERE
                soh.SalesOrderID = sod.SalesOrderID
                AND c.LastName LIKE ''Ab%''
        )
        AND EXISTS
        (
            SELECT *
            FROM AdventureWorks.Production.Product p
            WHERE
                p.ProductID = sod.ProductID
                AND p.Color IS NULL
        )
        AND NOT EXISTS
        (
            SELECT *
            FROM AdventureWorks.Sales.SalesOrderHeader soh
            JOIN AdventureWorks.Sales.SalesPerson sp ON
                soh.SalesPersonID = sp.SalesPersonID
            WHERE
                soh.SalesOrderID = sod.SalesOrderID
                AND sp.CommissionPct > 50
        )
')

INSERT #AvgTimes
SELECT
    r.cpu_time,
    'INSERT EXEC'
FROM sys.dm_exec_requests r
WHERE
    r.session_id = @@SPID

DROP TABLE #MyTable
GO 5

SELECT
    AVG
    (
        CASE a.insert_type
            WHEN 'INSERT inside EXEC' THEN a.CPU_time
            ELSE NULL
        END
    ) AS [CPU time - INSERT inside EXEC],
    AVG
    (
        CASE a.insert_type
            WHEN 'INSERT EXEC' THEN a.CPU_time
            ELSE NULL
        END
    ) AS [CPU time - INSERT EXEC]
FROM #AvgTimes a
GO

DROP TABLE #AvgTimes
GO

So what have we learned today? The choice between INSERT EXEC and INSERT inside of EXEC is not purely stylistic and has definite performance implications. Here are the rules I'll be following from now on:

  • When working with permanent tables, always avoid INSERT EXEC if possible. There are some cases where it won't be possible to avoid. I only showed dynamic SQL in this post, but INSERT EXEC also applies to stored procedures. Can you safely rip apart all of the stored procedures in your system in order to avoid this issue? Maybe not quite as easily as you can rip apart the dynamic SQL within stored procedures.
  • When working with temporary tables, evaluate the complexity of the operations, the amount of data to be inserted, and most importantly, test every solution! The more rows that are inserted as a result of the INSERT EXEC, the more the overhead you'll get from the Parameter Table. On the flip side, the more complex the dynamic statement, the more overhead you'll get from recompilations. Every scenario is bound to be different and you may just learn something about your processes by doing this extra bit of analysis.

標簽:瀘州 撫順 文山 濟源 吉林 商洛 玉溪 廣西

巨人網絡通訊聲明:本文標題《執行Insert Exec時的隱藏開銷 分析》,本文關鍵詞  執行,Insert,Exec,時,的,隱藏,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《執行Insert Exec時的隱藏開銷 分析》相關的同類信息!
  • 本頁收集關于執行Insert Exec時的隱藏開銷 分析的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    日韩av在线发布| 国产日韩精品一区| 国产精品午夜春色av| 精品视频一区二区三区免费| 精品一区免费av| 亚洲国产精品久久久久秋霞影院 | 91麻豆精品国产91久久久资源速度| 激情六月婷婷综合| 最近中文字幕一区二区三区| 久久久亚洲综合| 欧美一区永久视频免费观看| 在线观看成人免费视频| 91网页版在线| 不卡的电影网站| 暴力调教一区二区三区| 国产精品1区2区3区在线观看| 久久99在线观看| 国产一区二区三区免费| 国产在线麻豆精品观看| 日本色综合中文字幕| 日韩av在线播放中文字幕| 视频一区二区欧美| 日韩国产欧美视频| 免费一区二区视频| 韩国女主播一区| 成人一区在线观看| 91蜜桃传媒精品久久久一区二区| 9i在线看片成人免费| 97精品久久久午夜一区二区三区| 91在线国产福利| 欧美网站一区二区| 91麻豆精品国产91久久久久久| 91精品国产色综合久久ai换脸| 91久久免费观看| 91小宝寻花一区二区三区| 成人av在线资源网| 91美女精品福利| 91美女片黄在线观看| 99视频在线观看一区三区| 成人丝袜18视频在线观看| 国产精品综合二区| 国产尤物一区二区| 国产精品99久久久久久宅男| 国内精品嫩模私拍在线| 国产乱淫av一区二区三区| 成人免费黄色在线| 99国产精品视频免费观看| 97精品国产97久久久久久久久久久久| 91香蕉视频mp4| 日本韩国欧美在线| 欧美久久久久久久久中文字幕| 欧美日韩久久久| 26uuu成人网一区二区三区| 久久综合久久久久88| 久久精品亚洲精品国产欧美| 国产精品国产精品国产专区不蜜 | 国产精品色哟哟网站| 2022国产精品视频| 亚洲欧洲日韩在线| 亚洲国产中文字幕| 韩国女主播一区二区三区| 99re成人精品视频| 宅男噜噜噜66一区二区66| 亚洲精品一区二区三区在线观看| 欧美韩日一区二区三区四区| 一区二区三区在线观看网站| 美女视频第一区二区三区免费观看网站 | 日韩成人伦理电影在线观看| 蜜桃av噜噜一区| 色成人在线视频| 精品少妇一区二区三区| 亚洲乱码一区二区三区在线观看| 日韩电影免费一区| 91视频免费播放| 久久久久国产精品免费免费搜索| 亚洲精品免费视频| 美美哒免费高清在线观看视频一区二区| 国产黄色精品视频| 欧美日韩视频在线第一区| 国产网红主播福利一区二区| 亚洲成在线观看| 不卡的电视剧免费网站有什么| 精品日韩一区二区| 性欧美大战久久久久久久久| 色婷婷精品久久二区二区蜜臂av| 久久九九99视频| 亚洲综合激情另类小说区| 国内成人精品2018免费看| 欧美日韩美少妇| 最新日韩av在线| 粉嫩久久99精品久久久久久夜| 欧美精品色综合| 亚洲一线二线三线视频| 成人精品国产一区二区4080| 欧美一区国产二区| 午夜精品123| 色屁屁一区二区| 国产精品亲子伦对白| 国产老肥熟一区二区三区| 欧美色倩网站大全免费| 国产精品对白交换视频| 国内不卡的二区三区中文字幕 | 成人免费观看男女羞羞视频| 日韩一级成人av| 日韩电影免费一区| 欧美日韩精品三区| 调教+趴+乳夹+国产+精品| 91福利国产成人精品照片| 一区二区三区小说| 91亚洲国产成人精品一区二三| 亚洲国产精品激情在线观看| 国产.欧美.日韩| 亚洲成人中文在线| 国产婷婷色一区二区三区在线| 蜜桃视频一区二区三区| 欧美丰满美乳xxx高潮www| 日韩精品一区第一页| 91麻豆精品国产91久久久资源速度| 亚洲成人激情av| 69av一区二区三区| 久久国产成人午夜av影院| 日韩视频免费观看高清完整版在线观看| 一区二区高清免费观看影视大全| 91久久免费观看| 1区2区3区欧美| 在线精品视频小说1| 亚洲国产裸拍裸体视频在线观看乱了| 日本精品一级二级| 偷拍自拍另类欧美| 91精品国产综合久久久蜜臀图片| 蜜臀99久久精品久久久久久软件| 久久婷婷成人综合色| 不卡电影免费在线播放一区| 亚洲精品亚洲人成人网| 欧美日韩精品一区二区三区蜜桃| 日韩不卡一二三区| 国产精品视频线看| 欧美日韩在线电影| 国产激情91久久精品导航| 亚洲私人黄色宅男| 91精品国产综合久久久久久久久久| 国产精品综合在线视频| 一区二区三区电影在线播| 日韩女优av电影| 91色.com| 激情综合色播五月| 亚洲色图视频网| 在线播放91灌醉迷j高跟美女 | 日韩欧美激情四射| 99久久精品国产导航| 日韩毛片在线免费观看| 欧美一区欧美二区| 成人avav在线| 丝袜国产日韩另类美女| 久久久久久一二三区| 91福利小视频| 国产乱理伦片在线观看夜一区| 亚洲激情欧美激情| 精品久久久久香蕉网| 色88888久久久久久影院按摩 | 国产在线一区观看| 伊人性伊人情综合网| www亚洲一区| 欧美日韩一区不卡| 国产精品乡下勾搭老头1| 亚洲国产成人tv| 中文字幕一区av| 欧美成人精品福利| 欧美在线观看视频一区二区| 成人一区在线看| 老司机精品视频导航| 亚洲aaa精品| 中文字幕制服丝袜成人av| 91麻豆精品在线观看| 久久伊99综合婷婷久久伊| 色呦呦国产精品| 国产精品一区二区不卡| 日本午夜一本久久久综合| 亚洲自拍偷拍图区| 亚洲欧洲日韩一区二区三区| 日韩精品一区二区三区视频播放| 91在线码无精品| 成人app网站| 国产成人精品在线看| 麻豆精品一区二区综合av| 日韩avvvv在线播放| 亚洲第一在线综合网站| 亚洲高清不卡在线观看| 中文字幕一区二区日韩精品绯色| 国产精品欧美一区二区三区| 国产女主播一区| 国产视频视频一区| 亚洲国产成人一区二区三区| 国产区在线观看成人精品| 国产视频一区在线观看| 国产精品素人视频| 亚洲欧洲av一区二区三区久久| 综合色天天鬼久久鬼色| 一区二区在线观看视频在线观看| 中文字幕在线一区|