Varlık Çerçevesi, Yüksek Trafikli Web Sitelerine Uygun mu?


176

Entity Framework 4, potansiyel olarak 1000 hit / saniye içeren bir web sitesi için iyi bir çözüm mü?

Anladığım kadarıyla EF, çoğunlukla daha küçük veya intranet web siteleri için uygun bir çözümdür, ancak popüler bir topluluk web sitesi gibi bir şey için kolayca ölçeklendirilemez (SO'nun SQL için LINQ kullandığını biliyorum ama daha fazla örnek / kanıt istiyorum.). ..)

Şimdi ya saf bir ADO.NET yaklaşımı ya da EF4'ü seçmenin yolunda duruyorum. EF ile geliştirilen geliştirici verimliliğinin, ADO.NET'in (saklı yordamlarla) performansının ve ayrıntılı erişiminin değerinde olduğunu düşünüyor musunuz? Yüksek trafikli bir web sitesinin karşılaşabileceği herhangi bir ciddi sorun var mı, EF kullanıyordu?

Şimdiden teşekkür ederim.


1
Ölçeklemeyi anlamıyorsun. Ölçekleme, 10x kapasite eklediğinizde 10x veri alma anlamına gelir. EF neden bunun olmasını engellesin? Herhangi bir veritabanı iş yüküne sabit bir faktör ek yükü ekler.
usr

Yanıtlar:


152

Biraz ihtiyaç duyduğunuz soyutlamaya bağlı . Her şey bir uzlaşmadır; örneğin, EF ve NHibernate ilginç ve egzotik modellerinde verileri göstermek için büyük esneklik tanıtmak - ama sonuç olarak onlar yapmak yavaşlatırlar. Göze çarpan yükü.

Veri tabanı sağlayıcıları ile farklı müşteri başına masa düzenleri arasında geçiş yapmanıza gerek kalmazsa ve verileriniz öncelikle okunursa ve aynı modeli EF'de kullanmanız gerekmiyorsa, SSRS , ADO.NET Data Services, vb. - temel önleminiz olarak mutlak performans istiyorsanız, göz kamaştırıcıya bakmaktan çok daha kötüsünü yapabilirsiniz . Hem LINQ-to-SQL hem de EF'e dayanan testlerimizde , muhtemelen soyutlama katmanları (depolama modeli vb. Arasında) ve maddeleştirme nedeniyle EF'in ham okuma performansı açısından önemli ölçüde daha yavaş olduğunu tespit ettik .

Burada SO'da ham performans konusunda takıntılıyız ve hız kazanmak için bazı soyutlamaları kaybetme şansını yakalamanın mutluluğunu yaşıyoruz. Bu nedenle, veritabanını sorgulamak için birincil aracımız şık . Bu, önceden var olan LINQ-SQL modelimizi kullanmamızı bile sağlıyor, ancak basitçe: daha hızlı yığınlar. Performans testlerinde, temel olarak tüm ADO.NET kodunu (parametreler, veri okuyucular vb.) Manuel olarak yazma ile aynıdır, ancak bir sütun adını yanlış anlama riski yoktur. Ancak, SQL tabanlıdır (seçtiğiniz zehir ise SPROC'ları kullanmaktan mutluluk duysa da). Bunun avantajı olmasıdır hiçbir ek işlem katılan, ancak olan SQL gibi insanlar için bir sistem. Hangi düşünüyorum: kötü bir şey değil!

Örneğin, tipik bir sorgu olabilir:

int customerId = ...
var orders = connection.Query<Order>(
    "select * from Orders where CustomerId = @customerId ",
    new { customerId }).ToList();

hangi uygun, enjeksiyon güvenli, vb - ama tonlarca veri okuyucu goo olmadan. Karmaşık yapıları yüklemek için hem yatay hem de dikey bölümleri kaldırabilse de, tembel yüklemeyi desteklemeyeceğini unutmayın (ancak: biz çok açık yüklemenin büyük hayranlarıyız - daha az sürprizle).

