如何提高昂贵的表后台处理程序的查询性能

时间:2018-11-14 10:04:30

标签: sql sql-server tsql indexing

enter image description here需要使用以下查询从单阶段表中获取数据。但是,该查询需要大量时间才能执行。如何优化以下查询? 执行计划说,有一个表线轴,占总成本的50%,并在12.22中估算了运营成本。

CREATE TABLE #Enrollment_grp 
(
rowcounts int,
CustomerID NVARCHAR(100),
EWSPurchaseDate  DATETIME,
EWSPlanType nvarchar(200),
ContractStatus nvarchar(200),
TerminationDate  DATETIME,
StoreId [nvarchar](100) NULL,
CreatedDate DATETIME NULL,
ProductSKU [nvarchar](200) NULL,
ClientEWSWarrantySKU [nvarchar](100) NULL,
COUNTSL int null
)

CREATE CLUSTERED INDEX IDX_Enrollment_GRP_CustomerID ON #Enrollment_grp(CustomerID)

CREATE NONCLUSTERED INDEX IDX_Enrollment_GRP_EWSPUR ON #Enrollment_grp(EWSPurchaseDate)

CREATE NONCLUSTERED INDEX IDX_Enrollment_GRP_TERMDATE ON #Enrollment_grp(TerminationDate)

insert INTO #Enrollment_grp(CustomerID,EWSPurchaseDate,rowcounts,EWSPlanType,ContractStatus,TerminationDate,StoreID,CreatedDate,ProductSKU,ClientEWSWarrantySKU,COUNTSL)
(
SELECT CustomerID,EWSPurchaseDate,rowcounts,EWSPlanType,ContractStatus,temp.TerminationDate,temp.StoreID,temp.CreatedDate,temp.ProductSKU,temp.ClientEWSWarrantySKU,COUNTSL
from
(

SELECT x.CustomerID,x.EWSPurchaseDate,ROW_NUMBER() over(PARTITION BY x.CustomerID,x.EWSPlanType ORDER BY x.CreatedDate DESC) as rowcounts,
count(EWSPlanType) over (PARTITION BY x.CustomerID,x.EWSPlanType ORDER BY x.CreatedDate) COUNTSL,x.EWSPlanType,x.ContractStatus
,x.TerminationDate,X.StoreID,X.CreatedDate,x.ProductSKU,x.ClientEWSWarrantySKU
FROM STAGE_ENROLLMENT AS x (NOLOCK) WHERE x.ClientID = 1
) AS temp WHERE temp.rowcounts=1 AND cast(temp.TerminationDate AS DATE)>='2018-10-01'
)

CREATE TABLE #tmp
(
    ID int IDENTITY(1,1) PRIMARY KEY,
    TransactionNo [nvarchar](100) NULL,
    StoreName [nvarchar](100) NULL,
    EWSPlan NVARCHAR(200),
    EventDate DATETIME NULL,
    ProductType [nvarchar](200) NULL,
    PlanStartDate [varchar](50) NULL,
    PlanEndDate [varchar](50) NULL
)

CREATE NONCLUSTERED INDEX IX_tmp_TN
ON #tmp(TransactionNo)


