2011-03-10 11 views
5

El C# siguiente declaración bloquea el proceso y no puede recuperar los datos si itemToSkip es mayor que 0.LINQ Skip() Problema

int itemToSkip = 100; 
int itemToTake = 1000; 

var itemList = db.MYTABLEs.Skip(itemToSkip).Take(itemToTake).ToList(); 

¿Cómo puedo arreglar lo que? ¿Cuál es el problema?

+0

¿Funciona correctamente sin 'Skip' y/o' Take'? – Jon

+0

Sin Omitir, sí lo hace –

+0

La tabla contiene datos de 14 gb. Entonces no puedo obtenerlos a todos. Tengo que omitir y tomar –

Respuesta

8

No estoy seguro de qué proveedor tiene que proporciona db.MYTABLE. Realmente no es posible responder a su pregunta a menos que sepamos cómo se comporta db.MYTABLEs.

En LINQ normal, el salto no solo salta adelante; tiene que recorrer la cantidad de datos para saltar. Por lo tanto, para su tabla de datos de 14 gb, se repetirá a través del primer número de registros "omitidos". Si esta iteración es lenta, no está guardando ninguna CPU/tiempo omitiendo.

Para algunos proveedores, p. una fuente SQL, el salto se puede implementar usando cursores, que de nuevo pueden ser lentos. Si se trata de SQL Server, puede optimizarse con una palabra clave que puede ser más rápida.

Si es LINQ a SQL, que traduce la consulta en SQL mediante una cláusula de "no existe", que será extremadamente lenta, ya que tiene que pasar por todo el mesa si la cláusula NOT EXISTS no alcanza un índice Ver la siguiente (link):

LINQ a SQL traduce Saltar mediante el uso de una subconsulta con el SQL no cláusula EXISTS. Esta traducción tiene las siguientes limitaciones:

  • El argumento debe ser un conjunto. Las multiempadas no son compatibles, incluso si están ordenadas.

  • La consulta generada puede ser mucho más compleja que la consulta generada para la consulta base en la que se aplica el salto. Esta complejidad puede causar una disminución en el rendimiento o incluso un tiempo de espera.

En otras palabras, el doc dice "no lo hagas".

Solo para proveedores con funciones de acceso aleatorio, p. una matriz en memoria saltará muy rápido porque el proveedor puede adelantarse.

El peor caso sería si está ejecutando en un proveedor que clasifica automáticamente todo el conjunto de datos si utiliza Omitir/Tomar. Si tiene 14 gb de datos, este tipo va a ser muy lento.

Necesita experimentar un poco más para ver si su programa se cuelga en el salto, o simplemente acaparando toda la CPU que intenta iterar.

Si solo está tratando de dividir sus datos en fragmentos manejables, probablemente no debería estar usando omisión/recepción, que vuelve a consultar la fuente de datos cada vez.

3

Saltar generalmente insiste en tener un ordenamiento explícito. Pruebe

var itemList = db.MYTABLEs.OrderBy(r => r.Id).Skip(itemToSkip) 

o similar.

+0

@Rup No creo que sea el caso – msarchet

+0

Hacer un pedido de 11 millones de filas es bastante difícil :-( –

+1

@Rup: ¿por qué necesitaría un pedido? – Jon

0

Supongo que su DBMS no admite directamente la omisión y, por lo tanto, podría solicitar todos los datos, según el proveedor.

+1

¿Cree que Sql Server 2008 & System.Data.SqlClient provider y .NET 3.5 Framework pueden tener este problema? –

+0

Habla del proveedor LINQ, no del proveedor ADO.NET. Entonces, ¿está utilizando ADO.NET Entity Framework en .NET 3.5 en una base de datos MS SQL que? – Steven

+0

@Ahmet Altun: Sí, eso creo. MSSQL Server tiene un método llamado ROW_NUMBER() que numera las filas devueltas comenzando con una. Entonces, si desea devolver las filas 100000 a 100010, primero debe solicitar todas las 100010 filas. Ver por ejemplo aquí: http://stackoverflow.com/questions/187998/row-offset-in-ms-sql-server –

0

con una tabla tan grande que es posible que tarde mucho tiempo en volver, y se está demorando tanto debido a la falta de índices, necesita hacer algunos perfiles para ver la consulta subyacente, no puede diagnosticar el problema simplemente mirando el código LINQ

Cuestiones relacionadas