Ben EF demiyorum bu yanıtında Not değildir , yüksek hacimli işler için uygundur; basitçe: o kumandanın buna bağlı olduğunu biliyorum .


25
Kepçe için +1. Okuma modelleri için karmaşık bir ORM kullanmak sadece gerekli değildir. Şimdi ele aldığımız yaklaşım, etki alanı modelimiz için bir ORM kullanmak (süslü ORM öğelerinin gerçekten yararlı olduğu yerlerde) ve okuma modelimiz için dapper kullanmaktır. Bu süper hızlı uygulamalar için yapar.

2
@Marc, mükemmel cevap için teşekkür ederim - Sonunda kararımı güvenle verebilirim! Kesinlikle daha sonra daha detaylı olarak bakacağız. Gerçekten nasıl sadece bir dosya :) gibi

3
Kendi ORM'imi yazdım. Yavaş. Ben depper'a baktım ve hoşuma gitti. Şimdi tüm okuyucular için dapper'ı ve ekler için kendi ORM'imi kullanıyorum (bu, FK, işlemler ve tüm iyi şeyleri destekliyor). Şimdiye kadar yazdığım en kolay okunabilir kod.

2
@ acidzombie24 dapper işlemleri destekler ve dapper'ın katkı kısmı (nuget dağıtımının bir parçası değildir) insert etc seçenekleri kazanır. Sadece bütünlüğü söyleyerek. Kızım kullanışlı olduğuna sevindim.
Marc Gravell

1
@anyname Hiç bir konuda bir video kursu yapmadım; Orada bazı videolar var, ama benim tarafımdan değil. Yazılı bir kişi olma eğilimindeyim
Marc Gravell

217

"Hangi ORM kullanmalıyım" sorusu, genel olarak veri erişim stratejisi ve büyük ölçekli bir uygulamada performans optimizasyonu söz konusu olduğunda, büyük bir buzdağının tepesini hedef almaktadır.

