Not: Bu cevabı Entity Framework 4 gerçek olduğunda yazdım. Bu cevabın amacı önemsizliğe .Any()
karşı .Count()
performans testine girmek değildi . Mesele, EF'in mükemmel olmaktan uzak olduğunu göstermekti. Daha yeni sürümler daha iyidir ... ancak kodun yavaş olan bir parçası varsa ve EF kullanıyorsa, doğrudan TSQL ile test edin ve varsayımlara dayanmak yerine performansı karşılaştırın ( .Any()
her zamankinden daha hızlıdır .Count() > 0
).
Ben kabul ederken en cevabı ve yorum yukarı yüksek oyu - özellikle noktası üzerinde Any
sinyaller niyet geliştirici daha iyi Count() > 0
- Kont SQL Server (EntityFramework 4) üzerine büyüklük sırasına göre daha hızlı olduğu durum yaşadım.
İşte Any
thew zaman aşımı istisnası (~ 200.000 kayıtlarda) ile ilgili sorgu :
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
milisaniye içinde çalıştırılan sürüm:
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();
Ben tam bir SQL hem LINQs üretmek ne olduğunu görmek için bir yol bulmalıyız - ama arasında büyük performans fark yoktur açıktır Count
ve Any
bazı durumlarda, ve ne yazık ki sadece sopa olamaz görünüyor Any
her durumda.
EDIT: İşte üretilen SQL'ler. Gördüğünüz gibi güzellikler;)
ANY
:
exec sp_executesql N'SELECT ÜST (1)
[Proje2]. [ContactId] AS [ContactId],
[Proje2]. [Şirket Kimliği] AS [Şirket Kimliği],
[Proje2]. [KişiAdı] AS [KişiAdı],
[Proje2]. [TamAd] AS [TamAd],
[Proje2]. [ContactStatusId] AS [ContactStatusId],
[Proje2]. [Oluşturuldu] AS [Oluşturuldu]
FROM (SELECT [Project2]. [ContactId] AS [ContactId], [Project2]. [CompanyId] AS [CompanyId], [Project2]. [ContactName] AS [KişiAdı], [Project2]. [TamAd] AS [FullName] [Project2]. [ContactStatusId] AS [ContactStatusId], [Project2]. [Oluşturuldu] AS [Oluşturuldu], row_number () OVER (ORDER BY [Project2]. [ContactId] ASC) AS [row_number]
BAŞLANGIÇ (SEÇ
[Extent1]. [ContactId] AS [ContactId],
[Extent1]. [CompanyId] AS [CompanyId],
[Extent1]. [KişiAdı] AS [KişiAdı],
[Tam1]. [TamAd] AS [TamAd],
[Extent1]. [ContactStatusId] AS [ContactStatusId],
[Extent1]. [Oluşturuldu] AS [Oluşturuldu]
[Dbo] 'dan. [İletişim] AS [Extent1]
NEREDE ([Extent1]. [CompanyId] = @ p__linq__0) AND ([Extent1]. [ContactStatusId] <= 3) VE (VAR DEĞİL (SEÇ
1 AS [C1]
[Dbo] 'dan. [NewsletterLog] AS [Extent2]
NEREDE ([Extent1]. [ContactId] = [Extent2]. [ContactId]) AND (6 = [Extent2]. [NewsletterLogTypeId])
))
) AS [Proje2]
) AS [Proje2]
NEREDE [Proje2]. [Satır_sayısı]> 99
ORDER BY [Proje2]. [ContactId] ASC ', N' @ p__linq__0 int ', @ p__linq__0 = 4
COUNT
:
exec sp_executesql N'SELECT ÜST (1)
[Proje2]. [ContactId] AS [ContactId],
[Proje2]. [Şirket Kimliği] AS [Şirket Kimliği],
[Proje2]. [KişiAdı] AS [KişiAdı],
[Proje2]. [TamAd] AS [TamAd],
[Proje2]. [ContactStatusId] AS [ContactStatusId],
[Proje2]. [Oluşturuldu] AS [Oluşturuldu]
FROM (SELECT [Project2]. [ContactId] AS [ContactId], [Project2]. [CompanyId] AS [CompanyId], [Project2]. [ContactName] AS [KişiAdı], [Project2]. [TamAd] AS [FullName] [Project2]. [ContactStatusId] AS [ContactStatusId], [Project2]. [Oluşturuldu] AS [Oluşturuldu], row_number () OVER (ORDER BY [Project2]. [ContactId] ASC) AS [row_number]
BAŞLANGIÇ (SEÇ
[Proje1]. [ContactId] AS [ContactId],
[Proje1]. [Şirket Kimliği] AS [Şirket Kimliği],
[Proje1]. [KişiAdı] AS [KişiAdı],
[Proje1]. [TamAd] AS [TamAd],
[Proje1]. [ContactStatusId] AS [ContactStatusId],
[Proje1]. [Oluşturuldu] AS [Oluşturuldu]
BAŞLANGIÇ (SEÇ
[Extent1]. [ContactId] AS [ContactId],
[Extent1]. [CompanyId] AS [CompanyId],
[Extent1]. [KişiAdı] AS [KişiAdı],
[Tam1]. [TamAd] AS [TamAd],
[Extent1]. [ContactStatusId] AS [ContactStatusId],
[Oluşturuldu] AS [Oluşturuldu],
(SEÇ
COUNT (1) OLARAK [A1]
[Dbo] 'dan. [NewsletterLog] AS [Extent2]
NEREDE ([Extent1]. [ContactId] = [Extent2]. [ContactId]) AND (6 = [Extent2]. [NewsletterLogTypeId])) AS [C1]
[Dbo] 'dan. [İletişim] AS [Extent1]
) AS [Proje1]
NEREDE ([Project1]. [CompanyId] = @ p__linq__0) AND ([Project1]. [ContactStatusId] <= 3) AND (0 = [Project1]. [C1])
) AS [Proje2]
) AS [Proje2]
NEREDE [Proje2]. [Satır_sayısı]> 99
ORDER BY [Proje2]. [ContactId] ASC ', N' @ p__linq__0 int ', @ p__linq__0 = 4
EXISTS ile saf Nerede Count hesaplamak ve daha sonra Nerede Count == 0 ile yapmaktan daha kötü çalışır gibi görünüyor.
Bulgularımda bir hata görürseniz bana bildirin. Any vs Count tartışmasına bakılmaksızın tüm bunlardan çıkarılabilecek şey, daha karmaşık LINQ'nun Saklı Yordam olarak yeniden yazıldığında çok daha iyi olmasıdır;).