Flynnster
asked on
Need help with a Stored Procedure
I've got this wonderful Stored Procedure that is about to make me punt my laptop.
Yesterday, it worked fine. This morning I made one small tweak (changing a parameter to a variable), and now it runs for well over five minutes without returning anything.
When I take out the SQL and run it directly, it runs in under a minute. When I comment out the SQL, the Stored Procedure runs just fine in under a second.
Could someone please review this Stored Procedure and look to see if you can find any glaring errors ?
Thanks!
- Flynn
Yesterday, it worked fine. This morning I made one small tweak (changing a parameter to a variable), and now it runs for well over five minutes without returning anything.
When I take out the SQL and run it directly, it runs in under a minute. When I comment out the SQL, the Stored Procedure runs just fine in under a second.
Could someone please review this Stored Procedure and look to see if you can find any glaring errors ?
Thanks!
- Flynn
--DROP PROCEDURE [dbo].[stp_Crystal_EndingInventoryTotals_AllStores_FGK]
--GO
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
--CREATE PROCEDURE [dbo].[stp_Crystal_EndingInventoryTotals_AllStores_FGK]
ALTER PROCEDURE [dbo].[stp_Crystal_EndingInventoryTotals_AllStores_FGK]
@InventoryDateParam smalldatetime = null,
@IncludeNullDept bit = 0--,
--@YESTERDAY smalldatetime ,
--@RTNCODE char
AS
DECLARE
@YESTERDAY smalldatetime ,
@RTNCODE char
/*
Create table #tblStoreAttributes (
StoreNbr smallint,
[Address] varchar(50),
City varchar(50),
[State] char(2),
PostalCode char(10),
County char(30),
CompanyStoreFlag bit,
WPLAreaName varchar(50)
)
*/
--Retrieve store attributes
--Insert Into #tblStoreAttributes
--Execute @RtnCode = stp_RetrieveActiveStoreAttributes_AdBook
If @RtnCode <> 0
Begin
Print 'Return code ' + convert(varchar(12), @RtnCode) + ' received from stp_RetrieveActiveStoreAttributes_AdBook.'
Return 5
End
Select @Yesterday = Dateadd(d, -1, @InventoryDateParam)
;WITH RUN1 AS (
SELECT ID,StoreConfiguration_StoreNbr, InventoryDate
FROM Inventory.HistoricalInventory
WHERE InventoryDate = @Yesterday)
, RUN2 AS (
SELECT ID,StoreConfiguration_StoreNbr, InventoryDate
FROM Inventory.HistoricalInventory
WHERE InventoryDate = @InventoryDateParam)
, ST AS (
SELECT ID,StoreConfiguration_StoreNbr, InventoryDate FROM RUN1
UNION ALL
SELECT ID,StoreConfiguration_StoreNbr, InventoryDate FROM RUN2)
, GTIN AS (
SELECT DISTINCT I.GTINCode, V.StoreConfiguration_StoreNbr AS STORENBR
FROM [Control].SBTVendors V WITH (NOLOCK)
INNER JOIN Inventory.ItemAttributes I WITH (NOLOCK)
ON I.VendorNbr = V.VendorNbr
AND I.WhseCode = 0
,ST
WHERE V.StoreConfiguration_StoreNbr = ST.StoreConfiguration_StoreNbr
GROUP BY I.GTINCode, V.StoreConfiguration_StoreNbr
UNION
SELECT DISTINCT I.GTINCode, S.StoreNbr
FROM [Control].ExclusionVendors E WITH (NOLOCK)
INNER JOIN Inventory.ItemAttributes I WITH (NOLOCK)
ON I.VendorNbr = E.VendorNbr
,[Control].StoreConfiguration S
,ST
WHERE S.StoreNbr = ST.StoreConfiguration_StoreNbr
UNION
SELECT GTINCode, S.StoreNbr
FROM [Control].ExclusionGTINs
,[Control].StoreConfiguration S
,ST
WHERE S.StoreNbr = ST.StoreConfiguration_StoreNbr)
--, ATTRIB AS (Select STORENBR,City + ',' + State as DESCR From #tblStoreAttributes)
, MAIN AS(
SELECT HI.StoreConfiguration_StoreNbr AS StoreNbr, HI.InventoryDate,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryDateParam)
THEN Sum(HI.BalanceOnHand) ELSE 0 END) as CQOH,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryDateParam)
THEN Sum(HI.BalanceOnHand * Cast(HI.Cost as money)) ELSE 0 END) as CETC,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryDateParam)
THEN Sum(HI.BalanceOnHand * Cast(HI.Retail as money)) ELSE 0 END) as CETR,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryDateParam)
THEN Sum(HI.BalanceOnHand) ELSE 0 END) as PQOH,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryDateParam)
THEN Sum(HI.BalanceOnHand * Cast(HI.Cost as money)) ELSE 0 END) as PETC,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryDateParam)
THEN Sum(HI.BalanceOnHand * Cast(HI.Retail as money)) ELSE 0 END) as PETR
FROM Inventory.HistoricalInventory as HI with (nolock)
LEFT OUTER JOIN GTIN ON GTIN.STORENBR = HI.StoreConfiguration_StoreNbr
AND HI.GTINCODE = GTIN.GTINCODE
, ST
WHERE HI.SourceFlag = 'U'
AND HI.Department IN ('0','6','H')
AND HI.Category NOT IN (620,621)
AND ST.StoreConfiguration_StoreNbr = HI.StoreConfiguration_StoreNbr
AND ST.InventoryDate = HI.InventoryDate
AND ST.ID = HI.ID
AND GTIN.GTINCode IS NULL
GROUP BY HI.StoreConfiguration_StoreNbr,HI.InventoryDate)
/*
,PRETTYITUP AS (
SELECT MAIN.STORENBR, DESCR, SUM(CQOH) AS CQOH, SUM(CETC) AS CETC,
SUM(CETR) AS CETR, SUM(PQOH) AS PQOH, SUM(PETC) AS PETC, SUM(PETR) AS PETR
FROM MAIN LEFT OUTER JOIN ATTRIB ON MAIN.StoreNbr = ATTRIB.STORENBR
GROUP BY MAIN.STORENBR, DESCR)
SELECT STORENBR, DESCR, PQOH, CQOH, (CQOH - PQOH) AS QCHANGE, PETC, CETC
, (CETC - PETC) AS CCHANGE, CETR
FROM PRETTYITUP ORDER BY 1
*/
,PRETTYITUP AS (
SELECT MAIN.STORENBR
--, DESCR
, SUM(CQOH) AS CQOH, SUM(CETC) AS CETC,
SUM(CETR) AS CETR, SUM(PQOH) AS PQOH, SUM(PETC) AS PETC, SUM(PETR) AS PETR
FROM MAIN --LEFT OUTER JOIN ATTRIB ON MAIN.StoreNbr = ATTRIB.STORENBR
GROUP BY MAIN.STORENBR
--, DESCR
)
SELECT STORENBR
--, DESCR
, PQOH, CQOH, (CQOH - PQOH) AS QCHANGE, PETC, CETC, (CETC - PETC) AS CCHANGE, CETR
FROM PRETTYITUP ORDER BY 1
Return 0
ASKER
Unfortunately, it is still running with no resulting rows as of thre minutes...so I'm not certain this is the issue. However, I will review the article in the link you sent me!
- Flynn
- Flynn
ASKER
Ok, I'm now certain that it *IS* a case of parameter sniffing. I just went into the code, commented out the declaration statements for the input parameters, and changed the private variables within the SQL to literal strings. It ran in under a minute.
However, I am still unable to get it working with the common workaround of declaring the parameters then using SET to assign their value to a local private variable, as jason had suggested.
Any thoughts ? -Flynn
However, I am still unable to get it working with the common workaround of declaring the parameters then using SET to assign their value to a local private variable, as jason had suggested.
Any thoughts ? -Flynn
ASKER
Also, I am using 2005, so using an OPTION for OPTIMIZER UNKNOWN won't work here :(
- Flynn
- Flynn
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
USE [StoreInventory]
GO
/****** Object: StoredProcedure [dbo].[stp_Crystal_EndingI nventoryTo tals_AllSt ores_FGK] Script Date: 03/01/2011 08:18:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ========================== ========== =========
-- Author: Flynn Kinkade
-- Create date: 02/28/2011
-- Description: Stored procedure to drive an
-- exception report for the current report titled
-- SPI Ending Inventory Store Totals.
-- Code takes 45-55 seconds to run.
-- ========================== ========== =========
--CREATE PROCEDURE [dbo].[stp_Crystal_EndingI nventoryTo tals_AllSt ores_FGK]
ALTER PROCEDURE [dbo].[stp_Crystal_EndingI nventoryTo tals_AllSt ores_FGK]
@InventoryDateParam_IN smalldatetime = null
,@IncludeNullDept_IN bit = 0
AS
DECLARE
@InventoryDateParam smalldatetime,
@IncludeNullDept bit,
@YESTERDAY smalldatetime ,
@RTNCODE char
SET @InventoryDateParam = @InventoryDateParam_IN
SET @IncludeNullDept = @IncludeNullDept_IN
If @RtnCode <> 0
Begin
Print 'Return code ' + convert(varchar(12), @RtnCode) + ' received from stp_RetrieveActiveStoreAtt ributes_Ad Book.'
Return 5
End
Select @Yesterday = Dateadd(d, -1, @InventoryDateParam)
/*CREATING TABLE tblStoreAttributes */
Create table #tblStoreAttributes (
StoreNbr smallint,
[Address] varchar(50),
City varchar(50),
[State] char(2),
PostalCode char(10),
County char(30),
CompanyStoreFlag bit,
WPLAreaName varchar(50)
)
Insert Into #tblStoreAttributes
Execute @RtnCode = stp_RetrieveActiveStoreAtt ributes_Ad Book
/* FINISHED CREATING TABLE tblStoreAttributes */
/* CREATING TABLE GTIN */
CREATE TABLE #GTIN
(
GTINCode VARCHAR(50),
STORENBR VARCHAR(50)
)
CREATE NONCLUSTERED INDEX IX_GTIN_StoreNbr ON #GTIN (StoreNbr)
INSERT #GTIN
SELECT DISTINCT I.GTINCode, V.StoreConfiguration_Store Nbr as StoreNbr
FROM [Control].SBTVendors V WITH (NOLOCK)
INNER JOIN Inventory.ItemAttributes I WITH (NOLOCK)
ON I.VendorNbr = V.VendorNbr
AND I.WhseCode = 0
GROUP BY I.GTINCode, V.StoreConfiguration_Store Nbr
UNION
SELECT DISTINCT I.GTINCode, S.StoreNbr
FROM [Control].ExclusionVendors E WITH (NOLOCK)
INNER JOIN Inventory.ItemAttributes I WITH (NOLOCK)
ON I.VendorNbr = E.VendorNbr
,[Control].StoreConfigurat ion S
UNION
SELECT GTINCode, S.StoreNbr
FROM [Control].ExclusionGTINs
,[Control].StoreConfigurat ion S
/*FINISHED CREATING TABLE GTIN */
/*CREATING TABLE DATES */
CREATE TABLE #DATES
(
STORENBR VARCHAR(50),
INVENTORYDATE SMALLDATETIME
)
CREATE NONCLUSTERED INDEX IX_DATES_StoreNbr ON #DATES (StoreNbr)
INSERT #DATES
SELECT DISTINCT HI.StoreConfiguration_Stor eNbr AS StoreNbr, HI.InventoryDate
FROM Inventory.HistoricalInvent ory as HI with (nolock)
WHERE HI.InventoryDate = @Yesterday
UNION ALL
SELECT DISTINCT HI.StoreConfiguration_Stor eNbr AS StoreNbr, HI.InventoryDate
FROM Inventory.HistoricalInvent ory as HI with (nolock)
WHERE HI.InventoryDate = @InventoryDateParam
/* FINISHED CREATING TABLE DATES */
/* Create Table HI_SUBSET */
CREATE TABLE #HI_SUBSET
( StoreNbr VARCHAR(50)
,DESCR VARCHAR(50)
,CQOH numeric
,CETC decimal
,CETR decimal
,PQOH numeric
,PETC decimal
,PETR decimal)
INSERT #HI_SUBSET
SELECT HI.StoreConfiguration_Stor eNbr as StoreNbr,
SA.City+','+SA.[State] as DESCR,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryD ateParam)
THEN Sum(HI.BalanceOnHand) ELSE 0 END) as CQOH,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryD ateParam)
THEN ROUND(Sum(HI.BalanceOnHand * Cast(HI.Cost as money)),2) ELSE 0 END) as CETC,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryD ateParam)
THEN ROUND(Sum(HI.BalanceOnHand * Cast(HI.Retail as money)),2) ELSE 0 END) as CETR,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryD ateParam)
THEN Sum(HI.BalanceOnHand) ELSE 0 END) as PQOH,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryD ateParam)
THEN ROUND(Sum(HI.BalanceOnHand * Cast(HI.Cost as money)),2) ELSE 0 END) as PETC,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryD ateParam)
THEN ROUND(Sum(HI.BalanceOnHand * Cast(HI.Retail as money)),2) ELSE 0 END) AS PETR
FROM Inventory.HistoricalInvent ory as HI with (nolock)
LEFT OUTER JOIN #tblStoreAttributes as SA
ON HI.StoreConfiguration_Stor eNbr = SA.StoreNbr
LEFT OUTER JOIN #GTIN X
ON X.StoreNbr = HI.StoreConfiguration_Stor eNbr
AND X.GTINCode = HI.GTINCode
, #DATES Z
WHERE HI.SourceFlag = 'U'
AND ((@IncludeNullDept = 1 AND HI.Department IN ('0','6','H') OR HI.Department IS NULL)
OR (@IncludeNullDept = 0 AND HI.Department IN ('0','6','H')))
AND HI.Category NOT IN (620,621)
AND X.GTINCode IS NULL
AND HI.StoreConfiguration_Stor eNbr = Z.STORENBR
AND HI.InventoryDate = Z.InventoryDate
GROUP BY HI.StoreConfiguration_Stor eNbr,
HI.InventoryDate,
SA.City+','+SA.[State]
ORDER BY HI.StoreConfiguration_Stor eNbr,3
/* Finished creating table HI_SUBSET */
/* Run SQL for report */
SELECT A.STORENBR,A.DESCR,B.PQOH, A.CQOH,(A. CQOH - B.PQOH) AS QOH_DIFF
,B.PETC,A.CETC, (A.CETC - B.PETC) AS ETC_DIFF,A.CETR
FROM #HI_SUBSET A, #HI_SUBSET B
WHERE A.STORENBR = B.STORENBR
AND A.CQOH > 0
AND B.PQOH > 0
/* Finished running SQL for report */
/*Cleanup*/
DROP TABLE #GTIN
DROP TABLE #DATES
DROP TABLE #HI_SUBSET
DROP TABLE #tblStoreAttributes
/*End Cleanup*/
Return 0
GO
/****** Object: StoredProcedure [dbo].[stp_Crystal_EndingI
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ==========================
-- Author: Flynn Kinkade
-- Create date: 02/28/2011
-- Description: Stored procedure to drive an
-- exception report for the current report titled
-- SPI Ending Inventory Store Totals.
-- Code takes 45-55 seconds to run.
-- ==========================
--CREATE PROCEDURE [dbo].[stp_Crystal_EndingI
ALTER PROCEDURE [dbo].[stp_Crystal_EndingI
@InventoryDateParam_IN smalldatetime = null
,@IncludeNullDept_IN bit = 0
AS
DECLARE
@InventoryDateParam smalldatetime,
@IncludeNullDept bit,
@YESTERDAY smalldatetime ,
@RTNCODE char
SET @InventoryDateParam = @InventoryDateParam_IN
SET @IncludeNullDept = @IncludeNullDept_IN
If @RtnCode <> 0
Begin
Print 'Return code ' + convert(varchar(12), @RtnCode) + ' received from stp_RetrieveActiveStoreAtt
Return 5
End
Select @Yesterday = Dateadd(d, -1, @InventoryDateParam)
/*CREATING TABLE tblStoreAttributes */
Create table #tblStoreAttributes (
StoreNbr smallint,
[Address] varchar(50),
City varchar(50),
[State] char(2),
PostalCode char(10),
County char(30),
CompanyStoreFlag bit,
WPLAreaName varchar(50)
)
Insert Into #tblStoreAttributes
Execute @RtnCode = stp_RetrieveActiveStoreAtt
/* FINISHED CREATING TABLE tblStoreAttributes */
/* CREATING TABLE GTIN */
CREATE TABLE #GTIN
(
GTINCode VARCHAR(50),
STORENBR VARCHAR(50)
)
CREATE NONCLUSTERED INDEX IX_GTIN_StoreNbr ON #GTIN (StoreNbr)
INSERT #GTIN
SELECT DISTINCT I.GTINCode, V.StoreConfiguration_Store
FROM [Control].SBTVendors V WITH (NOLOCK)
INNER JOIN Inventory.ItemAttributes I WITH (NOLOCK)
ON I.VendorNbr = V.VendorNbr
AND I.WhseCode = 0
GROUP BY I.GTINCode, V.StoreConfiguration_Store
UNION
SELECT DISTINCT I.GTINCode, S.StoreNbr
FROM [Control].ExclusionVendors
INNER JOIN Inventory.ItemAttributes I WITH (NOLOCK)
ON I.VendorNbr = E.VendorNbr
,[Control].StoreConfigurat
UNION
SELECT GTINCode, S.StoreNbr
FROM [Control].ExclusionGTINs
,[Control].StoreConfigurat
/*FINISHED CREATING TABLE GTIN */
/*CREATING TABLE DATES */
CREATE TABLE #DATES
(
STORENBR VARCHAR(50),
INVENTORYDATE SMALLDATETIME
)
CREATE NONCLUSTERED INDEX IX_DATES_StoreNbr ON #DATES (StoreNbr)
INSERT #DATES
SELECT DISTINCT HI.StoreConfiguration_Stor
FROM Inventory.HistoricalInvent
WHERE HI.InventoryDate = @Yesterday
UNION ALL
SELECT DISTINCT HI.StoreConfiguration_Stor
FROM Inventory.HistoricalInvent
WHERE HI.InventoryDate = @InventoryDateParam
/* FINISHED CREATING TABLE DATES */
/* Create Table HI_SUBSET */
CREATE TABLE #HI_SUBSET
( StoreNbr VARCHAR(50)
,DESCR VARCHAR(50)
,CQOH numeric
,CETC decimal
,CETR decimal
,PQOH numeric
,PETC decimal
,PETR decimal)
INSERT #HI_SUBSET
SELECT HI.StoreConfiguration_Stor
SA.City+','+SA.[State] as DESCR,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryD
THEN Sum(HI.BalanceOnHand) ELSE 0 END) as CQOH,
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryD
THEN ROUND(Sum(HI.BalanceOnHand
(CASE WHEN HI.InventoryDate <> DATEADD(DAY,-1,@InventoryD
THEN ROUND(Sum(HI.BalanceOnHand
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryD
THEN Sum(HI.BalanceOnHand) ELSE 0 END) as PQOH,
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryD
THEN ROUND(Sum(HI.BalanceOnHand
(CASE WHEN HI.InventoryDate = DATEADD(DAY,-1,@InventoryD
THEN ROUND(Sum(HI.BalanceOnHand
FROM Inventory.HistoricalInvent
LEFT OUTER JOIN #tblStoreAttributes as SA
ON HI.StoreConfiguration_Stor
LEFT OUTER JOIN #GTIN X
ON X.StoreNbr = HI.StoreConfiguration_Stor
AND X.GTINCode = HI.GTINCode
, #DATES Z
WHERE HI.SourceFlag = 'U'
AND ((@IncludeNullDept = 1 AND HI.Department IN ('0','6','H') OR HI.Department IS NULL)
OR (@IncludeNullDept = 0 AND HI.Department IN ('0','6','H')))
AND HI.Category NOT IN (620,621)
AND X.GTINCode IS NULL
AND HI.StoreConfiguration_Stor
AND HI.InventoryDate = Z.InventoryDate
GROUP BY HI.StoreConfiguration_Stor
HI.InventoryDate,
SA.City+','+SA.[State]
ORDER BY HI.StoreConfiguration_Stor
/* Finished creating table HI_SUBSET */
/* Run SQL for report */
SELECT A.STORENBR,A.DESCR,B.PQOH,
,B.PETC,A.CETC, (A.CETC - B.PETC) AS ETC_DIFF,A.CETR
FROM #HI_SUBSET A, #HI_SUBSET B
WHERE A.STORENBR = B.STORENBR
AND A.CQOH > 0
AND B.PQOH > 0
/* Finished running SQL for report */
/*Cleanup*/
DROP TABLE #GTIN
DROP TABLE #DATES
DROP TABLE #HI_SUBSET
DROP TABLE #tblStoreAttributes
/*End Cleanup*/
Return 0
Um isn't that what I said and posted? I think points should be assigned.
ASKER
Southmod, please award the expert his points. Chalk it up to lack of understanding of the system on my part.
http://www.databasejournal.com/features/mssql/article.php/3841271/T-SQL-Best-Practices--Parameter-Sniffing.htm
You can try this:
Open in new window