Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF查询计数时间比完整列表时间长几个数量级_C#_Sql_Entity Framework 6 - Fatal编程技术网

C# EF查询计数时间比完整列表时间长几个数量级

C# EF查询计数时间比完整列表时间长几个数量级,c#,sql,entity-framework-6,C#,Sql,Entity Framework 6,我在EF中有一个查询,它在两个集合之间执行交集并计算返回的行数。这不是一个非常复杂的查询,生成的SQL很简单 但是,使用EF执行此查询花费的时间太长 在SSMS(20ms)中运行此查询不需要时间,但当我通过EF运行它时,它需要大约800ms,即使底层SQL是相同的。这对我来说不是指数问题 我已经在SQL事件探查器和EF事件探查器中查看了生成的SQL,生成的SQL与预期的一样 如果我使用.SqlQuery通过EF运行查询文本,它也会执行 大约20毫秒后 执行顺序不是问题,无论我运行哪个顺序.Sq

我在EF中有一个查询,它在两个集合之间执行交集并计算返回的行数。这不是一个非常复杂的查询,生成的SQL很简单

但是,使用EF执行此查询花费的时间太长


  • 在SSMS(20ms)中运行此查询不需要时间,但当我通过EF运行它时,它需要大约800ms,即使底层SQL是相同的。这对我来说不是指数问题
  • 我已经在SQL事件探查器和EF事件探查器中查看了生成的SQL,生成的SQL与预期的一样
  • 如果我使用
    .SqlQuery
    通过EF运行查询文本,它也会执行 大约20毫秒后
  • 执行顺序不是问题,无论我运行哪个顺序
    .SqlQuery
    ,中的实际EF查询都会重现EF perf问题(即它似乎不是SQL查询缓存问题)
  • 如果我从查询中删除计数(例如使用
    .ToArray().count()
    ),它将在大约20毫秒内执行(但是,如果交叉点足够大,这实际上不是一个可行的解决方案)
  • 查询计划似乎是合理的,它全部在索引中,并且在EF之外表现良好
是否有人知道可能导致这种行为的原因,或者我可以尝试诊断的其他原因?

编辑:

我对查询做了更多的尝试,并注意到生成的SQL在EF Profiler和SQL Profiler中有点不同,EF Profiler通过从查询中删除
exec sp_executesql
和参数化来稍微整理它。当我在基于代码的查询中复制这一点时,我能够重现EF查询的糟糕性能(这很好)。然而,在任何使用SSMS的情况下,它仍然运行得很快

我的假设是,参数嗅探的问题被隔离到同一查询的第一次执行。然而,进一步的阅读证明这一假设是无效的。我可以通过在
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]

“在SSMS(20ms)中运行此查询不需要时间,但当我通过 EF即使基础SQL相同,也需要大约800毫秒的时间。 在我看来,这个问题不是指数。”

这通常是参数嗅探的症状。SSMS在连接上设置选项,使查询在执行时重新编译(因此SSMS的执行时间总是很短)


规范参考:

“这个查询在SSMS(20ms)中运行不需要时间,但是当我通过EF运行它时,它需要大约800ms,即使底层SQL是相同的。这对我来说,问题不是索引。”-通常是参数嗅探的症状…@MitchWheat我认为这可能有点奇怪。为了隔离它,我尝试通过手动执行SQL两次来启动系统,一次使用原始SQL命令,然后使用EF查询。我的理解是,参数嗅探应该使第一个变慢。然而,无论我以何种方式订购,EF总是慢的。还有什么我应该试试的吗?@MitchWheat我做了更多的研究,你完全正确,这是由参数嗅探引起的。如果你发布,我会接受(因为这是一个为什么的问题)。谢谢您的帮助。@LukeMcGregor我想知道使用contains pr any而不是intersect重新格式化查询是否有助于提高性能,并避免参数嗅探altogether@TheVedge事实上,它很容易受到完全相同的问题的影响,但是这种变化确实让我减少了一点查询时间,因为(我没有意识到)所以谢谢:)