【发布时间】:2018-04-01 23:57:25
【问题描述】:
我有一个看起来非常简单的 LINQ 语句,但它生成的 SQL 对我来说没有意义,而且它的执行时间比我预期的要长得多。我只是想了解 LINQ 在做什么,以便弄清楚为什么它运行得这么慢。一条类似的 SQL 语句需要不到一秒的时间,但 LINQ 大约需要 20 秒。
代码如下:
// This line takes 20 seconds to return.
var alertEvents = GetFilteredAlertEvents(alert.AlertEvents, db).ToList<AlertEvent>();
private static IEnumerable<AlertEvent> GetFilteredAlertEvents(ICollection<AlertEvent> alertEvents, SlalomEREntities db)
{
Guid marketAlertReceiverGroupId = new Guid(ConfigurationManager.AppSettings["MarketAlertReceiverGroupId"]);
var subQuery = from ae in alertEvents
join tr in db.TargetResources on ae.ResourceId equals tr.ResourceID
join atr in db.AlertTargetResources on tr.ResourceID equals atr.TargetResourceID
where atr.AlertTargetID == marketAlertReceiverGroupId
select ae.AlertEventId;
return from alertEvent in alertEvents
where !subQuery.Contains(alertEvent.AlertEventId)
select alertEvent;
}
在 SSMS 中,子选择返回 3126 行没有where,只有 127 行有它。 SSMS 中的主要 select 返回 365 行,没有子选择。带有子选择的完整选择返回 238 行。没有很多数据。
使用 Visual Studio 的诊断工具,我看到 LINQ 生成了 14 条 SQL 语句。它们中的每一个都是一个简单的 SQL 选择,我没有看到任何连接,也没有看到 where 比较。这是我在诊断工具事件窗口中看到的示例 SQL 语句:
SELECT
[Extent1].[AlertTargetID] AS [AlertTargetID],
[Extent1].[TargetResourceID] AS [TargetResourceID],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[CreatedBy] AS [CreatedBy]
FROM [dbo].[AlertTargetResource] AS [Extent1]
还有 13 条类似的 SQL 语句。
这是我要复制的 SQL。
select *
from AlertEvent ae1
where ae1.AlertEventId not in
(select ae.AlertEventId
from AlertEvent ae
join TargetResource tr on ae.ResourceId = tr.ResourceID
join AlertTargetResource atr on atr.TargetResourceID = tr.ResourceID
where atr.AlertTargetID = '89bd4ea5-5d56-4b8a-81ba-5a9e5991ba64')
这是我的问题:
- 为什么 LINQ 对 14 个简单的选择而不是带有连接和位置的单个选择进行分类?
- 如何加快我认为很简单的代码?
【问题讨论】:
-
这可能是因为您在 .dbml 文件中将更新检查属性设置为始终。如果它是一个缓慢的查询,您可能需要将其删除或使用数据库视图以便将其缓存。
-
是的,这不是一个好方法。您需要组合这两个查询,因为第二个查询(
return语句中的那个)看起来必须执行多个查询。要么,要么使用ToList()将subquery转换为数据。 -
而
alert.AlertEvents也是数据库表,不是内存列表?
标签: c# performance tsql linq-to-sql