2009-11-09 17 views
6

He descubierto un gran problema de rendimiento en Linq a SQL.Problema nvarchar de SQL a SQL

Al seleccionar de una tabla que utiliza cadenas, los parámetros pasados ​​al servidor sql son siempre nvarchar, incluso cuando la tabla sql es varchar. Esto da como resultado exploraciones de tabla en lugar de búsquedas, un problema de rendimiento masivo.

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

var qa = q.ToArray(); 

el parámetro se pasa a través de como nvarchar, lo que resulta en todo el índice que se convierte de varchar a nvarchar antes de ser utilizados.

Si el parámetro es un varchar es una búsqueda muy rápida.

¿Hay alguna manera de anular o cambiar esto?

Gracias Saludos Craig.

+0

¿Cómo es tu DBML? – RobS

+0

Es una columna varchar, no una columna nvarchar. create table test (prueba varchar (200) not null) create index ixtest on test (test) – Craig

+0

El plan de consulta de la base de datos usa CONVERT_IMPLICIT y un escaneo en lugar de una búsqueda. Creo que es un problema común de LINQ to SQL. Estoy buscando una solución que permita que los parámetros se especifiquen correctamente. varchar (200) en cambio en nvarchar (4) que da como resultado la conversión. – Craig

Respuesta

8

Hmmm. Este era un error conocido con versiones previas a RTM de LINQ-to-SQL, pero por lo que leí en línea, este fue un problema fijo para las comparaciones de igualdad en RTM (aunque todavía está roto para las comparaciones de Contiene()).

De todos modos, aquí hay un hilo en los foros de MSDN con algunas soluciones detalladas: http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/4276ecd2-31ff-4cd0-82ea-7a22ce25308b

La solución que más me gusta es ésta:

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

Por cierto, otro caso vi que esto ocurra se encontraba en una tabla con una distribución impar de valores (por ejemplo, el 50% de la tabla tenía el mismo valor), lo que significa que, dado que el SQL Server desconoce el parámetro en el momento de la compilación, el mejor plan disponible era un escaneo de tabla. Si su distribución también es inusual, las soluciones anteriores no funcionarán, ya que el escaneo no vendrá de la conversión faltante sino de la parametrización misma. En ese caso, la única solución que conocería sería usar una sugerencia de OPTIMIZE FOR y especificar manualmente el SQL.

+0

+1 .. :) aquí hay otro hilo msdn, también con algunas soluciones alternativas: http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/20d456f0-9174-4745-bbc5-571f68879e27 – KristoferA

+0

Gracias. Me di cuenta de que es un problema solo con contains. Pensé que era más amplio al principio. – Craig

Cuestiones relacionadas