SQL Server - DATEDIFF函数耗时太长

时间:2016-05-10 23:15:17

标签: c# sql sql-server entity-framework linq-to-sql

我做了一些广泛的研究,我得出结论,DATEDIFF函数使我的查询运行得很慢。

以下是Entity Framework生成的查询,希望它看起来很可读。

这是生成T-SQL的Linq:

model.NewTotal1Week = ( from sdo in context.SubscriberDebitOrders
                        where
                        (
                           sdo.CampaignId == campaignId &&
                           ( sdo.Status == ( Int32 ) DebitOrderStatus.New_Faulty ) &&
                           ( SqlFunctions.DateDiff( "week", sdo.Collections.FirstOrDefault( c => c.TxnStatus == "U" ).ProcessDate, DateTime.Now ) <= 1 )
                        )
                        select sdo ).Count();

在下面的查询中,我想获得所有收藏品的COUNT个,这些收藏品从处理时间到今天的日期都在1周内。

有没有人可以帮我摆脱DATEDIFF功能?我在网上看过例子,但我无法适应我的情景,请原谅我,我不是很天才。

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM  [dbo].[SubscriberDebitOrder] AS [Extent1]
        OUTER APPLY  (SELECT TOP (1) 
            [Extent2].[ProcessDate] AS [ProcessDate]
            FROM [dbo].[Collections] AS [Extent2]
            WHERE ([Extent1].[Id] = [Extent2].[DebitOrderId]) AND (''U'' = [Extent2].[TxnStatus]) ) AS [Limit1]
        WHERE ([Extent1].[CampaignId] = @p__linq__0) AND (3 = [Extent1].[Status]) AND ((DATEDIFF(week, [Limit1].[ProcessDate], SysDateTime())) <= 1)
    )  AS [GroupBy1]',N'@p__linq__0 int',@p__linq__0=3
go

提前致谢。

2 个答案:

答案 0 :(得分:4)

它不仅仅是DATEDIFF,列上的任何函数都会导致查询在基础表/索引上执行SCAN

DATEDIFF(week, [Limit1].[ProcessDate], SysDateTime())) <=1

以上逻辑是否在上周获取数据?您也可以在上面编写,而不必在ProcessDate Column周围添加函数。

[Limit1].[ProcessDate] > SysDateTime()-7

答案 1 :(得分:3)

这是您的查询:

SELECT GroupBy1.A1 AS C1
FROM (SELECT COUNT(1) AS[A1
      FROM dbo.SubscriberDebitOrder AS Extent1 OUTER APPLY
           (SELECT TOP (1) Extent2.ProcessDate 
            FROM [dbo].Collections Extent2
            WHERE (Extent1.Id = Extent2.DebitOrderId AND
                   'U' = Extent2.TxnStatus
           ) AS [Limit1]
      WHERE (Extent1.CampaignId = @p__linq__0) AND (3 = Extent1.Status) AND 
            (DATEDIFF(week, Limit1.ProcessDate, SysDateTime()) <= 1)
     )  GroupBy1;

如其他地方所述,您应该更改日期逻辑并删除外部查询:

      SELECT COUNT(1) AS A1
      FROM dbo.SubscriberDebitOrder AS Extent1 OUTER APPLY
           (SELECT TOP (1) Extent2.ProcessDate 
            FROM [dbo].Collections Extent2
            WHERE (Extent1.Id = Extent2.DebitOrderId AND
                   'U' = Extent2.TxnStatus
           ) AS limit1
      WHERE (Extent1.CampaignId = @p__linq__0) AND (3 = Extent1.Status) AND 
            Limit1.ProcessDate <= DATEADD(-1, week, GETDATE())

非常重要的说明:这与您的查询不完全相同。您的原始查询计算了两个日期之间的周边界数。这取决于datefirst,但它通常是周六或周日晚上的数量。

根据您的描述,上述内容更为正确。

接下来,您需要Collections(DebitOrderId, TxnStatus, ProcessDate)SubscriberDebitOrder(CampaignId, Status)上的索引。

相关问题