2009-11-09 15 views
6

Odkryłem ogromny problem z wydajnością w Linq do SQL.Problem z Linq na SQL nvarchar

Podczas wybierania z tabeli za pomocą ciągów parametry przekazywane do serwera sql są zawsze nvarchar, nawet jeśli tabela sql jest varcharem. Powoduje to skanowanie tabeli zamiast poszukiwań, ogromny problem z wydajnością.

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

var qa = q.ToArray(); 

Parametr przepuszcza się jako nvarchar, co powoduje, że cały wskaźnik jest przekształcany z VARCHAR nvarchar przed użyciem.

Jeśli parametr jest varchar, jest to bardzo szybkie wyszukiwanie.

Czy istnieje sposób, aby to zmienić lub zmienić?

Dzięki Pozdrawiam Craig.

+0

Jak wygląda Twój DBML? – RobS

+0

To jest kolumna varchar, a nie kolumna nvarchar. utwórz test tabeli (test varchar (200) nie ma wartości null) utwórz indeks ixtest w teście (test) – Craig

+0

Plan kwerend baz danych używa CONVERT_IMPLICIT i skanowania zamiast przeszukiwania. Myślę, że jest to typowy problem LINQ to SQL. Szukam obejścia, które pozwoli poprawnie określić parametry. varchar (200) zamiast na nvarchar (4), który powoduje konwersję. – Craig

Odpowiedz

8

Hmmm. Był to znany błąd związany z kompilacją LINQ-SQL w wersjach wcześniejszych niż RTM, ale z tego, co czytałem w Internecie, wynikało to ze stałego problemu z porównywaniem równości w RTM (chociaż nadal nie działa w przypadku porównań Contains()).

Niezależnie, tutaj jest wątek na forach MSDN ze niektóre obejścia Szczegółowe: http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/4276ecd2-31ff-4cd0-82ea-7a22ce25308b

Obejście lubię najbardziej jest to jedno:

//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, kolejny przypadek Widziałem to dzieje się w sposób tabela z nieparzystym rozkładem wartości (np. 50% tabeli miało tę samą wartość), co oznacza, że ​​biorąc pod uwagę, że parametr nie jest znany SQL Server w czasie kompilacji planu, najlepszym dostępnym planem było skanowanie tabeli. Jeśli twoja dystrybucja jest również niezwykła, powyższe rozwiązania nie będą działać, ponieważ skanowanie nie będzie pochodzić z brakującej konwersji, ale raczej z samej parametryzacji. W takim przypadku jedynym obejściem byłoby użycie OPTIMIZE FOR Hint i ręczne określenie SQL.

+0

+1 .. :) Oto kolejny wątek msdn, również z alternatywnymi obejściami: http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/20d456f0-9174-4745-bbc5-571f68879e27 – KristoferA

+0

Dzięki. Zdałem sobie sprawę, że jest to problem tylko z zawiera. Myślałem, że na początku było to szersze. – Craig