2016-07-22 25 views
5

Garip bir konuya girdiğimde daha iyi performans için EF6 kodumuzun bir kısmını Dapper'a taşıyordum. Tek satırlık bir sorgu, 'u neredeyse 10 kez'u Dapper'da EF'de olduğundan daha fazla alıyordu. Böyle görünüyordu:Parametreli sorgular için Kötü Dapper performansı

using (IDbConnection conn = new SqlConnection("connection string")) 
{     
     row = conn.Query<ReportView>("select * from ReportView where ID = @ID", 
              new {ID = id})) 
            .FirstOrDefault(); 
} 

Bu sorgu yaklaşık 80 sütunlu bir görünüm hedefler ve EF versiyonu tamamen aynı sorguyu ve aynı modeli kullanır.

row = context.ReportViews.Where(s => s.ID == id).FirstOrDefault(); 

Ben ilk sorgu yavaş olabileceğini dikkate aldı, bu yüzden bir "ısınmak" süresinden sonra ölçümler aldı: Referans için, bu EF versiyonudur. EF modelini yeniden kullanmanın bir sorun olabileceğini düşündüm, bu yüzden model olarak basit bir POCO oluşturdum. Hiçbiri işe yaramadı. Bu yüzden onunla oynamıştım, farklı şeyler denedim ve SQL-enjeksiyonlu birleştirilmiş SQL deyimini kullanmaya karar verdim.

using (IDbConnection conn = new SqlConnection("connection string")) 
{     
     row = conn.Query<ReportView>(string.Format("select * from ReportView where ID = '{0}'", 
      id)).FirstOrDefault(); 
} 

Bu sorgu EF birden daha hızlıydı.

Peki burada neler oluyor? Parametrized sorgu neden bu kadar yavaş?

+1

çünkü doğal anahtarın olmaması EF ile Görüntüleme kullanarak sorunların her türlü vardı oluşturulan SQL – stuartd

+0

Profil. Görünümünüzün ne yaptığından emin değilim (belki de bir CTE kullanmak gibi EF'de yapamayacağınız bir şey), fakat neden sorguyu Dapper ile görünüm yerine görünümde denemiyorsunuz? – juharr

+1

Nasıl kıyaslama yapıyorsunuz? – mxmissile

cevap

0

Paramater'ın veri türü ile ilgili. Dizininkiyle uyuşmuyorsa, karşılaştırmak için her satırı yayınlar. Bir dize olarak yapmak, sql ayrıştırıcısı tarafından seçilir.

0

Son örneğinizi temel alarak, büyük olasılıkla sütununuzun varchar olduğunu, ancak parametreli sorguyu kullandığınızda, parametrenin nvarchar olarak gönderilmesi gerekir. Varchar'ın varchar'a veri kaybı olabileceğinden, SQL tablodaki her değeri karşılaştırma için nvarchar'a dönüştürür. Tahmin edebileceğiniz gibi, karşılaştırmak için her satırı dönüştürmek yavaştır ve endeksin kullanımını engeller.

Dapper.SqlMapper.AddTypeMap(typeof(string), System.Data.DbType.AnsiString); 

Aksi takdirde değiştirebilirsiniz: veritabanı hiç nvarchar kullanmıyorsa

, sadece uygulama başlatma sırasında eşlemesi değiştirebilirsiniz:

Bu sorunu gidermek için , iki seçeneğiniz vardır o sorgu başına:

row = conn.Query<ReportView>("select * from ReportView where ID = @ID", 
           new {ID = new DbString { Value = id, IsAnsi = true }}) 
           .FirstOrDefault();