2010-03-26 16 views
9

Estoy trabajando con una base de datos bastante grande de mysql (varios millones de filas) con una columna que almacena imágenes de blobs. La aplicación intenta tomar un subconjunto de las imágenes y ejecuta algunos algoritmos de procesamiento sobre ellas. El problema al que me estoy enfrentando es que, debido al gran conjunto de datos que tengo, el conjunto de datos que devuelve mi consulta es demasiado grande para almacenarlo en la memoria.Tratando con enormes resultados de SQL

Por el momento, he cambiado la consulta para no devolver las imágenes. Al iterar sobre el conjunto de resultados, ejecuto otra selección que toma la imagen individual que se relaciona con el registro actual. Esto funciona, pero las decenas de miles de consultas adicionales han resultado en una disminución del rendimiento que es inaceptable.

Mi próxima idea es limitar la consulta original a 10.000 resultados más o menos, y luego seguir consultando por tramos de 10.000 filas. Esto parece el compromiso a medio camino entre los dos enfoques. Siento que probablemente haya una mejor solución de la que no tengo conocimiento. ¿Hay alguna otra manera de tener porciones de un conjunto de resultados gigantesco en la memoria a la vez?

Saludos,

de Dave McClelland

+0

Quizás mis problemas de memoria no sean causados ​​por la consulta. Volví a una versión anterior (gracias, control de versión), y el lector de datos parece estar cargando solo la fila que está leyendo actualmente, como menciona Anthony. Aún así, me pregunto si no tiene más sentido mantener las imágenes en el sistema de archivos local en lugar de transferirlas a través de la red desde el servidor de bases de datos (como lo menciona ProphetBeal a continuación). El inconveniente es que se almacenará en ambas ubicaciones (deben permanecer en la base de datos para el uso de otros sistemas), pero el espacio de almacenamiento del sistema de archivos no es una preocupación inmediata. ¿Alguna idea sobre esto? –

+0

Le doy la respuesta a Anthony porque señaló que el DataReader no es la razón por la que mi memoria se estaba llenando (era algo relacionado, pero ligeramente diferente). Probablemente voy a usar la solución de ProphetBeal de mantener los BLOB en la máquina local para eliminar la congestión de la red, pero para cualquier persona que maneje un conjunto de datos grande para almacenar en la máquina local, un DataReader debería ser una solución efectiva. –

Respuesta

3

Una opción es utilizar un DataReader. Transmite los datos, pero es a costa de mantener una conexión abierta a la base de datos. Si está iterando sobre varios millones de filas y realizando el procesamiento para cada una, puede que no sea deseable.

Creo que se dirige por el camino correcto de capturar los datos en fragmentos, probablemente utilizando el método de límite de MySql, ¿correcto?

+0

Sí, había planeado usar el límite de SQL. –

+0

Además, ya estoy usando un DataReader para almacenar los resultados (usando OdbcCommand.ExecuteReader() luego iterando con while (datareader.Read()). Parece que no se transmite de manera muy efectiva ya que aún estaba llenando toda la memoria disponible del sistema ¿Hay algún uso de lectores de datos del que no tengo conocimiento? –

+0

@Dave, es posible que alguien más pueda ofrecer información sobre el uso específico de la memoria del lector de datos, pero entiendo que solo debe tener un registro en la memoria en un momento dado. En cualquier caso, debería requerir muchos menos recursos de memoria que un DataSet o DataTable. Sus problemas de memoria podrían ser el resultado de lo que está haciendo con los datos una vez que los haya recuperado, cuánto tiempo estará mantener esos objetos en el alcance, etc. –

1

Cuando se trata de este tipo de grandes conjuntos de datos, es importante que no se necesita tener todo en la memoria a la vez. Si está escribiendo el resultado en un disco o en una página web, hágalo a medida que lee en cada fila. No espere hasta haber leído todas las filas antes de comenzar a escribir.

También podría haber configurado las imágenes en DelayLoad = true para que solo se obtengan cuando las necesite en lugar de implementar esta funcionalidad usted mismo. Ver here para más información.

+0

Debería haber mencionado, estoy (actualmente) usando ADO.NET. ¿Hay un equivalente a DelayLoad? Podría migrar a Linq, pero preferiría no hacerlo. Actualizaré las etiquetas de pregunta. Además, no estoy escribiendo los resultados en ninguna parte. Estoy ejecutando algunos algoritmos de análisis de imágenes en los resultados para compararlo con una imagen pasada a la función. Como resultado, solo necesito almacenar la mejor imagen y puedo ignorar el resto. ¡Gracias por la rápida respuesta! –

0

Veo 2 opciones.

1) si se trata de una aplicación de Windows (a diferencia de una aplicación web) puede leer cada imagen con un lector de datos y volcar el archivo en una carpeta temporal en el disco, luego puede hacer cualquier procesamiento que necesite contra el archivo físico.

2) Lea y procese los datos en trozos pequeños. Las filas de 10k pueden ser mucho dependiendo de qué tan grandes sean las imágenes y cuánto proceso quieras hacer. Si recuperas 5k de filas por vez y lees más en un hilo separado cuando tienes 1k restante por procesar, puedes lograr un proceso sin interrupciones.

Además, aunque no siempre se recomienda, forzar la recolección de basura antes de procesar el siguiente conjunto de filas puede ayudar a liberar memoria.

0

He utilizado una solución como uno descrito en este tutorial antes: http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/data-access/tutorial-25-cs.aspx

Usted podría utilizar múltiples hilos comprobar la validez de tirar de una parte de las próximas series de datos (en un primer momento y en tirar de 1-10.000 el fondo extrae 10,001 - 20,000 y 20,001-30,000 filas, y borre las páginas anteriores de los datos (digamos que si está en 50,000 a 60,000 borre las primeras 1-10,000 filas para conservar la memoria si eso es un problema). Y use las ubicación de la "página" actual como un puntero para extraer el siguiente rango de datos o eliminar algunos datos fuera de rango.