INSERT INTO #tmp
(TransactionNo,
StoreName,
EWSPlan,
ProductType,
PlanStartDate,
PlanEndDate
)
(SELECT DISTINCT
stg.CustomerID AS TransactionNo,
stg.StoreID AS StoreName,
CASE WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 6 THEN 'AA'
    WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 15 THEN 'BB'
    WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 33 THEN 'CC'
    WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 42 THEN 'DD'
END AS EWSPlan,
stg.ProductSKU AS ProductType,
cast(format(stg.EWSPurchaseDate,'yyyy/MM/dd') as VARCHAR) AS PlanStartDate ,
'' AS PlanEndDate--,
FROM STAGE_ENROLLMENT AS stg (NOLOCK)
WHERE stg.ClientID = 1
AND stg.EWSPurchaseDate<='2018-10-31' AND stg.TerminationDate>='2018-10-01'
AND stg.ContractStatus = 1
AND stg.CustomerID IN (SELECT CustomerID FROM #Enrollment_grp where EWSPurchaseDate<='2018-10-31' AND TerminationDate>='2018-10-01' GROUP BY CustomerID HAVING COUNT(DISTINCT EWSPlanType) = 3 )
AND stg.ProductSKU IN (SELECT ProductSKU FROM #Enrollment_grp where EWSPurchaseDate<='2018-10-31' AND TerminationDate>='2018-10-01' GROUP BY ProductSKU HAVING COUNT(DISTINCT EWSPlanType) = 3 )
AND stg.StoreID IN (SELECT StoreID FROM #Enrollment_grp where EWSPurchaseDate<='2018-10-31' AND TerminationDate>='2018-10-01' GROUP BY StoreID HAVING COUNT(DISTINCT EWSPlanType) = 3 )
GROUP BY stg.CustomerID,stg.EWSPurchaseDate,stg.StoreID,stg.ProductSKU
HAVING COUNT(DISTINCT stg.EWSPlanType) = 3 
AND 
(CASE WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 6 THEN 'AA'
WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 15 THEN 'BB' 
WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 33 THEN 'CC' 
WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 42 THEN 'DD'
END) IS NOT NULL 
)

有人可以针对上述情况提供任何建议吗?

1 个答案:

答案 0 :(得分:1)

我可以建议您使用EXISTS代替IN。您能否应用以下更改并检查是否更快?

在您插入#tmp表之前,请先应用以下脚本:

SELECT CustomerID,ProductSKU,StoreID INTO #EnrTemp FROM #Enrollment_grp WHERE EWSPurchaseDate <= '2018-10-31' AND TerminationDate >= '2018-10-01' GROUP BY CustomerID,ProductSKU,StoreID HAVING COUNT(DISTINCT EWSPlanType)= 3

之后,删除这些条件:

AND stg.CustomerID IN (SELECT CustomerID FROM #Enrollment_grp WHERE EWSPurchaseDate <= '2018-10-31' AND TerminationDate >= '2018-10-01' GROUP BY CustomerID HAVING COUNT(DISTINCT EWSPlanType) = 3)
AND stg.ProductSKU IN (SELECT ProductSKU FROM #Enrollment_grp WHERE EWSPurchaseDate <= '2018-10-31' AND TerminationDate >= '2018-10-01' GROUP BY ProductSKU HAVING COUNT(DISTINCT EWSPlanType) = 3)
AND stg.StoreID    IN (SELECT StoreID    FROM #Enrollment_grp WHERE EWSPurchaseDate <= '2018-10-31' AND TerminationDate >= '2018-10-01' GROUP BY StoreID HAVING COUNT(DISTINCT EWSPlanType) = 3) 

并设置以下条件:

AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID  )

它看起来应该像:

SELECT CustomerID,ProductSKU,StoreID INTO #EnrTemp FROM #Enrollment_grp WHERE EWSPurchaseDate <= '2018-10-31' AND TerminationDate >= '2018-10-01' GROUP BY CustomerID,ProductSKU,StoreID HAVING COUNT(DISTINCT EWSPlanType)= 3

INSERT INTO #tmp (TransactionNo,
StoreName,
EWSPlan,
ProductType,
PlanStartDate,
PlanEndDate)
    (SELECT DISTINCT
        stg.CustomerID AS TransactionNo
       ,stg.StoreID AS StoreName
       ,CASE
            WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 6 THEN 'AA'
            WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 15 THEN 'BB'
            WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 33 THEN 'CC'
            WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 42 THEN 'DD'
        END AS EWSPlan
       ,stg.ProductSKU AS ProductType
       ,CAST(FORMAT(stg.EWSPurchaseDate, 'yyyy/MM/dd') AS VARCHAR) AS PlanStartDate
       ,'' AS PlanEndDate--,
    FROM STAGE_ENROLLMENT AS stg (NOLOCK)
    WHERE stg.ClientID = 1
    AND stg.EWSPurchaseDate <= '2018-10-31'
    AND stg.TerminationDate >= '2018-10-01'
    AND stg.ContractStatus = 1
    AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID  )
    GROUP BY stg.CustomerID,stg.EWSPurchaseDate,stg.StoreID,stg.ProductSKU HAVING COUNT(DISTINCT stg.EWSPlanType) = 3
    AND (CASE
        WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 6 THEN 'AA'
        WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 15 THEN 'BB'
        WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 33 THEN 'CC'
        WHEN SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) = 42 THEN 'DD'
    END) IS NOT NULL
    )