Aşağıdakilerin tümü ( kabaca önem sırasına göre) iş hacmini etkileyecek ve hepsi orada bulunan bazı ORM çerçevelerinin çoğu tarafından (bazen farklı şekillerde) ele alınacak:

  1. Veri Tabanı Tasarımı ve Bakımı

    Bu, geniş bir aralıkta, veri odaklı bir uygulamanın veya web sitesinin verimliliğinin en önemli belirleyicisidir ve genellikle programcılar tarafından tamamen göz ardı edilir.

    Uygun normalleştirme teknikleri kullanmazsanız, siteniz mahkumdur. Birincil anahtarlarınız yoksa hemen hemen her sorgu köpek yavaş olacaktır. Anahtar-Değer Çiftleri (AKA Varlık-Nitelik-Değer) tablolarını iyi bir sebep olmadan kullanmak gibi iyi bilinen kalıpları kullanıyorsanız, fiziksel okuma ve yazma sayısını patlatacaksınız.

    Sayfa sıkıştırma, FILESTREAMdepolama (ikili veriler için), hiyerarşiler için SPARSEsütunlar , vb. Gibi veritabanının size sunduğu özelliklerden yararlanmazsanız hierarchyid(tüm SQL Server örnekleri) performans olabilir göreceğim.

    Veritabanınızı tasarladıktan ve en azından şimdilik mümkün olabileceği kadar iyi olduğuna ikna olduktan sonra , veri erişim stratejiniz hakkında endişelenmeye başlamalısınız .

  2. İstekli vs tembel yükleme

    Çoğu ORM , ilişkiler için tembel yükleme denilen bir teknik kullandı ; bu, varsayılan olarak bir kerede bir varlık (tablo sırası) yükleyeceği ve bir veya daha fazla ilgili (yabancı) yüklemesi gerektiğinde veritabanına bir gidiş-dönüş yapacak anlamına gelir. key) satırlar.

    Bu iyi ya da kötü bir şey değil, verilerle gerçekte ne yapılması gerektiğine ve ne kadar önceden bildiğinize bağlı. Bazen tembel yükleme kesinlikle yapılacak en doğru şeydir. Örneğin, NHibernate, hiçbir şey için sorgulama yapmamaya ve belirli bir kimlik için bir proxy oluşturmaya karar verebilir . İhtiyacınız olan tek şey kimliğin kendisi ise neden daha fazlasını isteyelim? Öte yandan, her bir öğenin bir ağacını 3 seviyeli bir hiyerarşide basmaya çalışıyorsanız, tembel yükleme, performans için aşırı derecede kötü olan bir O (N²) işlemi olur .

    "Saf SQL" (örneğin, ham ADO.NET sorguları / saklı yordamları) kullanmanın ilginç yararlarından biri, belirli bir ekranı veya sayfayı görüntülemek için tam olarak hangi verilerin gerekli olduğunu düşünmeye zorlamasıdır. ORMS'nin ve tembel yükleme özellikleri yok önlemek Bunu yaparken sizi, ancak do size, iyi ... olma fırsatını sunmaktadır tembel ve yanlışlıkla yürütmek sorguların sayısını patlayabilir. Bu nedenle, ORM'lerinizi istekli yükleme özelliklerini anlamanız ve herhangi bir sayfa isteği için sunucuya gönderdiğiniz sorgu sayısı konusunda daima uyanık olmanız gerekir.

  3. Caching

    Tüm büyük ORM'ler birinci seviye önbellek, AKA "kimlik önbellek" i korurlar; bu, kimliğine iki kez aynı varlık istemeniz durumunda, ikinci bir tur atması gerektirmeyeceği anlamına gelir ve ayrıca (veritabanınızı doğru tasarladıysanız) ) size iyimser eşzamanlılık kullanma yeteneği verir.

    L1 önbelleği, L2S ve EF'de oldukça opaktır, çalışmakta olduğuna güvenmek zorundasınız. NHibernate bu konuda daha açıktır ( Get/ Loadvs. Query/ QueryOver). Yine de, kimliğe göre sorgulamaya çalıştığınız sürece burada iyi olmalısınız. Birçok insan L1 önbelleğini unutur ve tekrar tekrar aynı kimliği, kimliği dışında başka bir şey tarafından tekrar tekrar arar (yani bir arama alanı). Bunu yapmanız gerekirse, daha sonra yapılacak aramalar için kimliği veya hatta tüm varlığı saklamanız gerekir.

    Ayrıca seviye 2 önbellek ("sorgu önbelleği") de vardır. NHibernate bu yerleşik yapıya sahiptir. Linq to SQL ve Entity Framework , sorgu ifadesinin kendisini derleyerek uygulama sunucusu yüklerini biraz azaltmaya yardımcı olabilecek sorguları derledi , ancak verileri önbelleğe almıyor. Microsoft bu veri erişim endişesi yerine bir uygulama endişesi olarak görünüyor ve bu hem L2S hem de EF için önemli bir zayıf nokta. Söylemeye gerek yok, aynı zamanda "ham" SQL'in zayıf bir noktası. Temelde NHibernate dışındaki herhangi bir ORM ile gerçekten iyi bir performans elde etmek için kendi önbellek cephenizi uygulamanız gerekir.

    Orada EF4'ü için bir L2 önbellek "uzantısı" da var tamam bir uygulama düzeyi önbelleği için toptan yedek gerçekten değil.

  4. Sorgu Sayısı

    İlişkisel veritabanları veri kümelerine dayanır . Kısa sürede büyük miktarlarda veri üretmek konusunda gerçekten başarılılar , ancak sorgu gecikmesi açısından hiçbir yere yakın değiller çünkü her komutta belirli bir miktar ek yük vardır. İyi tasarlanmış bir uygulama bu DBMS'nin güçlü yönlerine dayanmalı ve sorgu sayısını en aza indirmeli ve her birindeki veri miktarını en üst düzeye çıkarmalıdır.

    Şimdi sadece bir satıra ihtiyacınız olduğunda veritabanının tamamını sorgulamak istemiyorum. Eğer gerekirse Söylediğim şey olduğunu Customer, Address, Phone, CreditCard, ve Ordersonra gereken, tek bir sayfa hizmet etmek için aynı anda satırları tüm sormak , aynı anda hepsi için ayrı ayrı sorguyu yürütmek yoktur. Bazen bundan daha kötüsü, aynı Customerkaydı arka arkaya 5 kez sorgulayan bir kod görürsünüz , önce Id, sonra Name, sonra EmailAddress, sonra ... gülünç verimsiz.

    Tamamı tamamen farklı veri kümelerinde çalışan birkaç sorgu yürütmeniz gerekse bile, hepsini tek bir "komut dosyası" olarak veri tabanına göndermek ve birden fazla sonuç kümesi döndürmesini sağlamak genellikle daha etkilidir. En fazla veri topladığınız şey değil, endişelendiğiniz yüküdür.

    Bu sağduyulu gibi gelebilir, ancak uygulamanın çeşitli bölümlerinde yürütülen tüm sorguların kaydını kaybetmek çoğu zaman kolaydır; Üyelik Sağlayıcınız kullanıcı / rol tablolarını, Başlık işleminiz alışveriş sepetini, Menü işleminiz site haritası tablosunu, Kenar Çubuğu işleminizin özellikli ürün listesini sorgular ve belki de sayfanız birkaç ayrı özerk alana bölünmüştür. Sipariş Geçmişi, En Son Görüntülenen, Kategori ve Envanter tablolarını ayrı ayrı sorgulayın ve bunu bilmeden önce, sayfayı sunmaya başlamadan önce 20 sorgu yürütüyorsunuz. Sadece performansı tamamen yok ediyor.

    Bazı çerçeveler - ve burada esas olarak NHibernate'i düşünüyorum - bu konuda son derece zekiyiz ve tüm sorguları toplayan vadeli işlem adı verilen bir şeyi kullanmanıza ve hepsini bir kerede, en son dakikada yürütmeye çalışmanıza izin veriyor . AFAIK, bunu Microsoft teknolojilerinin herhangi biriyle yapmak istiyorsanız kendi başınızasınız; Uygulama mantığınıza eklemeniz gerekir.

  5. İndeksleme, Tahminler ve Projeksiyonlar

    Konuştuğum cihazların en az% 50'si konuştum ve hatta bazı DBA'lar endeksleri kapsayan kavramlarla ilgili sorun yaşıyor gibi görünüyor. " Customer.NameSütun endekslendi, yani isim üzerinde yaptığım her arama hızlı olmalı" diye düşünüyorlar. NameDizin , aradığınız belirli sütunu kapsamıyorsa , bu şekilde çalışmaz . De SQL Server, bununla bitti INCLUDEde CREATE INDEXaçıklamada.

    Her SELECT *yerde saf bir şekilde kullanıyorsanız - ve eğer bir projeksiyon kullanarak açıkça belirtmediğiniz sürece her ORM'nin yapacağı şey az çoktur - o zaman DBMS, endekslerinizi tamamen göz ardı etmeyi seçebilir, çünkü bunlar kaplanmamış sütunlar içerir. Bir projeksiyon, örneğin, bunu yapmak yerine;

    from c in db.Customers where c.Name == "John Doe" select c
    

    Bunun yerine bunu yapın:

    from c in db.Customers where c.Name == "John Doe"
    select new { c.Id, c.Name }
    

    Ve bu irade, en modern ORMs için, sadece gidip sorgulamak talimat Idve Nametahminen endeksi kapsamındadır sütunları (ancak Email, LastActivityDateya da başka hangi Orada sopa oldu sütunlar).

    Ayrıca, uygun tahminleri kullanarak tüm indeksleme avantajlarını tamamen ortadan kaldırmak çok kolaydır. Örneğin:

    from c in db.Customers where c.Name.Contains("Doe")
    

    ... önceki sorgumuzla neredeyse birebir aynı gözüküyor, ancak aslında tam bir tablo veya indeks taramasıyla sonuçlanacak çünkü çeviriyor LIKE '%Doe%'. Benzer şekilde, şüpheli bir şekilde basit görünen başka bir sorgu:

    from c in db.Customers where (maxDate == null) || (c.BirthDate >= maxDate)
    

    Bir dizininiz olduğunu varsayarsak BirthDate, bu yüklemin tamamen yararsız hale gelmesi için iyi bir şansı var. Buradaki varsayımsal programcımız açıkça bir tür dinamik sorgu oluşturmaya çalıştı ("sadece bu parametre belirtilmişse doğum tarihini filtrele"), ancak bunu yapmanın doğru yolu bu değil. Bunun yerine şöyle yazılır:

    from c in db.Customers where c.BirthDate >= (maxDate ?? DateTime.MinValue)
    

    ... şimdi DB motoru bunu nasıl parametreleyeceğini ve bir indeks araması yapmayı biliyor. Sorgu ifadesinde küçük, görünüşte önemsiz bir değişiklik performansı önemli ölçüde etkileyebilir.

    Ne yazık ki, genel olarak LINQ, böyle kötü sorgular yazmayı çok kolaylaştırır, çünkü bazen sağlayıcılar ne yapmaya çalıştığınızı tahmin edebilir ve sorguyu optimize edebilir, bazen de değildir. Bu yüzden , (zaten tecrübeli bir DBA'ya) gözle görülür şekilde açık olan sinir bozucu derecede tutarsız sonuçlarla bitirdiniz, eski düz SQL yazdınız.

    Temel olarak her şey, hem oluşturulan SQL hem de yol açtığı yürütme planlarını yakından takip etmeniz gerektiğine ve beklediğiniz sonuçları alamamanız durumunda, bunu atlamaktan korkmayın. Arada bir ORM katmanı ve SQL el-kodu. Bu sadece EF için değil, herhangi bir ORM için de geçerlidir .

  6. İşlemler ve Kilitleme

    Milisaniyeye kadar güncel olan verileri görüntülemeniz mi gerekiyor? Belki - bağlıdır - ama muhtemelen değil. Ne yazık ki, Varlık Çerçeve seni vermeznolock , sadece kullanabilirsiniz READ UNCOMMITTEDaz işlem düzeyinde (değil tablo düzeyi). Aslında, ORM'lerin hiçbiri bu konuda özellikle güvenilir değildir; kirli okuma yapmak istiyorsanız, SQL seviyesine düşmeniz ve geçici sorgular veya saklı yordamlar yazmanız gerekir. Öyleyse, tekrar kaynayan şey, bunu çerçeve içinde yapmanın sizin için ne kadar kolay olduğu.

    Entity Framework bu konuda uzun bir yol kat etti - EF'in 1. sürümü (.NET 3.5'te) çok kötüydü, "varlıklar" soyutlamasını kırmak inanılmaz derecede zordu, ama şimdi ExecuteStoreQuery ve Translate'e sahipsin , bu yüzden gerçekten çok fena değil. Bu adamlarla arkadaş olun, çünkü onları çok kullanıyor olacaksınız.

    Aynı zamanda yazma kilitleme ve kilitlenme sorunu ve veritabanında mümkün olan en kısa sürede kilit tutma genel uygulaması da var. Bu bağlamda, çoğu ORM (Entity Framework dahil), aslında ham SQL'den daha iyi olma eğilimindedir, çünkü EF'de SaveChanges olan Çalışma modeli birimini içermektedir . Başka bir deyişle, kalbinizin içeriğine varlıkları "ekleyebilir" veya "güncelleyebilir" veya "silebilir", istediğiniz zaman, çalışma birimini işleyene kadar hiçbir değişikliğin veritabanına itilmeyeceği bilgisini güvence altına alabilirsiniz.

    Bir UOW'nin uzun süren bir işlemle aynı olmadığını unutmayın . UOW, ORM'nin iyimser eşzamanlılık özelliklerini hala kullanıyor ve bellekteki tüm değişiklikleri takip ediyor . Son işleme kadar tek bir DML bildirimi yayınlanmaz. Bu işlem sürelerini mümkün olduğu kadar düşük tutar. Uygulamanızı ham SQL kullanarak oluşturursanız, bu ertelenen davranışı elde etmek oldukça zordur.

    Bunun özellikle EF için ne anlama geldiğini: İş birimlerinizi mümkün olduğunca kaba yapın ve tam olarak ihtiyaç duymadıkça bunları işleme koymayın. Bunu yapın ve bireysel ADO.NET komutlarını rastgele zamanlarda kullanacağınızdan çok daha düşük bir kilit çekişmesi ile sonuçlanacak.

