2009-11-09 105 views
6

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

从表中选择使用字符串时,传递给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,它是一个非常快的搜索。

有什么办法可以覆盖或改变它?

谢谢 Registers Craig。

+0

你的DBML是什么样的? – RobS 2009-11-09 06:44:12

+0

它是一个varchar列,不是nvarchar列。 创建表测试(测试varchar(200)非空) 在测试(测试)上创建索引ixtest – Craig 2009-11-09 07:18:20

+0

数据库查询计划使用CONVERT_IMPLICIT和扫描而不是查找。我认为这是一个常见的LINQ to SQL问题。 我正在寻找一种可以正确指定参数的解决方法。 varchar(200)而不是nvarchar(4)导致转换。 – Craig 2009-11-09 07:20:10

回答

8

嗯。这是一个使用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()); 

BTW,我看到了另一种情况下发生这种情况是在一个表格中有奇数分布的值(例如表格的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 2009-11-10 03:10:20

+0

谢谢。 我已经意识到这只是包含的问题。起初我认为它更广泛。 – Craig 2009-11-17 08:24:56