运行存储过程时处理器利用率高

Viv*_*ngh 5 sql-server execution-plan sql-server-2016

我有一个存储过程,它在 12/11 之前运行良好,平均执行时间不到 2 小时。从周二(12/11)开始,存储过程连续运行了3个多小时,不得不手动杀死并重新运行。

  1. 12 月 12 日,我们继续编写了存储过程的脚本。删除当前程序并重新创建它,它运行良好。
  2. 2013 年 12 月 13 日,当程序再次需要很长时间才能执行时,我们尝试了类似的删除和重新创建它的方法,但这次没有奏效。我们必须手动运行存储过程的每一行。
  3. 今天也需要很长时间才能运行。

需要注意的一件事是,无论何时运行该特定存储过程,处理器利用率都会高达 95%。我们有描述相同的 SQLMonitor 工具 -

在此处输入图片说明

为了消除参数嗅探的可能性,我清除了 proc 缓存,DBCC FREEPROCCACHE并在美国东部标准时间上午 5:30 再次通过删除并重新创建它来重新运行该过程。即使在此之后,处理器利用率也会出现峰值。以下是清除 proc 缓存后的当前处理器利用率 -

在此处输入图片说明

以下是存储过程仅供参考 -

CREATE PROCEDURE [dbo].[Build_Base02_Orders] 

AS
BEGIN

    SET NOCOUNT ON;

    declare @Start_Date datetime = getdate();
    declare @Last_Date datetime
    DECLARE @PROMOHIGHDATE INT = (SELECT MAX(FILE_DATE) FROM Stage1_Promotion);

 --Create the Orders from Items

   drop table WinstonBrand_Base.dbo.Orders;


With OrdersBase1 as
(
 Select * from WinstonBrand.dbo.Stage3_Orders Orders
 UNION ALL
 Select * from WinstonBrand.dbo.Stage1_Order_Header_HH HH
 WHERE YEAR(ORDDATE) = '2005' AND NOT EXISTS (SELECT 1 FROM WinstonBrand.dbo.Stage3_Orders SO WHERE HH.ORDNO = SO.ORDNO)
)

   Select *,

   Row_Number() over (partition by Orders.ORDNO order by Orders.Ordno,Orders.ORDDATE DESC) as lastposition
  into #baseorders
  from OrdersBase1 Orders
    where indid is not null
  and exists
  (select 1 from WinstonBrand_Base.dbo.Items items where items.ITMORDNO = orders.ORDNO)