Sonuç olarak:

EF, yüksek trafikli / yüksek performanslı uygulamalar için tamamen iyi, diğer tüm çerçevelerde olduğu gibi yüksek trafikli / yüksek performanslı uygulamalar için gayet iyi. Önemli olan onu nasıl kullandığın. İşte en popüler çerçevelerin ve performans açısından sundukları özelliklerin hızlıca karşılaştırılması (açıklama: N = Desteklenmiyor, P = Kısmi, Y = evet / desteklenir):

                                | L2S | EF1 | EF4 | NH3 | ADO
                                +-----+-----+-----+-----+-----
Lazy Loading (entities)         |  N  |  N  |  N  |  Y  |  N
Lazy Loading (relationships)    |  Y  |  Y  |  Y  |  Y  |  N
Eager Loading (global)          |  N  |  N  |  N  |  Y  |  N
Eager Loading (per-session)     |  Y  |  N  |  N  |  Y  |  N
Eager Loading (per-query)       |  N  |  Y  |  Y  |  Y  |  Y
Level 1 (Identity) Cache        |  Y  |  Y  |  Y  |  Y  |  N
Level 2 (Query) Cache           |  N  |  N  |  P  |  Y  |  N
Compiled Queries                |  Y  |  P  |  Y  |  N  | N/A
Multi-Queries                   |  N  |  N  |  N  |  Y  |  Y
Multiple Result Sets            |  Y  |  N  |  P  |  Y  |  Y
Futures                         |  N  |  N  |  N  |  Y  |  N
Explicit Locking (per-table)    |  N  |  N  |  N  |  P  |  Y
Transaction Isolation Level     |  Y  |  Y  |  Y  |  Y  |  Y
Ad-Hoc Queries                  |  Y  |  P  |  Y  |  Y  |  Y
Stored Procedures               |  Y  |  P  |  Y  |  Y  |  Y
Unit of Work                    |  Y  |  Y  |  Y  |  Y  |  N

