Catatan: Saya menulis jawaban ini ketika Entity Framework 4 aktual. Inti dari jawaban ini adalah untuk tidak masuk ke pengujian sepele .Any()
vs .Count()
kinerja. Intinya adalah memberi sinyal bahwa EF jauh dari sempurna. Versi yang lebih baru lebih baik ... tetapi jika Anda memiliki bagian dari kode yang lambat dan menggunakan EF, uji dengan TSQL langsung dan bandingkan kinerja daripada mengandalkan asumsi (yang .Any()
SELALU lebih cepat daripada .Count() > 0
).
Sementara saya setuju dengan jawaban dan komentar yang paling banyak dipilih - terutama pada maksud Any
sinyal maksud pengembang lebih baik daripada Count() > 0
- Saya memiliki situasi di mana Hitungan lebih cepat berdasarkan urutan besarnya pada SQL Server (EntityFramework 4).
Berikut adalah kueri dengan Any
pengecualian batas waktu tersebut (pada ~ 200.000 catatan):
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
versi dieksekusi dalam hitungan milidetik:
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();
Saya perlu menemukan cara untuk melihat apa yang persis dihasilkan oleh kedua LINQ SQL - tapi jelas ada perbedaan kinerja yang sangat besar antara Count
dan Any
dalam beberapa kasus, dan sayangnya sepertinya Anda tidak bisa hanya bertahan dengan Any
semua kasus.
EDIT: Berikut ini adalah SQL yang dihasilkan. Keindahan seperti yang Anda lihat;)
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],
[Proyek2]. [Dibuat] AS [Dibuat]
DARI (PILIH [Project2]. [ContactId] AS [ContactId], [Project2]. [CompanyId] AS [CompanyId], [Project2]. [ContactName] AS [ContactName], [Project2]. [FullName] AS [FullName] , [Project2]. [ContactStatusId] AS [ContactStatusId], [Project2]. [Dibuat] AS [Dibuat], row_number () LEBIH (ORDER DENGAN [Project2]. [ContactId] ASC) AS [row_number]
DARI (PILIH
[Extent1]. [ContactId] AS [ContactId],
[Extent1]. [CompanyId] AS [CompanyId],
[Extent1]. [ContactName] AS [ContactName],
[Extent1]. [FullName] AS [FullName],
[Extent1]. [ContactStatusId] AS [ContactStatusId],
[Extent1]. [Dibuat] AS [Dibuat]
DARI [dbo]. [Kontak] SEBAGAI [Extent1]
DIMANA ([Extent1]. [CompanyId] = @ p__linq__0) DAN ([Extent1]. [ContactStatusId] <= 3) DAN (BUKAN ADA (SELECT)
1 AS [C1]
DARI [dbo]. [NewsletterLog] AS [Extent2]
WHERE ([Extent1]. [ContactId] = [Extent2]. [ContactId]) AND (6 = [Extent2]. [NewsletterLogTypeId])
))
) SEBAGAI [Proyek2]
) SEBAGAI [Proyek2]
WHERE [Project2]. [Row_number]> 99
ORDER OLEH [Project2]. [ContactId] ASC ', N' @ p__linq__0 int ', @ p__linq__0 = 4
COUNT
:
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],
[Proyek2]. [Dibuat] AS [Dibuat]
DARI (PILIH [Project2]. [ContactId] AS [ContactId], [Project2]. [CompanyId] AS [CompanyId], [Project2]. [ContactName] AS [ContactName], [Project2]. [FullName] AS [FullName] , [Project2]. [ContactStatusId] AS [ContactStatusId], [Project2]. [Dibuat] AS [Dibuat], row_number () LEBIH (ORDER DENGAN [Project2]. [ContactId] ASC) AS [row_number]
DARI (PILIH
[Project1]. [ContactId] AS [ContactId],
[Project1]. [CompanyId] AS [CompanyId],
[Project1]. [ContactName] AS [ContactName],
[Project1]. [FullName] AS [FullName],
[Project1]. [ContactStatusId] AS [ContactStatusId],
[Proyek1]. [Dibuat] AS [Dibuat]
DARI (PILIH
[Extent1]. [ContactId] AS [ContactId],
[Extent1]. [CompanyId] AS [CompanyId],
[Extent1]. [ContactName] AS [ContactName],
[Extent1]. [FullName] AS [FullName],
[Extent1]. [ContactStatusId] AS [ContactStatusId],
[Extent1]. [Created] AS [Created],
(PILIH
COUNT (1) AS [A1]
DARI [dbo]. [NewsletterLog] AS [Extent2]
WHERE ([Extent1]. [ContactId] = [Extent2]. [ContactId]) AND (6 = [Extent2]. [NewsletterLogTypeId])) SEBAGAI [C1]
DARI [dbo]. [Kontak] SEBAGAI [Extent1]
) SEBAGAI [Proyek1]
WHERE ([Project1]. [CompanyId] = @ p__linq__0) DAN ([Project1]. [ContactStatusId] <= 3) DAN (0 = [Project1]. [C1])
) SEBAGAI [Proyek2]
) SEBAGAI [Proyek2]
WHERE [Project2]. [Row_number]> 99
ORDER OLEH [Project2]. [ContactId] ASC ', N' @ p__linq__0 int ', @ p__linq__0 = 4
Tampaknya murni Dimana dengan EXIS bekerja jauh lebih buruk daripada menghitung Hitung dan kemudian melakukan Mana dengan Hitung == 0.
Beritahu saya jika Anda melihat kesalahan dalam temuan saya. Apa yang bisa diambil dari semua ini terlepas dari diskusi Apa pun vs Hitung adalah bahwa setiap LINQ yang lebih kompleks jauh lebih baik ketika ditulis ulang sebagai Prosedur Tersimpan;).