SQL 服务器 - DATEDIFF 函数耗时太长
SQL Server - DATEDIFF Function taking too long
我做了一些广泛的研究,得出的结论是 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();
在下面的查询中,我想获取从处理时间到今天的 1 周内的所有集合的 COUNT 个。
有没有人可以帮我去掉 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
提前致谢。
它不仅仅是 DATEDIFF,列上的任何函数都会导致查询对基础 table/index
进行扫描
DATEDIFF(week, [Limit1].[ProcessDate], SysDateTime())) <=1
以上逻辑是取上周数据?您也可以在不将函数放在 ProcessDate 列周围的情况下编写上面的代码。
[Limit1].[ProcessDate] > SysDateTime()-7
这是您的查询:
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)
上建立索引。
我做了一些广泛的研究,得出的结论是 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();
在下面的查询中,我想获取从处理时间到今天的 1 周内的所有集合的 COUNT 个。
有没有人可以帮我去掉 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
提前致谢。
它不仅仅是 DATEDIFF,列上的任何函数都会导致查询对基础 table/index
进行扫描DATEDIFF(week, [Limit1].[ProcessDate], SysDateTime())) <=1
以上逻辑是取上周数据?您也可以在不将函数放在 ProcessDate 列周围的情况下编写上面的代码。
[Limit1].[ProcessDate] > SysDateTime()-7
这是您的查询:
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)
上建立索引。