Gördüğünüz gibi, EF4 (şu anki sürüm) çok kötü bir ücret almıyor, ancak performans öncelikli kaygınız ise muhtemelen en iyisi değil. NHibernate bu alanda çok daha olgun ve hatta Linq to SQL bile EF'in hala yapmadığı bazı performans arttırıcı özellikler sunuyor. Ham ADO.NET, çok özel veri erişim senaryoları için genellikle daha hızlı olacaktır , ancak tüm parçaları bir araya getirdiğinizde, çeşitli çerçevelerden elde ettiğiniz pek çok önemli fayda sunmaz.

Ve, kırık bir kayıt gibi göründüğümden tamamen emin olmak için, veritabanınızı, uygulamanızı ve veri erişim stratejilerinizi uygun şekilde tasarlamamanız durumunda bunların hiçbiri en ufak bir sorun olmaz. Yukarıdaki çizelgede yer alan öğelerin tümü , taban çizgisinin ötesindeki performansı artırmak içindir ; Çoğu zaman, temel kendisi en çok iyileştirme gerektiren şeydir.


38
Ne harika ve kapsamlı bir cevap!

2
+1 (eğer yapabilirsem daha fazlası) - bir süredir gördüğüm en iyi cevaplardan biri ve bir iki şey öğrendim - bunu paylaştığın için teşekkürler!
BrokenGlass

