我在EF中有一个查询,它正在执行两个集合之间的交集并计算返回的行数。它不是一个非常复杂的查询,生成的SQL很简单。
然而,使用EF执行此查询的时间太长了。
.SqlQuery<int>
通过EF运行查询文本,它也会执行
在大约20ms。.SqlQuery<int>
和实际EF查询重现EF perf问题(即它似乎不是SQL查询缓存问题)的问题。.ToArray().Count()
),它会在大约20ms内执行(但如果交叉点足够大,这不是一个可行的解决方案)有没有人知道任何可能导致这种行为的事情,或者我可以尝试诊断它的任何其他事情?
修改
我更多地使用查询并注意到生成的SQL在EF Profiler中与SQL Profiler略有不同,EF Profiler通过从查询中删除exec sp_executesql
和参数化来稍微整理一下。当我在基于代码的查询中复制它时,我能够重现EF查询的不良性能(这很好)。然而,在使用SSMS的任何情况下它仍然运行得很快。
我的假设是参数嗅探的问题被隔离到第一次执行相同的查询。然而,进一步阅读证明这一假设无效。我能够通过将OPTION (RECOMPILE)
添加到exec sp_executesql
字符串的末尾来证明这是由参数嗅探(如@MitchWheat建议)引起的。这使它在合理的时间范围内执行。
我还不确定如何用EF解决这个问题,但至少我知道它是什么。
EF查询
var query = (from c in ctx.RuleCurrentMembershipCache
where c.RuleId == baseRule
where c.Direction == Direction.In
select c.Key)
.Distinct()
.Intersect((from c in ctx.RuleCurrentMembershipCache
where c.RuleId == ruleId
where c.Direction == Direction.In
select c.Key).Distinct());
query.ToArray().Count();//fast
query.Count();//slow
生成SQL
SELECT [GroupBy1].[A1] AS [C1]
FROM (
SELECT COUNT(1) AS [A1]
FROM (
SELECT [Distinct1].[Key] AS [Key]
FROM (
SELECT DISTINCT [Extent1].[Key] AS [Key]
FROM [RuleCurrentMembershipCache] AS [Extent1]
WHERE ([Extent1].[RuleId] = 'c0cdd83d-0cad-430d-bb6a-7abdbf115856' /* @p__linq__0 */)
AND (1 = CAST([Extent1].[Direction] AS int)
)
) AS [Distinct1]
INTERSECT
SELECT [Distinct2].[Key] AS [Key]
FROM (
SELECT DISTINCT [Extent2].[Key] AS [Key]
FROM [RuleCurrentMembershipCache] AS [Extent2]
WHERE ([Extent2].[RuleId] = '6d97cf92-8a57-4de2-8756-0abe6977eb7d' /* @p__linq__1 */)
AND (1 = CAST([Extent2].[Direction] AS int))
) AS [Distinct2]
) AS [Intersect1]
) AS [GroupBy1]
模式
CREATE TABLE [RuleCurrentMembershipCache](
[RuleId] [uniqueidentifier] NOT NULL,
[Key] [int] NOT NULL,
[Timestamp] [datetimeoffset](7) NOT NULL,
[Direction] [int] NOT NULL,
CONSTRAINT [PK_RuleCurrentMembershipCache] PRIMARY KEY CLUSTERED
(
[RuleId] ASC,
[Key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_RuleId] ON [RuleCurrentMembershipCache]
(
[RuleId] ASC
)
INCLUDE ( [Direction],
[Key]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
答案 0 :(得分:2)
“此查询没有时间在SSMS(20ms)中运行,但是当我通过它运行时 即使基础SQL相同,EF大约需要800毫秒。 这对我来说这个问题不是指数。“
这通常是参数嗅探的症状。 SSMS在连接上设置选项,这些选项在执行时会导致查询被重新编译(因此SSMS的执行时间总是很短)。