Rendimiento LINQ 1 millón de registros.
-
miércoles, 22 de febrero de 2012 10:30
Buenas,<o:p></o:p>
Necesitamos cargar una tabla con más de 1 millón de registros.<o:p></o:p>
Utilizamos la forma más rápida que nos da LINQ para acceder y traer los datos. Utilizamos la clase System.Data.Linq.Table<o:p></o:p>
Esta tabla se la asignamos al datasource de un GRID y el rendimiento de visualización de datos no es muy buena que digamos (tarda de 5 a 10 segundos).
¿¿¿Existe alguna manera de cargar los datos en LINQ (Just-In-Time) es decir, bajo demanda???
Si ese acceso a datos lo tratamos con una lista de objetos (.toList()) y se lo asociamos a un BINDINGSOURCE, todavía el rendimiento es muchísimo peor...
¿¿¿Alguien tiene experiencia en cargas de grandes volúmenes de datos con LINQ???
<o:p></o:p>
I.L.
Todas las respuestas
-
miércoles, 22 de febrero de 2012 11:32
Hola,
Yo creo que el problema no es linq sino el traer 1.000.000 de registros, utilices lo que utilices siempre vas a tener retardos y posiblemente algún problema.
Porque no utilizas una paginación con linq lo puedes hacer Take y Skip mira este link
http://www.vikramlakhotia.com/Using_Take_and_Skip_method_in_LINQ_queries.aspx
Saludos,
phurtado
- Propuesto como respuesta By AlaN sábado, 21 de abril de 2012 19:12
-
miércoles, 22 de febrero de 2012 16:09
OK! Tienes razón el problema es traer 1 millon de registros, pero tenemos que hacerlo.
Tenemos que realizar un simple mantenimiento de una tabla que tiene más de 1 millon de registros.
Tenemos un grid con un filtro para que el usuario no se tenga que traer siempre todos los registros, pero si el usuario no filtra nada, deberíamos de mostrar todos los resultados.
Utilizando la tabla de LINQ (que es lo más rapido) la carga tarda mucho y además carga todos los datos en memoria que ocupan una barbaridad.
La opción de cargarlo paginado, tampoco nos sirve, ya que si el usuario decide ordenar la tabla tendríamos que volver a ir a Base de Datos.
Nos gustaría saber, si hay algúna manerá más optima de realizarlo y si alguien se ha tenido que pegar alguna vez con algún caso parecido.
Aparentemente es una solución sencilla. Aparentemente....
¿Alguien tiene experiencia con un caso tan aparentemente SENCILLO como este?
I.L.
-
jueves, 23 de febrero de 2012 8:23
Hola I.L.
La opción de cargarlo paginado, tampoco nos sirve, ya que si el usuario decide ordenar la tabla tendríamos que volver a ir a Base de Datos.
Pues ve a la bb.dd y recupera la pagina según la ordenación, otra cosa que intentes te va a ocasionar problemas siempre.
Lo siento no poder dar otra respuesta pero creo que manejar un 1.000.000 de registros en memoria no es una solución.
Saludos,
phurtado
-
jueves, 19 de abril de 2012 14:00
Hola.
Veo que este hilo no tiene respuesta y esta muerto hace ya un tiempo.
Para I.L. veo una posible solucion, y es usar un Local DataBase Cache
Tutorial: Agregar una caché de base de datos local a una aplicación de n niveles
De esta manera evitar tener que trater en cada consulta de tu servidor 1MM de registros, y solo sincronizas si haces algun cambio en la DDBB, esto lo hace de manera bidireccional y la Cache es local, asi que todos los registros que consultes son locales y solo los cambios viajen por la red.
Saludos.
-
jueves, 19 de abril de 2012 14:06
Hola,
Aumento del rendimiento en las consultas LINQ.
http://msdn.microsoft.com/es-es/magazine/cc721610.aspx
Jose Mendez.
Blog
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
Si un Post reponde a tu pregunta, por favor "Marcala como Respondida" y "Vota como útil". -
jueves, 19 de abril de 2012 23:00
Hola Jose, By Alan
Todo perfecto pero os pregunto con cualquiera de las dos soluciones podeís trabajar con un 1.000.000 de registros, vamos ni con eso ni con nada:).
La solución es paginar los datos y solicitar lo que el usuario puede ver y no hay otra.
Saludos,
-
viernes, 20 de abril de 2012 12:41
Hola Pedro.
La solucion la di en funcion de evitar los viajes de ida y vuelta al servidor a buscar informacion (1MM de registros), de hecho, la paginacion es la opcion ideal ya que dibujaria muchisimo mas rapido 10 mil registros frente a 100 mil o 1MM, tomando en cuenta que se trabajaria con copia local y luego solo se sincronizan los cambios.
Saludos.
-
viernes, 20 de abril de 2012 13:35
Hola By AlaN,
La respuesta sería "No":). Que te plantees eso en una entidad pequeña me parece perfecto. Pero piensa que usuario se va a descargar 1.000.000 de registros?, con lo cual aunque evites viajes vas a cargar la cache con 100.000 registros, piénsalo?. Para mi y ya te lo he comentado es "No".
Saludos
-
viernes, 20 de abril de 2012 14:11
Puede ser ignorancia de mi parte, pero no veo qué relevancia tiene usar System.Data.Linq.Table. Lo que sí me parece relevante es cómo y dónde almacenas tus datos y la forma como los recuperas. Asumo que estás usando Entiy Framework ¿Es así? En ese caso, estás delegando en el framework todas las decisiones en cuanto a cómo, cuándo y cuántos registros traer de la base de datos. Esto te da poco control sobre el performance de la aplicación.
Te dejo este link que te puede dar una idea: http://ahmedelbaz.com/2010/05/03/entity-framework-and-linq-to-sql-paging/
Estoy seguro que otros compañeros en el foro te pueden dar alguna indicación más precisa.
Saludos,
Y.
Si he contestado tu pregunta, por favor marca mi post como respuesta.
...Y si mi post te ha servido, márcalo como útil
-
viernes, 20 de abril de 2012 16:16
Hola By AlaN,
La respuesta sería "No":). Que te plantees eso en una entidad pequeña me parece perfecto. Pero piensa que usuario se va a descargar 1.000.000 de registros?, con lo cual aunque evites viajes vas a cargar la cache con 100.000 registros, piénsalo?. Para mi y ya te lo he comentado es "No".
Saludos
Es que a la cache que me refiero no es un repositorio comun (DataSets, DataTable o EntityFramework o una Lista en memoria), es una base de datos local (*.sdf), ya que el lo hace desde el servidor y ahi si se hacen largas la carga de trabajo para la red y el desplegar los datos en la UI. Supongo que es mejor hacerlo de manera local y por eso le sugeri ese tipo de solucion en conjunto con lo sugerido por usted, o sea, la paginacion.
PD: Si el LocalDataBase Cache tiene problemas de rendimiento.. confirmen, ya que no he leido nada al respecto, tiene varias desventajas frente a un motor de bases de datos comun, pero para ambientes conectados ocacionalmente son un hit.
Saludos.
-
sábado, 21 de abril de 2012 0:34
Hola By Alan,
Me parece una buena idea y de hecho yo lo he puesto en marcha bastantes veces:). Pero no te das cuenta que eso vale sino hay ordenación, en el momento que permitas ordenar o vas a la bb.dd donde están todos los registros por lo menos la primera vez o los datos en cache no sirven.
Esa si podría ser la solución, mezclar lo que comente yo de la paginación con este detalle para poder ordenar y solo recuperar de la bb.dd las paginas que no existan en cache. Pero recuerda en el momento que alguien cambie la ordenación o un filtro borra la cache.
Saludos,
- Propuesto como respuesta By AlaN sábado, 21 de abril de 2012 19:13
-
sábado, 21 de abril de 2012 14:10
Hola.
Exacto Pedro, se supone que se filtra la informacion y deberia ser la local y si mal no recuerdo, el problema de este tipo de DDBB es que no usan indices por su naturaleza, lo que las haria un poco mas lentas, pero dada situacion expuesta supongo que ese sacrificio se compensa evitando los viajes.
Entonces, lo recomendado seria que lo trabajara un datatable(o algo similar) enlazado a un Dataview, asi puede ordenar, paginar y cuando se apliquen los cambios estos se reflejan en la DDBB, o sea, solo a las filas que se le hicieron cambios, y cuando sincronice con el servidor solo traeria las filas que han sido modificadas desde la ultima sincronizacion, por eso hablaba de evitar los viajes innecesarios y al ser local es mucho mas rapido y con el paginado mejor ni hablemos :P.
Saludos.
-
sábado, 21 de abril de 2012 14:48
Guardar 1MM de filas en una BD sin índices puede sdr mortal, y cargarlo en en datatable con su dataview más todavía.
Yo pienso q lo mejor es paginar de todas formas, y si el usuario quiere ordenar pues se pega otro tiro.
Es posible q incluso sea más rápido pedir al servidor otras 100 filas con otro orden q ordenar 1MM de filaz en memoria si tienes bien los índices.
Yo creo q la solución es paginar y cargar las páginas bajo demanda.
Pero esto es en general, habría q analizar el caso concreto.
Xavi Paper
-
sábado, 21 de abril de 2012 17:25
Hola.
La solucion de Xavi me gusta, pero seria bueno sabir si I.L. trabaja con EF, que para trabajar con carga bajo demanda es muy comodo.
PD: Xavi, si se fija lo que digo es poner toda la info en un datatable (de forma "cruda") desde la DDBB local, luego de ahi en el dataview se juega como se quiera, y ahi entra la paginacion ;).
Saludos.
- Editado By AlaN sábado, 21 de abril de 2012 17:26 add info.
-
sábado, 21 de abril de 2012 18:58
Hola By AlaN,
Lo que yo comento no es eso, simplemente es pegar un tiro al servidor y traerse sólo una pequeña cantidad. Aquí pongo algunos motivos:
- La mayoria de veces no se ven más allà de las 20 primeras filas, por lo que cargando páginas de 100 elementos nos aseguramos acertar un porcetage muy alto de lo que necesita.
- Esto carga mucho menos la memoria de la parte cliente, ya que sólo carga unas pocas instancias y no 1.000.000 de filas.
- Cualquier sistema de caché, ya sea con una BD local, una colección estática, una caché distribuida, ... implica más código y gestionar la caducidad, enterarse de cuando los datos no están frescos.
- Las consultas al servidor son muy rápidas al cargar sólo pocas instancias, por lo que sobrecargamos poco el procesador y menos todavía la red. Con esto se mejora muchísimo en rendimiento.
- En el caso de cambiar el criterio de búsqueda u el orden, pegar un tiro continua siendo ràpido (si el índice en la BD está bien puesto), mientras que ordenar en cliente 1MM de filas puede ser una pasada. Más todavía si el cliente es un ordenador con poca potencia de cálculo o memoria, donde la caida de rendimiento puede ser muy grande.
- La gestión de ordenes, filtros, ... en un DataTable no es una buena alternativa, para mi es mucho mejor cargar la información directamente con DataReader, cargarlo en una colección y asignarla al DataSource.
- ...
Continuo pensando (salvo algunos casos muy concretos) es mucho mejor pegar de nuevo el tiro, pero ya te digo que hay que tomar tiempos del ejemplo en concreto para decir qué es mejor.
Xavi Paper
- Propuesto como respuesta By AlaN sábado, 21 de abril de 2012 19:12
-
sábado, 21 de abril de 2012 19:12
Ok, ahora si entiendo.. ahora veo el punto de pedro.
Todos dias se aprende algo nuevo :D.
Saludos.

