T-SQL - WHERE条件性能

时间:2014-01-30 19:30:37

标签: sql-server tsql reporting-services

我有像这样声明的变量

DECLARE @Customer_No VARCHAR(MAX)
SET @Customer_No = 'Z110073574;Z110027464;Z110229752;Z110274156;Z110170566;Z110102837;Z110074199'

查询包含条件

WHERE ((@Customer_No = '') OR ([Customer No_] IN (SELECT [No_] FROM Customer)))

如果变量@Customer_No可以包含空值(''),则应跳过过滤。如果变量包含以分号分隔的客户,则将字符串解析为表Customer,并按Customer表中的值过滤查询。

查询需要15分钟才能运行。如果我只使用第二个条件,则需要大约50秒。

WHERE [Customer No_] IN (SELECT [No_] FROM Customer)

我不明白。这怎么可能?有解决方案吗说明? 谢谢。

编辑:查询

SELECT  DET.[Cust_ Ledger Entry No_]
      , DET.[Amount]
      , DET.[Entry Type]
      , CLE.[Document No_]
FROM [dbo].[Company$Cust_ Ledger Entry] CLE
LEFT JOIN [dbo].[Company$Detailed Cust_ Ledg_ Entry] DET ON CLE.[Entry No_] = DET.[Cust_ Ledger Entry No_]
WHERE ((@Customer_No = '') OR (DET.[Customer No_] IN (SELECT [No_] FROM Customer)))
  AND (DET.[Entry Type] = 1 OR DET.[Entry Type] = 2)
  AND (CLE.[Due Date] >= @FromDueDate AND CLE.[Due Date] <= @ToDueDate)
  AND CLE.[Posting Date] <= @ToDate

4 个答案:

答案 0 :(得分:1)

我认为您可以简单地查询而不会损失以下内容的完整性。就像亚伦说的那样,你可以发布一个查询计划吗?

SELECT  
    DET.[Cust_ Ledger Entry No_],
    DET.[Amount],
    DET.[Entry Type],
    CLE.[Document No_]
FROM 
    [dbo].[Company$Cust_ Ledger Entry] CLE
LEFT JOIN 
    [dbo].[Company$Detailed Cust_ Ledg_ Entry] DET 
ON 
    CLE.[Entry No_] = DET.[Cust_ Ledger Entry No_]
WHERE 
   ( @FAS_No = '' OR DET.[Customer No_] IN (SELECT [No_] FROM Customer) )
   AND DET.[Entry Type] in (1, 2)
   AND CLE.[Due Date] >= @FromDueDate 
   AND CLE.[Due Date] <= @ToDueDate
   AND CLE.[Posting Date] <= @ToDate

答案 1 :(得分:0)

如果没有更多信息(表格结构,行数等),就很难找到确切的问题。但是,有一点可以肯定的是,在TSQL中使用OR会降低整体性能。如果有一种方法可以使用AND代替OR而不是建议使用AND。

你可以随时使用IF语句来检查变量是否为空。如果没有,则将SELECT与WHERE一起使用。如果它为空,则使用SELECT而不使用WHERE。

要检查的另一件事可能是您的索引。这可以加速一些事情。

答案 2 :(得分:0)

在哪里杀死左边的DET所以也可以加入
如果你将条件拉入连接,那么查询优化器似乎做得更好 我认为这为查询优化器提供了更好的机会

SELECT  DET.[Cust_ Ledger Entry No_]
      , DET.[Amount]
      , DET.[Entry Type]
      , CLE.[Document No_]
  FROM [dbo].[Company$Cust_ Ledger Entry] CLE
  JOIN [dbo].[Company$Detailed Cust_ Ledg_ Entry] DET 
    ON CLE.[Entry No_] = DET.[Cust_ Ledger Entry No_]
   AND ( DET.[Entry Type] IN (1,2) )
   AND ( CLE.[Due Date] >= @FromDueDate AND CLE.[Due Date] <= @ToDueDate )
   AND   CLE.[Posting Date] <= @ToDate
  JOIN Customer 
    ON @Customer_No = ''
    OR DET.[Customer No_] = Customer.[No_]

尝试提示
我将从INNER MERGE JOIN客户

开始

请将[NO_]声明为PK

答案 3 :(得分:0)

我认为您可以通过写入

来降低性能
  • 使用CTE - (SELECT [No_] FROM Customer)
  • 加入cte主表,这将为您提供性能