9

我在 Linq to SQL 中发现了一个巨大的性能问题。

当使用字符串从表中选择时,传递给 sql server 的参数始终是 nvarchar,即使 sql 表是 varchar。这会导致表扫描而不是搜索,这是一个巨大的性能问题。

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 回答