2016-07-22 35 views
5

私は奇妙な問題に遭遇したときにパフォーマンスを向上させるためにEF6コードのいくつかをDapperに移植することを研究していました。単一行のクエリは、を、EFで行ったよりもDapperの方がほぼ10倍となりました。パラメータ化されたクエリのパフォーマンスが悪い

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

このクエリは約80列のビューをターゲットにしており、EFバージョンは同じ正確なクエリと同じモデルを使用しています。参考までに、これはEFバージョンです:

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

私は、最初のクエリが遅くなる可能性があることを考慮したので、私は「ウォームアップ」期間後に測定しました。私はそれがEFモデルの再利用の問題かもしれないと思ったので、モデルとして単純なPOCOを作成しました。それのどれも働かなかった。だから、私はそれを試して、別のことを試して、SQLインジェクション連結SQLステートメントを使用しようと決めました。

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

この問い合わせはEFよりも、実際に速かったです。

ここで何が起こっていますか?なぜパラメータ化されたクエリが非常に遅いのですか?

+1

生成されたSQLをプロファイル – stuartd

+0

自然なキーがないため、EFでビューを使用するとさまざまな問題が発生しました。あなたのビューが何か(CTEを使用するようなEFではできないことかもしれません)がわかりませんが、Dapperのビューではなくビューでクエリを試してみてください。 – juharr

+1

どのようにベンチマークですか? – mxmissile

答えて

0

これはパラメータのデータ型と関係があります。インデックスと一致しない場合は、すべての行をキャストして比較します。それは、SQLパーサによってタイプが選択される文字列として実行されます。

0

最終的な例に基づいて、列はvarcharである可能性が高いですが、パラメータ化クエリを使用すると、パラメータはnvarcharとして送信されます。 nvarcharからvarcharにデータが失われる可能性があるため、SQLは比較のためにテーブルの各値をnvarcharに変換します。想像するように、比較のためにすべての行を変換するのは遅く、インデックスの使用はできません。これを回避するには

、次の2つの選択肢があります。

データベースがすべてではnvarcharを使用していない場合、あなたは、単にアプリケーションの起動時にマッピングを変更することができます。

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

をそうしないと、変更することができますクエリごとに:

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