1
Bu harika bir cevap bile belirtilenlere katılmıyorum. ORM'leri karşılaştıran tablo her zaman doğru değildir. Varlıklar tembel yükleme nedir? Tembel yüklü sütunlar mı demek istiyorsun? Bu L2S'de desteklenir. Sence neden NH derlenmiş sorguları desteklemiyor? Bence adlandırılmış HQL sorguları önceden derlenebilir. EF4'ün çoklu sonuç kümeleri için desteği yoktur.
Ladislav Mrnka

11
Mecbur kuvvetle niteliksiz katılmıyorum "EF yüksek trafik / yüksek performanslı uygulamalar için tamamen gayet" deyimi, bu böyle olmadığını defalarca gördük. Verilen, belki neyi "yüksek performanslı" vasıtası ile katılmıyorum ama örneğin 500ms aşağı web sayfalarını optimize edilmesi ve bunun 400ms + çerçevesinde iç açıklanamaz geçirmiş olan (ve sadece 10ms aslında , isabet SQL) bazı durumlar için "iyi" değil bizim dev ekibimiz için kabul edilemez düpedüz.
Nick Craver

1
EF'deki vadeli işlemler hakkında basit bir not. Bunlar resmen MS EF ekibi tarafından sağlanmamaktadır, ancak Future <> IQueryable <> uzantılarını tanımlayan üçüncü taraf projeleriyle başarılabilir. Örneğin, EntityFramework. NuSet'te bulunan LoreSoft tarafından eklenmiştir. Üretim uygulamalarındaki kişisel testlerim, düzinelerce bağımlı olmayan sorguyu (tüm sorgular paralel olarak gerçekleştirilebiliyor, hiç kimse bir önceki sorgunun sonucunu gerektirmiyor) geleceği kullanarak tek bir partide paketlendiğinde 10 katına kadar performans artışı gösteriyor. Ayrıca AsNoTracking () yalnızca çok sayıda kayıt okurken performansı daha da artırır, daha sonra güncelleme yapmaz.
David Oliván Ubieto

