我想优化这个SP,任何人都知道我该怎么做?提前谢谢。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Members] (
@StartTime datetime = null
, @EndTime datetime = null
, @CustomerEmail nvarchar(255) = null
, @CustomerName nvarchar(255) = null
, @ShippingMethod nvarchar(255) = null
, @MemberOrderStatusPending int = null
, @MemberOrderProcessing int = null
, @MemberOrderComplete int = null
, @MemberOrderStatusCancelled int = null
, @MemberOrderStatusCancelledDiscontinued int = null
, @MemberOrderStatusCancelledCustomerRequest int = null
, @MemberOrderStatusCancelledPendingNeverPaid int = null
)
AS
BEGIN
SET NOCOUNT ON
SELECT DISTINCT o.OrderID
, o.OrderTotal
, o.BillingFirstName + ' ' + o.BillingLastName AS CustomerName
, o.CreatedOn AS CreatedOn
FROM Order o
WHERE ( o.CreatedOn > @StartTime OR @StartTime IS NULL )
AND ( o.CreatedOn < @EndTime OR @EndTime IS NULL )
AND ( o.ShippingEmail = @CustomerEmail OR @CustomerEmail IS NULL)
AND ( o.BillingFirstName + ' ' + o.BillingLastName = @CustomerName OR @CustomerName IS NULL )
AND ( o.ShippingFirstName + ' ' + o.ShippingLastName = @CustomerName OR @CustomerName IS NULL )
AND ( o.ShippingMethod = @ShippingMethod OR @ShippingMethod IS NULL )
AND ( o.OrderStatusID = @MemberOrderProcessing
OR o.OrderStatusID = @MemberOrderProcessing
OR o.OrderStatusID = @MemberOrderComplete
OR o.OrderStatusID = @MemberOrderStatusCancelled
OR o.OrderStatusID = @MemberOrderStatusCancelledDiscontinued
OR o.OrderStatusID = @MemberOrderStatusCancelledCustomerRequest
OR o.OrderStatusID = @MemberOrderStatusCancelledPendingNeverPaid
OR @MemberOrderProcessing IS NULL
OR @MemberOrderProcessing IS NULL
OR @MemberOrderComplete IS NULL
OR @MemberOrderStatusCancelled IS NULL
OR @MemberOrderStatusCancelledDiscontinued IS NULL
OR @MemberOrderStatusCancelledCustomerRequest IS NULL
OR @MemberOrderStatusCancelledPendingNeverPaid IS NULL )
ORDER BY
o.OrderID
END
答案 0 :(得分:1)
当你有那么多OR条件时,性能肯定会受到影响(更不用说这会导致参数嗅探)。我强烈建议在这里使用Dynamic SQL。像这样的东西,
DECLARE @query VARCHAR(MAX)
SET @query =
'SELECT DISTINCT o.OrderID, o.OrderTotal, o.BillingFirstName + ' ' + o.BillingLastName AS CustomerName, o.CreatedOn AS CreatedOn FROM Order o
WHERE 1=1 '
IF @StartTime IS NOT NULL
SET @query = @query + ' AND o.CreatedOn > @StartTime'
IF @EndTime IS NOT NULL
SET @query = @query + ' AND o.CreatedOn < @EndTime'
IF @CustomerEmail IS NOT NULL
SET @query = @query + ' AND o.ShippingEmail = @CustomerEmail'
......
......
exec sp_executesql @query,
N'@StartTime DATETIME,
@EndTime DATETIME,
...<other param definitions>',
@StartTime,
@EndTime,
.. <other param values>
答案 1 :(得分:0)
如果OrderStatusID是位字段,则可能会有以下操作
SELECT DISTINCT o.OrderID
, o.OrderTotal
, o.BillingFirstName + ' ' + o.BillingLastName AS CustomerName
, o.CreatedOn AS CreatedOn
FROM Order o
WHERE ( o.CreatedOn > COALESCE( @StartTime, '01-01-1899' ))
AND ( o.CreatedOn < COALESCE( @EndTime, '01-01-2099' ))
AND ( o.BillingFirstName + ' ' + o.BillingLastName = COALESCE( @CustomerName, o.BillingFirstName + ' ' + o.BillingLastName ))
AND ( o.ShippingFirstName + ' ' + o.ShippingLastName = COALESCE (@CustomerName, o.ShippingFirstName + ' ' + o.ShippingLastName ))
AND ( o.ShippingEmail = COALESCE(@CustomerEmail, o.ShippingEmail )
AND ( o.ShippingMethod = COALESCE ( @ShippingMethod, o.ShippingMethod )
AND ( o.OrderStatusID & (
COALESCE ( @MemberOrderProcessing, 1 )
| COALESCE ( @MemberOrderComplete, 2 )
| COALESCE ( @MemberOrderStatusCancelled , 4 )
| COALESCE ( @MemberOrderStatusCancelledDiscontinued , 8 )
| COALESCE ( @MemberOrderStatusCancelledCustomerRequest , 16 )
| COALESCE ( @MemberOrderStatusCancelledPendingNeverPaid , 32 )
) >= 1
)
ORDER BY
o.OrderID
答案 2 :(得分:0)
动态搜索条件的最佳来源:
Dynamic Search Conditions in T-SQL by Erland Sommarskog
如果可以使用索引,对于如何执行此操作会有很多微妙的含义。如果您使用的是SQL Server 2008的正确版本,则只需将OPTION (RECOMPILE)
添加到查询中,并将运行时的局部变量值用于优化。
考虑到这一点,OPTION (RECOMPILE)
将采用此代码(其中没有索引可用于此OR
的混乱):
WHERE
(@search1 IS NULL or Column1=@Search1)
AND (@search2 IS NULL or Column2=@Search2)
AND (@search3 IS NULL or Column3=@Search3)
并在运行时优化它(假设只有@ Search2传入了一个值):
WHERE
Column2=@Search2
并且可以使用索引(如果在Column2上定义了一个索引)
如果您没有使用SQL Server 2008所需的版本,则链接文章提供了许多方法,每种方法都有利弊。例如,如果您可以确定搜索列的最小和最大可能范围,并且搜索列为NOT NULL,那么您可以做得比(@Search IS NULL或Col = @ Search)更好,{{3} }。但是你应该阅读整篇文章,有很多变化取决于你的情况,你真的需要学习多种方法以及何时使用它们。