;WITH  Orders AS
  (
   SELECT b.*,OrderLoadDates.File_Date,
   ROW_NUMBER() OVER(PARTITION BY HHID ORDER BY HHID,Ordno,Orddate) AS HOSEQNUM,
   ROW_NUMBER() OVER(PARTITION BY HHID ORDER BY Orddate DESC) AS HOSEQNUMD,
   P.PROMO_DESC,P.PROMO_QUALIFY_AMT
   FROM #BaseOrders b
   OUTER APPLY (SELECT * FROM ufnGetLastOrdHeader(b.ORDNO) a WHERE b.ORDNO=a.ORDER_NUMBER)  OrderLoadDates
   OUTER APPLY ufnGetSTAGE1_Promotion(Offer,@PROMOHIGHDATE) P 


   WHERE b.lastposition = 1
  ),

  ORD_ODATE AS (
  SELECT
  HHID HO_HHID, ORDDATE HO_ODATE
  FROM ORDERS 
  WHERE HOSEQNUM = 1
  ),

  SHPING_CRT_HEADER AS (
  SELECT
  ORDER_NUMBER,  MEDIUM_CODE,  SOURCE_CODE,  CAMPAIGN_CODE,  TERM_CODE,  CONTENT_CODE
  FROM(
  SELECT
  ORDER_NUMBER,
  MEDIUM_CODE,
  SOURCE_CODE,
  CAMPAIGN_CODE,
  TERM_CODE,
  CONTENT_CODE,
  ROW_NUMBER() OVER(PARTITION BY CART_ID,ORDER_NUMBER ORDER BY LOAD_DATE DESC) ROW_SELECT
  FROM WinstonBrand.DBO.LTD_Shopping_Cart_Header
  WHERE --MEDIUM_CODE <> ''
  (MEDIUM_CODE <> '' OR SOURCE_CODE <> '' OR CAMPAIGN_CODE <> '' OR TERM_CODE <> '' OR CONTENT_CODE <> '')
  )A
  WHERE ROW_SELECT = 1
  ) 

    SELECT 
    HHID,
    INDID,
    ADDRID,
    COMPID,
    ACCTNO,
    EMAIL_ADD EMAIL,
    Orders.ORDNO,
    CAST(HOSEQNUM AS INT) AS HOSEQNUM,
    CAST(HOSEQNUMD AS INT) AS HOSEQNUMD,
    ORDDATE,
    CAST(ORDTDOL AS NUMERIC(9,2)) AS ORDTDOL,
    ORDITEMQTY,
    ORDSHIPQTY,
    CAST(1 AS INT) AS ORDFREQ,
    SOURCE AS ORDSOURCE,
    Ordchanneltype AS ORDCHANNEL,
    CAST(ORDCOGS AS NUMERIC(9,2)) AS ORDCOGS,
    CAST(ORDCANCEL AS NUMERIC(9,2)) AS ORDCANCEL,
    CAST(ORDRETURN AS NUMERIC(9,2)) AS ORDRETURN,
    CAST(ORDSOLDOUT AS NUMERIC(9,2)) AS ORDSOLDOUT,
    CAST(ORDDISCNT AS NUMERIC(9,2)) AS ORDDISCNT,
    CAST(ORDERTAX_AMOUNT AS NUMERIC(9,2)) AS TAXAMT,
    ORDPAYMENT1,
    ORDPAYMENT2,
    ORDCCTYPE,
    OTYPE,
    offer AS ORDOFFER,
    PROMO_DESC,
    PROMO_QUALIFY_AMT,
    keycode AS ORDKEYCODE,
    ORDDER_ENTRY_DATE AS ORDER_ENTRY_DATE,
    CASE WHEN file_date = '20130829' OR file_date > '20130901' THEN TRY_CONVERT(NUMERIC(9,2),FREIGHT_CHARGES)
    ELSE TRY_CONVERT(NUMERIC(9,2) ,ORDERFREIGHT_AMOUNT) END
    AS ORDERFREIGHT_AMOUNT,
    CAST(PAYMENT_TYPECODE AS VARCHAR(20))  AS PAYMENT_TYPECODE,
    SERVICE_LEVEL,
    GIFT_FLAG,
    UNDISCOUNTED_FREIGHT AS ORDER_UNDISCOUNTED_FREIGHT_AMOUNT,
    FULLY_SHIPPEDFLAG,
    APPLIED_PROMOCODE,
    PROMO_GIVEN,
    PROMO_DISCOUNT,
    MEMBER_DISCOUNT,
    MEMBER_PROGRAM,
    MEMBER_PROGRAM_SEQ,
    UPSELL_SEQ,
    REPLACE(DETAIL_REFERRING_CAT,',','') DETAIL_REFERRING_CAT,
    REFERRING_DOMAIN,
    REPLACE(REFERRING_WEBSITE,',',' ') REFERRING_WEBSITE,
    REPLACE(SEARCH_PHRASE,',',' ') SEARCH_PHRASE,
    BRAND_CWD_EFFORT,
    BRANDFROM_ORDER,
    CASE WHEN file_date = '20130829' OR file_date > '20130901' THEN
    TRY_CONVERT(NUMERIC(9,2), ADDTL_ORDER_CHARGES) ELSE TRY_CONVERT(NUMERIC(9,2) ,EST_FREIGHTCOSTS ) END AS PROCESSING_FEE,
    CAST(ORDMKTCAT AS NUMERIC(9,2)) AS ORDMKTCAT,
    CAST (ORDMKTWEB AS NUMERIC(9,2)) AS ORDMKTWEB,
    TRY_CONVERT(NUMERIC(9,2),ACTUAL_FREIGHTCOSTS) AS ORDFREIGHT_EXPENSE,
    CASE
    WHEN CAST(ORDMKTCAT AS NUMERIC(9,2)) > 0 AND CAST (ORDMKTWEB AS NUMERIC(9,2)) > 0 THEN 'CATALOG & WEB'
    WHEN CAST (ORDMKTWEB AS NUMERIC(9,2)) > 0 AND CAST(ORDMKTCAT AS NUMERIC(9,2)) = 0 THEN 'WEB ONLY'
    WHEN CAST(ORDMKTCAT AS NUMERIC(9,2)) > 0 AND CAST (ORDMKTWEB AS NUMERIC(9,2)) = 0 THEN 'CATALOG ONLY'
    ELSE NULL
    END AS MRKTCHANNEL,
    HO_ODATE,
    ISNULL(MEDIUM_CODE,'') UTM_MEDIUM_CODE,
    ISNULL(SOURCE_CODE,'') UTM_SOURCE_CODE,
    ISNULL(CAMPAIGN_CODE,'') UTM_CAMPAIGN_CODE,
    ISNULL(TERM_CODE,'') UTM_TERM_CODE,
    ISNULL(CONTENT_CODE,'') UTM_CONTENT_CODE

 INTO WinstonBrand_Base.dbo.Orders
    FROM Orders 
    OUTER APPLY ufnGetOrderItemSum(ORDNO ,GIFT) CUSTITEM
    LEFT JOIN ORD_ODATE ON HHID = HO_HHID
    LEFT JOIN SHPING_CRT_HEADER S ON Orders.ORDNO = S.ORDER_NUMBER;


    /****** Object:  Index [NonClusteredIndex-20130929-123603]    Script Date: 9/29/2013 12:37:39 PM ******/
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20130929-123603] ON WinstonBrand_Base.dbo.Orders
(
    [HHID] ASC,
    [INDID] ASC,
    [ACCTNO] ASC,
    [ORDNO] ASC,
    --[AOSEQNUM] ASC,
    [HOSEQNUM] ASC,
    [HOSEQNUMD] ASC,
    --[IOSEQNUM] ASC,
    [ORDDATE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];

END
Run Code Online (Sandbox Code Playgroud)

这是ufnGetLastOrdHeader存储过程中使用的用户定义函数-

USE [WinstonBrand]
GO

/****** Object:  UserDefinedFunction [dbo].[ufnGetLastOrdHeader]    Script Date: 12/14/2018 6:50:33 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE FUNCTION [dbo].[ufnGetLastOrdHeader](@ORDNO varchar(20))
    RETURNS TABLE
AS
RETURN (
select ORDER_NUMBER, ORDERFREIGHT_AMOUNT,UNDISCOUNTED_FREIGHT,ACTUAL_FREIGHTCOSTS,EST_FREIGHTCOSTS, ADDTL_ORDER_CHARGES,ADDTL_HANDLING_FEE,FREIGHT_CHARGES, file_date,lastposition from(
   SELECT ORDER_NUMBER, ORDERFREIGHT_AMOUNT,UNDISCOUNTED_FREIGHT,ACTUAL_FREIGHTCOSTS,EST_FREIGHTCOSTS,ADDTL_ORDER_CHARGES,ADDTL_HANDLING_FEE,FREIGHT_CHARGES,file_date
, row_number() over (partition by ORDER_NUMBER order by FILE_DATE DESC) as lastposition
FROM Stage1_Order_Header where ORDER_NUMBER=@ORDNO
) S1_OH where lastposition=1)


GO
Run Code Online (Sandbox Code Playgroud)

我的问题是我无法理解为什么在仅运行此过程时会突然使用处理器。除了参数嗅探之外还有什么我应该看看的。SQL Server 的版本是 2016-SP1。如果需要更多详细信息,请告诉我。

编辑 -

我在我的SSMS窗口上运行了以下 4 个命令

DBCC FREESYSTEMCACHE ('ALL')
DBCC FREESESSIONCACHE
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
Run Code Online (Sandbox Code Playgroud)

之后,我开始通过进行一些更改来执行我的查询(因为它是在 PRODUCTION 框上完成的)。以下是使用的查询和执行计划 -

SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SET NOCOUNT ON;

declare @Start_Date datetime = getdate();
declare @Last_Date datetime
DECLARE @PROMOHIGHDATE INT = (SELECT MAX(FILE_DATE) FROM Stage1_Promotion);


With OrdersBase1 as
(
 Select * from WinstonBrand.dbo.Stage3_Orders Orders with (nolock)
 UNION ALL
 Select * from WinstonBrand.dbo.Stage1_Order_Header_HH HH with (nolock)
 WHERE YEAR(ORDDATE) = '2005' AND NOT EXISTS (SELECT 1 FROM WinstonBrand.dbo.Stage3_Orders SO with (nolock) WHERE HH.ORDNO = SO.ORDNO)
)

   Select *,

   Row_Number() over (partition by Orders.ORDNO order by Orders.Ordno,Orders.ORDDATE DESC) as lastposition
  into #baseorders
  from OrdersBase1 Orders with (nolock) --WinstonBrand.dbo.stage3_Orders Orders
    where indid is not null
  and exists
  (select 1 from WinstonBrand_Base.dbo.Items items with (nolock) where items.ITMORDNO = orders.ORDNO)


;WITH  Orders AS
  (
   SELECT b.*,OrderLoadDates.File_Date,
   ROW_NUMBER() OVER(PARTITION BY HHID ORDER BY HHID,Ordno,Orddate) AS HOSEQNUM,
   ROW_NUMBER() OVER(PARTITION BY HHID ORDER BY Orddate DESC) AS HOSEQNUMD,
   P.PROMO_DESC,P.PROMO_QUALIFY_AMT
   FROM #BaseOrders b
   OUTER APPLY (SELECT * FROM ufnGetLastOrdHeader(b.ORDNO) a WHERE b.ORDNO=a.ORDER_NUMBER)  OrderLoadDates
   OUTER APPLY ufnGetSTAGE1_Promotion(Offer,@PROMOHIGHDATE) P 


   WHERE b.lastposition = 1
  ),

  ORD_ODATE AS (
  SELECT
  HHID HO_HHID, ORDDATE HO_ODATE
  FROM ORDERS 
  WHERE HOSEQNUM = 1
  ),

  SHPING_CRT_HEADER AS (
  SELECT
  ORDER_NUMBER,  MEDIUM_CODE,  SOURCE_CODE,  CAMPAIGN_CODE,  TERM_CODE,  CONTENT_CODE
  FROM(
  SELECT
  ORDER_NUMBER,
  MEDIUM_CODE,
  SOURCE_CODE,
  CAMPAIGN_CODE,
  TERM_CODE,
  CONTENT_CODE,
  ROW_NUMBER() OVER(PARTITION BY CART_ID,ORDER_NUMBER ORDER BY LOAD_DATE DESC) ROW_SELECT
  FROM WinstonBrand.DBO.LTD_Shopping_Cart_Header with (nolock)
  WHERE --MEDIUM_CODE <> ''
  (MEDIUM_CODE <> '' OR SOURCE_CODE <> '' OR CAMPAIGN_CODE <> '' OR TERM_CODE <> '' OR CONTENT_CODE <> '')
  )A
  WHERE ROW_SELECT = 1
  ) 

    SELECT 
    HHID,
    INDID,
    ADDRID,
    COMPID,
    ACCTNO,
    EMAIL_ADD EMAIL,
    Orders.ORDNO,
    CAST(HOSEQNUM AS INT) AS HOSEQNUM,
    CAST(HOSEQNUMD AS INT) AS HOSEQNUMD,
    ORDDATE,
    CAST(ORDTDOL AS NUMERIC(9,2)) AS ORDTDOL,
    ORDITEMQTY,
    ORDSHIPQTY,
    CAST(1 AS INT) AS ORDFREQ,
    SOURCE AS ORDSOURCE,
    Ordchanneltype AS ORDCHANNEL,
    CAST(ORDCOGS AS NUMERIC(9,2)) AS ORDCOGS,
    CAST(ORDCANCEL AS NUMERIC(9,2)) AS ORDCANCEL,
    CAST(ORDRETURN AS NUMERIC(9,2)) AS ORDRETURN,
    CAST(ORDSOLDOUT AS NUMERIC(9,2)) AS ORDSOLDOUT,
    CAST(ORDDISCNT AS NUMERIC(9,2)) AS ORDDISCNT,
    CAST(ORDERTAX_AMOUNT AS NUMERIC(9,2)) AS TAXAMT,
    ORDPAYMENT1,
    ORDPAYMENT2,
    ORDCCTYPE,
    OTYPE,
    offer AS ORDOFFER,
    PROMO_DESC,
    PROMO_QUALIFY_AMT,
    keycode AS ORDKEYCODE,
    ORDDER_ENTRY_DATE AS ORDER_ENTRY_DATE,
    --Freight_Charges,
    CASE WHEN file_date = '20130829' OR file_date > '20130901' THEN TRY_CONVERT(NUMERIC(9,2),FREIGHT_CHARGES)
    ELSE TRY_CONVERT(NUMERIC(9,2) ,ORDERFREIGHT_AMOUNT) END
    AS ORDERFREIGHT_AMOUNT,
    CAST(PAYMENT_TYPECODE AS VARCHAR(20))  AS PAYMENT_TYPECODE,
    SERVICE_LEVEL,
    GIFT_FLAG,
    UNDISCOUNTED_FREIGHT AS ORDER_UNDISCOUNTED_FREIGHT_AMOUNT,
    --ACTUAL_FREIGHTCOSTS as FREIGHT_EXPENSE,
    FULLY_SHIPPEDFLAG,
    APPLIED_PROMOCODE,
    PROMO_GIVEN,
    PROMO_DISCOUNT,
    MEMBER_DISCOUNT,
    MEMBER_PROGRAM,
    MEMBER_PROGRAM_SEQ,
    UPSELL_SEQ,
    REPLACE(DETAIL_REFERRING_CAT,',','') DETAIL_REFERRING_CAT,
    REFERRING_DOMAIN,
    REPLACE(REFERRING_WEBSITE,',',' ') REFERRING_WEBSITE,
    REPLACE(SEARCH_PHRASE,',',' ') SEARCH_PHRASE,
    BRAND_CWD_EFFORT,
    BRANDFROM_ORDER,
    CASE WHEN file_date = '20130829' OR file_date > '20130901' THEN
    TRY_CONVERT(NUMERIC(9,2), ADDTL_ORDER_CHARGES) ELSE TRY_CONVERT(NUMERIC(9,2) ,EST_FREIGHTCOSTS ) END AS PROCESSING_FEE,
    CAST(ORDMKTCAT AS NUMERIC(9,2)) AS ORDMKTCAT,
    CAST (ORDMKTWEB AS NUMERIC(9,2)) AS ORDMKTWEB,
    TRY_CONVERT(NUMERIC(9,2),ACTUAL_FREIGHTCOSTS) AS ORDFREIGHT_EXPENSE,
    CASE
    WHEN CAST(ORDMKTCAT AS NUMERIC(9,2)) > 0 AND CAST (ORDMKTWEB AS NUMERIC(9,2)) > 0 THEN 'CATALOG & WEB'
    WHEN CAST (ORDMKTWEB AS NUMERIC(9,2)) > 0 AND CAST(ORDMKTCAT AS NUMERIC(9,2)) = 0 THEN 'WEB ONLY'
    WHEN CAST(ORDMKTCAT AS NUMERIC(9,2)) > 0 AND CAST (ORDMKTWEB AS NUMERIC(9,2)) = 0 THEN 'CATALOG ONLY'
    ELSE NULL
    END AS MRKTCHANNEL,
    HO_ODATE,
    ISNULL(MEDIUM_CODE,'') UTM_MEDIUM_CODE,
    ISNULL(SOURCE_CODE,'') UTM_SOURCE_CODE,
    ISNULL(CAMPAIGN_CODE,'') UTM_CAMPAIGN_CODE,
    ISNULL(TERM_CODE,'') UTM_TERM_CODE,
    ISNULL(CONTENT_CODE,'') UTM_CONTENT_CODE

 INTO WinstonBrand_Base.dbo.Orders_DBA
    FROM Orders with (nolock)
    OUTER APPLY ufnGetOrderItemSum(ORDNO ,GIFT) CUSTITEM
    LEFT JOIN ORD_ODATE ON HHID = HO_HHID
    LEFT JOIN SHPING_CRT_HEADER S ON Orders.ORDNO = S.ORDER_NUMBER;


    /****** Object:  Index [NonClusteredIndex-20130929-123603]    Script Date: 9/29/2013 12:37:39 PM ******/
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20130929-123603_DBA] ON WinstonBrand_Base.dbo.Orders_DBA
(
    [HHID] ASC,
    [INDID] ASC,
    [ACCTNO] ASC,
    [ORDNO] ASC,
    [HOSEQNUM] ASC,
    [HOSEQNUMD] ASC,
    [ORDDATE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY];

SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
Run Code Online (Sandbox Code Playgroud)

以下是打印在 SSMS 结果窗口上的消息 -

SQL Server 执行时间:CPU 时间 = 0 毫秒,已用时间 = 0 毫秒。

SQL Server 执行时间:CPU 时间 = 0 毫秒,已用时间 = 0 毫秒。表'Stage1_Promotion'。扫描计数 1,逻辑读 2248,物理读 4,预读 2198,lob 逻辑读 0,lob 物理读 0,lob 预读 0。

SQL Server 执行时间:CPU 时间 = 47 毫秒,已用时间 = 68 毫秒。表“项目”。扫描计数 6,逻辑读取 11895581,物理读取 8481,预读读取 11793819,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage3_Orders'。扫描计数 12,逻辑读取 2258024,物理读取 41,预读读取 2257333,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage1_Order_Header_HH'。扫描计数 6,逻辑读取 435021,物理读取 0,预读读取 435021,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Worktable'。扫描计数 0,逻辑读取 0,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Workfile'。扫描计数 50,逻辑读取 83864,

SQL Server 执行时间:CPU 时间 = 1370469 毫秒,已用时间 = 836897 毫秒。

SQL Server 解析和编译时间:CPU 时间 = 5734 毫秒,已用时间 = 5827 毫秒。表“工作台”。扫描计数 203343290,逻辑读取 1778461093,物理读取 470694,预读读取 2151647,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'LTD_Shopping_Cart_Header'。扫描计数 1,逻辑读取 404060,物理读取 0,预读读取 404060,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Workfile'。扫描计数 3752,逻辑读取 9917704,物理读取 1903935,预读读取 13387577,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Items'。扫描计数1,逻辑读11895581,物理读6902,预读11292947,lob逻辑读0,lob物理读0,lob预读0。表' Stage1_Order_Header'。扫描计数 2,逻辑读取 2068767,物理读取 4,预读读取 1034391,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 '#baseorders___________________________________________________________________________________________________________________000000001C31'。扫描计数 2,逻辑读取 4239764,物理读取 140,预读读取 1994015,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage1_Promotion'。扫描计数 2,逻辑读取 4496,物理读取 4,预读读取 2198,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。警告:空值被聚合或其他 SET 操作消除。lob 物理读取 0,lob 预读读取 0。表 '#baseorders_________________________________________________________________________________________________________000000001C31'。扫描计数 2,逻辑读取 4239764,物理读取 140,预读读取 1994015,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage1_Promotion'。扫描计数 2,逻辑读取 4496,物理读取 4,预读读取 2198,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。警告:空值被聚合或其他 SET 操作消除。lob 物理读取 0,lob 预读读取 0。表 '#baseorders_________________________________________________________________________________________________________000000001C31'。扫描计数 2,逻辑读取 4239764,物理读取 140,预读读取 1994015,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage1_Promotion'。扫描计数 2,逻辑读取 4496,物理读取 4,预读读取 2198,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。警告:空值被聚合或其他 SET 操作消除。预读读取 1994015,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage1_Promotion'。扫描计数 2,逻辑读取 4496,物理读取 4,预读读取 2198,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。警告:空值被聚合或其他 SET 操作消除。预读读取 1994015,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Stage1_Promotion'。扫描计数 2,逻辑读取 4496,物理读取 4,预读读取 2198,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。警告:空值被聚合或其他 SET 操作消除。

SQL Server 执行时间:CPU 时间 = 7282594 毫秒,已用时间 = 8292072 毫秒。表“工作台”。扫描计数 0,逻辑读取 0,物理读取 0,预读读取 521245,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。表 'Orders_DBA'。扫描计数 1,逻辑读 2343169,物理读 0,预读 31057,lob 逻辑读 0,lob 物理读 0,lob 预读 0。

SQL Server 执行时间:CPU 时间 = 298765 毫秒,已用时间 = 312090 毫秒。

SQL Server 执行时间:CPU 时间 = 0 毫秒,已用时间 = 0 毫秒。

下面是查询运行时间段的资源利用率图。查询开始运行,15:43 EST并需要2:37:27几个小时才能完成。

在此处输入图片说明

这是查询计划的链接

Ran*_*gen 4

如果不了解更多关于表结构的信息,并且没有测试数据,这些是您可以尝试的事情。

第 1 部分:插入#baseorders(相比之下“不太重要”)

在这一部分中,可以对where子句进行一些更改,因此函数不适用于ORDDATE。根据统计,这部分需要 22 分钟的 CPU 时间。

With OrdersBase1 as
(
 Select * from WinstonBrand.dbo.Stage3_Orders Orders with (nolock)
 UNION ALL
 Select * from WinstonBrand.dbo.Stage1_Order_Header_HH HH with (nolock)
 WHERE ORDDATE > '2004-12-31 23:59:59.999' AND ORDDATE <  '2006-01-01 00:00:00.000' -- Functions on Columns are bad for indexing.
AND NOT EXISTS (SELECT 1 FROM WinstonBrand.dbo.Stage3_Orders SO with (nolock) WHERE HH.ORDNO = SO.ORDNO)
)

   Select *,

   Row_Number() over (partition by Orders.ORDNO order by Orders.Ordno,Orders.ORDDATE DESC) as lastposition
  into #baseorders
  from OrdersBase1 Orders with (nolock) --WinstonBrand.dbo.stage3_Orders Orders
    where indid is not null
  and exists
  (select 1 from WinstonBrand_Base.dbo.Items items with (nolock) where items.ITMORDNO = orders.ORDNO)
Run Code Online (Sandbox Code Playgroud)

但是,除非我们在 Stage1_Order_Header_H (ORDNO,ORDDATE) 上有索引,否则这些更改不会产生太大影响

在此输入图像描述

当然,由于我们要做的是select *,索引就需要覆盖整个表。

CREATE INDEX IX_Stage1_Order_Header_H
ON dbo.Stage1_Order_Header_H(ORDNO,ORDDATE)
INCLUDE(everything)
Run Code Online (Sandbox Code Playgroud)

这并不理想。作为旁注,这里是关于改进 select 的分组会议*

如果您只是使用它进行处理,而不是对其进行大量键查找,那么您可以尝试在所涉及的表上创建聚集或非聚集列存储索引。列存储使批处理速度更快。

CREATE CLUSTERED COLUMNSTORE INDEX CCX_Stage1_Order_Header_H
 ON dbo.Stage1_Order_Header_H
Run Code Online (Sandbox Code Playgroud)

第 2 部分:插入 WinstonBrand_Base.dbo.Orders_DBA

或者正如我想称之为的,sortfest。这是最重要的部分,CPU 时间为 2:01:22.594。

附件一:

在此输入图像描述

深入挖掘证据

在索引假脱机上,我们有一个 CONVERT IMPLICIT,我们需要将其删除。 在此输入图像描述

难道 ORDER_NUMBER 是 nvarchar,并且是这样的:

 CREATE FUNCTION [dbo].[ufnGetLastOrdHeader](@ORDNO varchar(20)) 
Run Code Online (Sandbox Code Playgroud)

应该改为这样:

 CREATE FUNCTION [dbo].[ufnGetLastOrdHeader](@ORDNO nvarchar(20)) 
Run Code Online (Sandbox Code Playgroud)

但是,它是在参数上进行转换,而不是在列上进行转换,因此基于性能并不是发生这种情况的最糟糕情况。如果可以修复,就应该修复。

之后,我会尝试添加这个索引:

CREATE INDEX IX_Stage1_Order_Header
on dbo.Stage1_Order_Header(ORDER_NUMBER,FILE_DATE)
INCLUDE( ORDERFREIGHT_AMOUNT,UNDISCOUNTED_FREIGHT,ACTUAL_FREIGHTCOSTS,EST_FREIGHTCOSTS,ADDTL_ORDER_CHARGES,ADDTL_HANDLING_FEE,FREIGHT_CHARGES)
Run Code Online (Sandbox Code Playgroud)

尝试删除其中的 2 种。排序是非常昂贵的。

需要明确的是,考虑删除函数本身或重写也是一件需要考虑的事情,但如果没有表定义和数据集,就很难测试。

附件B:

在此输入图像描述

  CREATE INDEX IX_LTD_Shopping_Cart_Header_ORDER_NUMBER_CART_ID_LOAD_DATE
  on DBO.LTD_Shopping_Cart_Header(ORDER_NUMBER,CART_ID,LOAD_DATE)
  INCLUDE(

  MEDIUM_CODE,
  SOURCE_CODE,
  CAMPAIGN_CODE,
  TERM_CODE,
  CONTENT_CODE,
  )
Run Code Online (Sandbox Code Playgroud)

图表 C.1:

在此输入图像描述 这个有点棘手,有些选择会选择临时表中的所有内容,但您可能会通过在过程中添加以下索引来看到结果。

   CREATE INDEX IX_BaseOrders
ON #BaseOrders(HHID,Ordno,Orddate)
include(everything)
Run Code Online (Sandbox Code Playgroud)

图表 C.2

在此输入图像描述

简而言之

简而言之,排序是我首先要尝试改进的事情,因为它们会占用大量 CPU 时间。重写查询、函数、省略不需要的数据……将是我的第一个方法,但是通过索引来删除这些排序应该会有帮助。

  • 感谢@Randi 提供详细的解决方案。我一定会尝试一下并让你知道。 (2认同)