38

Düzenleme: @Aaronaught büyük cevabı dayanarak EF ile performans hedefleyen birkaç puan ekliyorum. Bu yeni noktalar Edit tarafından önceden eklenmiştir.


Yüksek trafikli web sitelerinde performanstaki en büyük gelişme, önbellekleme (= her şeyden önce herhangi bir web sunucusu işleminden veya veritabanı sorgulamasından kaçınılması) ve ardından veritabanı sorguları yapılırken iş parçacığı engellemesini önlemek için eşzamansız işlemle gerçekleştirilir.

Sorunuza kurşun geçirmez bir cevap yoktur, çünkü bu her zaman uygulama gereksinimlerine ve sorguların karmaşıklığına bağlıdır. Gerçek şu ki, EF ile geliştirici üretkenliği, çoğu durumda hatalı EF kullanımına ve korkunç performansa yol açan karmaşıklığı gizlemektedir. Veri erişimi için üst düzey soyutlanmış bir arabirim ortaya çıkarabileceğiniz ve her durumda sorunsuz çalışacağı fikri işe yaramaz. ORM ile bile, soyutlamanın arkasında ne olduğunu ve nasıl doğru kullanılacağını bilmelisin.

EF ile daha önce deneyiminiz yoksa, performansla ilgili birçok zorlukla karşılaşacaksınız. EF ile çalışırken ADO.NET'e kıyasla çok daha fazla hata yapabilirsiniz. Ayrıca, EF’de birçok ek işlem yapıldığından, EF her zamanki ADO.NET’ten önemli ölçüde daha yavaş olacaktır - bu, basit bir konsept uygulama kanıtı kanıtı ile ölçebileceğiniz bir şeydir.

