喵喔喔
当实体框架4是实际的时候,我写了这个答案。这个答案的目的不在于涉及琐碎的问题。.Any()VS.Count()性能测试。关键是要表明EF远非十全十美。新版本更好.。但是,如果您的代码部分速度慢,并且使用EF,则使用直接TSQL进行测试,并比较性能,而不是依赖于假设(即.Any()总是比.Count() > 0).虽然我同意大多数人投票通过的回答和评论-特别是在这一点上Any信号开发意图比Count() > 0-在SQLServer(EntityFramework4)上,计数按数量级计算得更快。下面是查询Any超时异常(在~200.000条记录上):con = db.Contacts.
Where(a => a.CompanyId == companyId && a.ContactStatusId <= (int) Const.ContactStatusEnum.Reactivated
&& !a.NewsletterLogs.Any(b => b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr)
).OrderBy(a => a.ContactId).
Skip(position - 1).
Take(1).FirstOrDefault();Count版本以毫秒为单位执行:con = db.Contacts.
Where(a => a.CompanyId == companyId && a.ContactStatusId <= (int) Const.ContactStatusEnum.Reactivated
&& a.NewsletterLogs.Count(b => b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr) == 0
).OrderBy(a => a.ContactId).
Skip(position - 1).
Take(1).FirstOrDefault();我需要找到一种方法来查看两个LINQ所产生的确切SQL-但很明显,两者之间的性能差别很大。Count和Any在某些情况下,不幸的是,你似乎不能就这样Any在任何情况下。编辑:这里是生成的SQL。如你所见;)ANY:exec sp_executesql N'SELECT TOP (1)
[Project2].[ContactId] AS [ContactId],
[Project2].[CompanyId] AS [CompanyId],
[Project2].[ContactName] AS [ContactName],
[Project2].[FullName] AS [FullName],
[Project2].[ContactStatusId] AS [ContactStatusId],
[Project2].[Created] AS [Created]
FROM ( SELECT [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName],
[Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created], row_number()
OVER (ORDER BY [Project2].[ContactId] ASC) AS [row_number]
FROM ( SELECT
[Extent1].[ContactId] AS [ContactId],
[Extent1].[CompanyId] AS [CompanyId],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[FullName] AS [FullName],
[Extent1].[ContactStatusId] AS [ContactStatusId],
[Extent1].[Created] AS [Created]
FROM [dbo].[Contact] AS [Extent1]
WHERE ([Extent1].[CompanyId] = @p__linq__0) AND ([Extent1].[ContactStatusId] <= 3) AND ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[NewsletterLog] AS [Extent2]
WHERE ([Extent1].[ContactId] = [Extent2].[ContactId]) AND (6 = [Extent2].[NewsletterLogTypeId])
))
) AS [Project2]
) AS [Project2]
WHERE [Project2].[row_number] > 99
ORDER BY [Project2].[ContactId] ASC',N'@p__linq__0 int',@p__linq__0=4COUNT:exec sp_executesql N'SELECT TOP (1)
[Project2].[ContactId] AS [ContactId],
[Project2].[CompanyId] AS [CompanyId],
[Project2].[ContactName] AS [ContactName],
[Project2].[FullName] AS [FullName],
[Project2].[ContactStatusId] AS [ContactStatusId],
[Project2].[Created] AS [Created]
FROM ( SELECT [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName],
[Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created],
row_number() OVER (ORDER BY [Project2].[ContactId] ASC) AS [row_number]
FROM ( SELECT
[Project1].[ContactId] AS [ContactId],
[Project1].[CompanyId] AS [CompanyId],
[Project1].[ContactName] AS [ContactName],
[Project1].[FullName] AS [FullName],
[Project1].[ContactStatusId] AS [ContactStatusId],
[Project1].[Created] AS [Created]
FROM ( SELECT
[Extent1].[ContactId] AS [ContactId],
[Extent1].[CompanyId] AS [CompanyId],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[FullName] AS [FullName],
[Extent1].[ContactStatusId] AS [ContactStatusId],
[Extent1].[Created] AS [Created],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[NewsletterLog] AS [Extent2]
WHERE ([Extent1].[ContactId] = [Extent2].[ContactId]) AND (6 = [Extent2].[NewsletterLogTypeId])) AS [C1]
FROM [dbo].[Contact] AS [Extent1]
) AS [Project1]
WHERE ([Project1].[CompanyId] = @p__linq__0) AND ([Project1].[ContactStatusId] <= 3) AND (0 = [Project1].[C1])
) AS [Project2]
) AS [Project2]
WHERE [Project2].[row_number] > 99
ORDER BY [Project2].[ContactId] ASC',N'@p__linq__0 int',@p__linq__0=4似乎纯粹的Where With比计算Count然后使用count=0执行WHERE要糟糕得多。如果你们看到我的发现有什么错误请告诉我。不管对VS计数的讨论如何,都可以从这一切中删除任何更复杂的LINQ,当将其重写为存储过程时,情况要好得多;)。