USE AdventureWorks2012
Go
CREATE PROCEDURE usp_SearchOrderDetailByDate
(
@FromDate date,
@ToDate date
)
AS
BEGIN
SET NOCOUNT ON;
SELECT p.Name,sod.OrderQty,sod.LineTotal,sod.CarrierTrackingNumber,sod.UnitPrice,sod.UnitPriceDiscount
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON p.ProductID = sod.ProductID
WHERE sod.ModifiedDate >= @FromDate AND sod.ModifiedDate <=@ToDate
SET NOCOUNT OFF;
END
CREATE NONCLUSTERED INDEX [id_ModifiedDate] ON [Sales].[SalesOrderDetail]
(
[ModifiedDate] ASC
)
INCLUDE ( [CarrierTrackingNumber],
[OrderQty],
[UnitPrice],
[UnitPriceDiscount],
[LineTotal],
[ProductID])
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SET STATISTICS PROFILE ON;
EXEC usp_SearchOrderDetailByDate '2005-07-01','2005-07-31';
SET STATISTICS PROFILE OFF;
SET STATISTICS PROFILE ON;
EXEC usp_SearchOrderDetailByDate '2005-07-01','2007-12-31'
SET STATISTICS PROFILE OFF;
SET STATISTICS PROFILE ON;
EXEC usp_SearchOrderDetailByDate '2005-07-01','2007-12-31' WITH RECOMPILE
SET STATISTICS PROFILE OFF;
Alter your store procedured to add the option WITH RECOMPILE
USE AdventureWorks2012
Go
ALTER PROCEDURE usp_SearchOrderDetailByDate
(
@FromDate date,
@ToDate date
)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
SELECT p.Name,sod.OrderQty,sod.LineTotal,sod.CarrierTrackingNumber,sod.UnitPrice,sod.UnitPriceDiscount
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON p.ProductID = sod.ProductID
WHERE sod.ModifiedDate >= @FromDate AND sod.ModifiedDate <=@ToDate
SET NOCOUNT OFF;
END
Both ways, SQL Engine is forced to re-compile your stored procedure before executing, and the result of the Execution Plan is better.
USE AdventureWorks2012
Go
ALTER PROCEDURE usp_SearchOrderDetailByDate
(
@FromDate date,
@ToDate date
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @StartDate date,@EndDate date
SELECT @StartDate = @FromDate,@EndDate = @ToDate
SELECT p.Name,sod.OrderQty,sod.LineTotal,sod.CarrierTrackingNumber,sod.UnitPrice,sod.UnitPriceDiscount
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON p.ProductID = sod.ProductID
WHERE sod.ModifiedDate >= @StartDate AND sod.ModifiedDate <=@EndDate
SET NOCOUNT OFF;
END
If we excute it again, the Estimated Rows is 10,918 -- not good, but better than the previous excution plan.
USE AdventureWorks2012
Go
ALTER PROCEDURE usp_SearchOrderDetailByDate
(
@FromDate date,
@ToDate date
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @StartDate date,@EndDate date
SELECT @StartDate = @FromDate,@EndDate = @ToDate
SELECT p.Name,sod.OrderQty,sod.LineTotal,sod.CarrierTrackingNumber,sod.UnitPrice,sod.UnitPriceDiscount
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON p.ProductID = sod.ProductID
WHERE sod.ModifiedDate >= @StartDate AND sod.ModifiedDate <=@EndDate
OPTION(RECOMPILE)
SET NOCOUNT OFF;
END
I perfer this way to 3.1 WITH RECOMPILE because it does not require re-compiling all objects in your stored procedure.
USE AdventureWorks2012
Go
ALTER PROCEDURE usp_SearchOrderDetailByDate
(
@FromDate date,
@ToDate date
)
AS
BEGIN
SET NOCOUNT ON;
SELECT p.Name,sod.OrderQty,sod.LineTotal,sod.CarrierTrackingNumber,sod.UnitPrice,sod.UnitPriceDiscount
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON p.ProductID = sod.ProductID
WHERE sod.ModifiedDate >= @FromDate AND sod.ModifiedDate <=@ToDate
OPTION(OPTIMIZE FOR (@FromDate = '2005-07-01',@ToDate='2007-12-31') )
SET NOCOUNT OFF;
END
The Execution Plan will always be based on the set of paramters @FromDate = '2005-07-01' and @ToDate='2007-12-31'
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
SET STATISTICS PROFILE ON;
EXEC usp_SearchOrderDetailByDate '2005-07-01','2005-07-31';
SET STATISTICS PROFILE OFF;
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)