9

Linq to SQL で大きなパフォーマンスの問題を発見しました。

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

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

var qa = q.ToArray();

パラメータは nvarchar として渡されるため、使用前にインデックス全体が varchar から nvarchar に変換されます。

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

これをオーバーライドまたは変更する方法はありますか?

よろしくクレイグ。

4

1 に答える 1

9

うーん。これは、LINQ-to-SQLのRTM以前のビルドでの既知のバグでしたが、オンラインで読んだところ、これはRTMでの同等性比較の修正された問題でした(Contains()比較ではまだ壊れています)。

とにかく、MSDNフォーラムのスレッドにいくつかの回避策の詳細があります: http ://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/4276ecd2-31ff-4cd0-82ea-7a22ce25308b

私が最も好きな回避策はこれです:

//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());

ところで、これが起こっているのを私が見た別のケースは、値の分布が奇数であるテーブル(たとえば、テーブルの50%が同じ値を持っていた)でした。つまり、プランのコンパイル時にパラメーターがSQL Serverに不明であるため、テーブルスキャンが最適でした。利用可能な計画。分布も異常な場合、スキャンは欠落している変換からではなく、パラメーター化自体から行われるため、上記の回避策は機能しません。その場合、私が知っている唯一の回避策は、OPTIMIZE FORヒントを使用し、SQLを手動で指定することです。

于 2009-11-10T02:37:54.187 に答える