EF’ten en iyi performansı almak istiyorsanız, muhtemelen:

  • SQL profiler ile veri erişiminizi çok dikkatli bir şekilde gözden geçirin ve Linq-to-nesneleri yerine Linq-varlıklarını doğru kullanıyorlarsa LINQ sorgularınızı inceleyin
  • Gelişmiş EF optimizasyon özelliklerini çok dikkatli kullanın. MergeOption.NoTracking
  • Bazı durumlarda ESQL kullanın
  • Sıklıkla yürütülen ön derleme sorguları
  • Bazı sorgular için "ikinci seviye önbellek" benzeri bir özellik elde etmek için EF Önbellek paketleyiciden yararlanmayı düşünün
  • Performans iyileştirmesi gerektiren sık kullanılan projeksiyonlar veya toplamalar için bazı senaryolarda SQL görünümlerini veya özel eşlenmiş SQL sorgularını (EDMX dosyasının el ile tutulmasını gerektirir) kullanın
  • Linq veya ESQL'de tanımlandığında yeterli performans sağlamayan bazı sorgular için yerel SQL ve saklı yordamları kullanın
  • Düzenleme: Sorguları dikkatlice kullanın - her sorgu veri tabanına gidiş dönüş yapar. EFv4'ün sorgulama grubu yok, çünkü yürütülen veritabanı komutu başına birden fazla sonuç kümesi kullanamıyor. EFv4.5, haritalanmış saklı prosedürler için çoklu sonuç kümelerini destekleyecektir.
  • Düzenleme: Veri değişikliklerinde dikkatli çalışın. Yine EF, tamamen komut harmanlamasından yoksun . Bu nedenle, ADO.NET'te SqlCommandbirden fazla ekleme, güncelleme veya silme içeren tekli kullanabilirsiniz , ancak EF ile bu komutların her biri veritabanına ayrı gidiş dönüş olarak çalıştırılır.
  • Düzenleme: Kimlik haritası / kimlik önbelleği ile dikkatlice çalışın. EF'in önbelleği sorgulamak için özel bir yöntemi vardır ( GetByKeyObjectContext API'sinde veya FindDbContext API'sinde). Linq-to-entities veya ESQL kullanıyorsanız, veritabanına gidiş dönüş yaratacaktır ve bundan sonra mevcut örneği önbellekten döndürecektir.
  • Düzenleme: istekli yükleme dikkatlice kullanın. Her zaman kazan-kazan çözümü değildir, çünkü büyük bir veri kümesi üretir . Gördüğünüz gibi bir sürü ek karmaşıklık var ve hepsi bu. ORM, haritalamayı ve materyalleştirmeyi kolaylaştırıyor, ancak performansla uğraşırken çok daha karmaşık hale gelecek ve takas yapmanız gerekecek.

SO hala L2S kullanıyor mu emin değilim. Dapper adında yeni bir açık kaynak ORM geliştirdiler ve bence bu gelişmenin arkasındaki ana nokta performansı artırmaktı.


Ladislav, bu gerçekten yardımcı bir cevap. Bu Dapper'ı ilk kez duyduğumda (ve dolayısıyla PetaPoco, Massive'ı keşfetti) - ve ilginç bir fikir gibi görünüyor.

1
SO şimdi SQL ve Dapper ile LINQ karışımını kullanıyor gibi görünüyor: samsaffron.com/archive/2011/03/30/… Alıntı: "Yeni ORM [Dapper] 'ı belirli bir sorun için kullanıyoruz: parametreli hale getirilmiş SQL'i iş nesnelerine eşlemek Tam gelişmiş bir ORM olarak kullanmıyoruz, ilişkiler, diğer ziller ve ıslık çalmıyor, performansın önemli olduğu ve bizim haritamızı kullanmak için tüm satır içi SQL'imizi taşıdığı LINQ-2-SQL kullanmaya devam etmemizi sağlıyor. çünkü daha hızlı ve daha esnek. "

5
@ Slauma, aylar öncesinden bir ifadedir, genel olarak SO'daki tüm yeni çalışmalar Dapper'da yapılır, örneğin bugün eklediğim yeni bir tablo dbml dosyasında bile değildir.
Sam Saffron

1
@Sam: SO'daki mevcut veri erişim stratejisi hakkında yeni bir blog yazısı var mı? Çok ilginç olurdu ! Bu arada Dapper uzatıldı mı? Anladığım kadarıyla Dapper tam bir ORM değil, ilişkileri desteklemiyordu - peki ya güncellemeler, ekler, silmeler, işlemler, değişiklik izleme vb.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.