How to improve query performance for expensive table spool
There is a requirement to get the data from a single stage table with the below query. However, the query is taking lots of time to execute. How to optimize the below query?
Execution plan says there is table spool which is 50% of entire cost and estimated operated cost in 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
)
Can anybody provide any suggestion for the above scenario?
sql sql-server tsql indexing
add a comment |
There is a requirement to get the data from a single stage table with the below query. However, the query is taking lots of time to execute. How to optimize the below query?
Execution plan says there is table spool which is 50% of entire cost and estimated operated cost in 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
)
Can anybody provide any suggestion for the above scenario?
sql sql-server tsql indexing
Could you note the execution time of every query in the batch?
– serge
Nov 14 '18 at 10:24
8.5 mins for this insert to #tmp table
– Jai Asnani
Nov 14 '18 at 10:28
1
Start by removing *NOLOCK
. That doesn't mean go fast or don't lock, it means "read dirty and duplicate data while taking excessive locks and miss some rows completely"
– Panagiotis Kanavos
Nov 14 '18 at 10:41
1
There are many problems with that query - converting dates to strings, sums and casts in WHERE or HAVING clauses, groups in subqueries. That single table spool is the least of the problems. Applying functions to a field prevents the server from using any indexes that cover it.ClientEWSWarrantySKU
et seems to be flags and that big CASE is trying to determine the value of those flags. Use a separate table instead of thatcase
to determine the value ofEWSPlan
with a simple join.
– Panagiotis Kanavos
Nov 14 '18 at 10:47
Thanks for the suggestion! Instead of below case statement (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 Used below and SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) in (6,15,33,42) . WIll this be fine?
– Jai Asnani
Nov 14 '18 at 10:55
add a comment |
There is a requirement to get the data from a single stage table with the below query. However, the query is taking lots of time to execute. How to optimize the below query?
Execution plan says there is table spool which is 50% of entire cost and estimated operated cost in 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
)
Can anybody provide any suggestion for the above scenario?
sql sql-server tsql indexing
There is a requirement to get the data from a single stage table with the below query. However, the query is taking lots of time to execute. How to optimize the below query?
Execution plan says there is table spool which is 50% of entire cost and estimated operated cost in 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
)
Can anybody provide any suggestion for the above scenario?
sql sql-server tsql indexing
sql sql-server tsql indexing
edited Nov 14 '18 at 10:26
Jai Asnani
asked Nov 14 '18 at 10:04
Jai AsnaniJai Asnani
224
224
Could you note the execution time of every query in the batch?
– serge
Nov 14 '18 at 10:24
8.5 mins for this insert to #tmp table
– Jai Asnani
Nov 14 '18 at 10:28
1
Start by removing *NOLOCK
. That doesn't mean go fast or don't lock, it means "read dirty and duplicate data while taking excessive locks and miss some rows completely"
– Panagiotis Kanavos
Nov 14 '18 at 10:41
1
There are many problems with that query - converting dates to strings, sums and casts in WHERE or HAVING clauses, groups in subqueries. That single table spool is the least of the problems. Applying functions to a field prevents the server from using any indexes that cover it.ClientEWSWarrantySKU
et seems to be flags and that big CASE is trying to determine the value of those flags. Use a separate table instead of thatcase
to determine the value ofEWSPlan
with a simple join.
– Panagiotis Kanavos
Nov 14 '18 at 10:47
Thanks for the suggestion! Instead of below case statement (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 Used below and SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) in (6,15,33,42) . WIll this be fine?
– Jai Asnani
Nov 14 '18 at 10:55
add a comment |
Could you note the execution time of every query in the batch?
– serge
Nov 14 '18 at 10:24
8.5 mins for this insert to #tmp table
– Jai Asnani
Nov 14 '18 at 10:28
1
Start by removing *NOLOCK
. That doesn't mean go fast or don't lock, it means "read dirty and duplicate data while taking excessive locks and miss some rows completely"
– Panagiotis Kanavos
Nov 14 '18 at 10:41
1
There are many problems with that query - converting dates to strings, sums and casts in WHERE or HAVING clauses, groups in subqueries. That single table spool is the least of the problems. Applying functions to a field prevents the server from using any indexes that cover it.ClientEWSWarrantySKU
et seems to be flags and that big CASE is trying to determine the value of those flags. Use a separate table instead of thatcase
to determine the value ofEWSPlan
with a simple join.
– Panagiotis Kanavos
Nov 14 '18 at 10:47
Thanks for the suggestion! Instead of below case statement (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 Used below and SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) in (6,15,33,42) . WIll this be fine?
– Jai Asnani
Nov 14 '18 at 10:55
Could you note the execution time of every query in the batch?
– serge
Nov 14 '18 at 10:24
Could you note the execution time of every query in the batch?
– serge
Nov 14 '18 at 10:24
8.5 mins for this insert to #tmp table
– Jai Asnani
Nov 14 '18 at 10:28
8.5 mins for this insert to #tmp table
– Jai Asnani
Nov 14 '18 at 10:28
1
1
Start by removing *
NOLOCK
. That doesn't mean go fast or don't lock, it means "read dirty and duplicate data while taking excessive locks and miss some rows completely"– Panagiotis Kanavos
Nov 14 '18 at 10:41
Start by removing *
NOLOCK
. That doesn't mean go fast or don't lock, it means "read dirty and duplicate data while taking excessive locks and miss some rows completely"– Panagiotis Kanavos
Nov 14 '18 at 10:41
1
1
There are many problems with that query - converting dates to strings, sums and casts in WHERE or HAVING clauses, groups in subqueries. That single table spool is the least of the problems. Applying functions to a field prevents the server from using any indexes that cover it.
ClientEWSWarrantySKU
et seems to be flags and that big CASE is trying to determine the value of those flags. Use a separate table instead of that case
to determine the value of EWSPlan
with a simple join.– Panagiotis Kanavos
Nov 14 '18 at 10:47
There are many problems with that query - converting dates to strings, sums and casts in WHERE or HAVING clauses, groups in subqueries. That single table spool is the least of the problems. Applying functions to a field prevents the server from using any indexes that cover it.
ClientEWSWarrantySKU
et seems to be flags and that big CASE is trying to determine the value of those flags. Use a separate table instead of that case
to determine the value of EWSPlan
with a simple join.– Panagiotis Kanavos
Nov 14 '18 at 10:47
Thanks for the suggestion! Instead of below case statement (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 Used below and SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) in (6,15,33,42) . WIll this be fine?
– Jai Asnani
Nov 14 '18 at 10:55
Thanks for the suggestion! Instead of below case statement (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 Used below and SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) in (6,15,33,42) . WIll this be fine?
– Jai Asnani
Nov 14 '18 at 10:55
add a comment |
1 Answer
1
active
oldest
votes
I can suggest to you using EXISTS instead of IN. Could you apply these following changes and check whether faster or nor :
Before you insert into #tmp table apply this script :
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
After that remove these where conditions :
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 put the following condition :
AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID )
It should looks like :
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
)
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297554%2fhow-to-improve-query-performance-for-expensive-table-spool%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I can suggest to you using EXISTS instead of IN. Could you apply these following changes and check whether faster or nor :
Before you insert into #tmp table apply this script :
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
After that remove these where conditions :
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 put the following condition :
AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID )
It should looks like :
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
)
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
add a comment |
I can suggest to you using EXISTS instead of IN. Could you apply these following changes and check whether faster or nor :
Before you insert into #tmp table apply this script :
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
After that remove these where conditions :
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 put the following condition :
AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID )
It should looks like :
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
)
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
add a comment |
I can suggest to you using EXISTS instead of IN. Could you apply these following changes and check whether faster or nor :
Before you insert into #tmp table apply this script :
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
After that remove these where conditions :
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 put the following condition :
AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID )
It should looks like :
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
)
I can suggest to you using EXISTS instead of IN. Could you apply these following changes and check whether faster or nor :
Before you insert into #tmp table apply this script :
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
After that remove these where conditions :
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 put the following condition :
AND EXISTS (SELECT 1 FROM #EnrTemp E WHERE STG.CustomerID = E.CustomerID AND STG.ProductSKU = E.ProductSKU AND STG.StoreID = E.StoreID )
It should looks like :
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
)
edited Nov 14 '18 at 10:35
answered Nov 14 '18 at 10:30
Zeki GumusZeki Gumus
1,402212
1,402212
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
add a comment |
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
Thanks alot @Ayzek this solution worked :-)
– Jai Asnani
Nov 14 '18 at 11:13
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297554%2fhow-to-improve-query-performance-for-expensive-table-spool%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Could you note the execution time of every query in the batch?
– serge
Nov 14 '18 at 10:24
8.5 mins for this insert to #tmp table
– Jai Asnani
Nov 14 '18 at 10:28
1
Start by removing *
NOLOCK
. That doesn't mean go fast or don't lock, it means "read dirty and duplicate data while taking excessive locks and miss some rows completely"– Panagiotis Kanavos
Nov 14 '18 at 10:41
1
There are many problems with that query - converting dates to strings, sums and casts in WHERE or HAVING clauses, groups in subqueries. That single table spool is the least of the problems. Applying functions to a field prevents the server from using any indexes that cover it.
ClientEWSWarrantySKU
et seems to be flags and that big CASE is trying to determine the value of those flags. Use a separate table instead of thatcase
to determine the value ofEWSPlan
with a simple join.– Panagiotis Kanavos
Nov 14 '18 at 10:47
Thanks for the suggestion! Instead of below case statement (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 Used below and SUM(DISTINCT CAST(stg.ClientEWSWarrantySKU AS INT)) in (6,15,33,42) . WIll this be fine?
– Jai Asnani
Nov 14 '18 at 10:55