2009-11-09 42 views
6

私はLinqからSQLへの巨大なパフォーマンスの問題を発見しました。LinqからSQLへのnvarcharの問題

文字列を使用してテーブルから選択する場合、SQL Serverに渡されるパラメータは、SQLテーブルがvarcharの場合でも常にnvarcharです。この結果、シークの代わりにテーブルスキャンが発生し、パフォーマンス上の大きな問題になります。

var q = (
    from a in tbl 
    where a.index == "TEST" 
    select a) 

var qa = q.ToArray(); 

パラメータが使用される前にはnvarcharするVARCHARから変換された全体指標になるNVARCHARとして通過させます。

パラメータがvarcharの場合、非常に高速なシークです。

これを上書きまたは変更する方法はありますか?

ありがとうございました よろしくお願いします。 Craig。

+0

あなたのDBMLはどのように見えますか? – RobS

+0

これはvarcharカラムであり、nvarcharカラムではありません。 create table test(test varchar(200)not null) テストでインデックスixtestを作成します。 – Craig

+0

データベースクエリプランは、シークの代わりにCONVERT_IMPLICITとスキャンを使用します。私はこれがLINQ to SQLの一般的な問題だと思う。 パラメータを正しく指定できる回避策を探しています。代わりにvarchar(200)をnvarchar(4)に変換します。 – Craig

答えて

8

Hmmm。これは、RTM以前のLINQ-to-SQLビルドの既知のバグでしたが、私がオンラインで読んだところでは、これはRTMの等価比較の固定問題でした(Contains()比較ではまだ解消されていますが)。 http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/4276ecd2-31ff-4cd0-82ea-7a22ce25308b

私が一番好きな回避策はこの1つである:

//define a query 
IQueryable<Employee> emps = from emp in dc2.Employees where emp.NationalIDNumber == "abc" select emp; 

//get hold of the SQL command translation of the query... 
System.Data.Common.DbCommand command = dc2.GetCommand(emps); 

//change param type from "string" (nvarchar) to "ansistring" (varchar) 
command.Parameters[0].DbType = DbType.AnsiString; 
command.Connection = dc2.Connection; 

//run 
IEnumerable<Employee> emps2 = dc2.Translate<Employee>(command.ExecuteReader()); 

ところで、私が見た別のケースは、この出来事がでた

にかかわらず、ここでいくつかの回避策は、詳細なとMSDNフォーラムのスレッドです(テーブルの50%が同じ値を持っていました)、プランのコンパイル時にパラメータがSQL Serverに認識されていない場合、テーブルスキャンが利用可能な最良のプランであることを意味します。あなたの流通が珍しい場合は、上記の回避策は機能しません。なぜならスキャンは欠落した変換からではなく、パラメータ化自体から来るからです。その場合、OPTIMIZE FORヒントを使用して手動でSQLを指定することが私が知っている唯一の回避策です。

+0

+1 .. :)ここに別の回避策がある別のmsdnスレッドがあります。 http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/20d456f0-9174-4745-bbc5-571f68879e27 – KristoferA

+0

ありがとうございます。 私はそれが含まれているだけの問題であることを認識しました。最初はもっと広いと思った。 – Craig