Pregunta

Anteriormente, hice la pregunta .

El problema es que las demandas de nuestra estructura de archivos son muy altas.

Por ejemplo, estamos intentando crear un contenedor con hasta 4500 archivos y datos de 500 mb.

La estructura de archivos de este contenedor consiste en

  • Base de datos SQLite (bajo 1mb)
  • archivo xml-like basado en texto
  • Imágenes dentro de una estructura de carpetas dinámica que conforman el resto de los archivos de 4,500ish

  • Después de la creación inicial, los archivos de imágenes se leen solo con la excepción de la eliminación.

  • La pequeña db se usa regularmente cuando se accede al contenedor.

Tar, Zip y los me gusta son demasiado lentos (incluso con compresión 0). Lo lento es subjetivo, lo sé, pero para descomprimir un contenedor de este tamaño es superior a 20 segundos.

¿Algún pensamiento?

¿Fue útil?

Solución

Tres cosas.

1) Lo que Timothy Walters dijo es correcto, voy a entrar en más detalles.

2) 4500 archivos y 500 Mb de datos son simplemente una gran cantidad de datos y escrituras en disco. Si está operando en todo el conjunto de datos, será lento. Sólo la verdad de E / S.

3) Como han mencionado otros, no hay detalles sobre el caso de uso.

Si asumimos un escenario de acceso aleatorio de solo lectura, lo que Timothy dice está bastante en suspenso, y la implementación es sencilla.

En pocas palabras, esto es lo que haces.

Usted concatena todos los archivos en un solo blob. Mientras los concatena, realiza un seguimiento de su nombre de archivo, la longitud del archivo y el desplazamiento que el archivo comienza dentro del blob. Usted escribe esa información en un bloque de datos, ordenados por nombre. Llamaremos a esto la Tabla de contenido o el bloque de TDC.

A continuación, a continuación, concatene los dos archivos juntos. En el caso simple, primero tiene el bloque TOC, luego el bloque de datos.

Cuando desee obtener datos de este formato, busque el TOC para el nombre del archivo, tome el desplazamiento desde el principio del bloque de datos, agregue el tamaño del bloque TOC y lea los bytes de datos FILE_LENGTH. Simple.

Si quieres ser inteligente, puedes poner la TDC al FINAL del archivo blob. Luego, agregue al final, el desplazamiento al inicio de la tabla de contenido. Luego, ve hasta el final del archivo, realiza una copia de seguridad de 4 u 8 bytes (según el tamaño de tu número), toma ese valor y busca aún más al inicio de tu tabla de contenido. Entonces vuelves a la casilla uno. Haces esto para no tener que reconstruir el archivo dos veces al principio.

Si coloca su tabla de contenido en bloques (por ejemplo, 1K byte de tamaño), entonces puede realizar fácilmente una búsqueda binaria en la tabla de contenido. Simplemente complete cada bloque con las entradas de información del archivo, y cuando se quede sin espacio, escriba un marcador, un pad con ceros y avance al siguiente bloque. Para realizar la búsqueda binaria, ya conoce el tamaño de la TDC, comience en el medio, lea el primer nombre del archivo y vaya desde allí. Pronto, encontrará el bloque, y luego leerá el bloque y lo buscará en busca del archivo. Esto lo hace eficiente para leer sin tener el TOC completo en la RAM. El otro beneficio es que el bloqueo requiere menos actividad de disco que un esquema encadenado como TAR (donde tienes que rastrear el archivo para encontrar algo).

Le sugiero que rellene los archivos para bloquear tamaños, discos como el trabajo con bloques de datos de tamaño normal, esto tampoco es difícil.

Actualizar esto sin reconstruir todo es difícil. Si desea un sistema de contenedor actualizable, también puede consultar algunos de los diseños de sistemas de archivos más simples, porque eso es lo que realmente está buscando en ese caso.

En cuanto a la portabilidad, le sugiero que almacene sus números binarios en orden de la red, ya que la mayoría de las bibliotecas estándar tienen rutinas para manejar esos detalles por usted.

Otros consejos

Como parece que está realizando operaciones de sistema de archivos arbitrarias en su contenedor (por ejemplo, creación, eliminación de nuevos archivos en el contenedor, sobrescribiendo archivos existentes, adjuntando), creo que debería buscar algún tipo de sistema de archivos. Asigne un archivo grande, luego cree una estructura de sistema de archivos en él.

Hay varias opciones disponibles para el sistema de archivos: tanto para Berkeley UFS como para Linux ext2 / ext3, hay bibliotecas en modo usuario disponibles. También podría ser posible que encuentre una implementación FAT en algún lugar. Asegúrese de comprender la estructura del sistema de archivos y elija uno que permita la extensión. Sé que ext2 es bastante fácil de extender (por otro grupo de bloques) y que FAT es difícil de extender (es necesario adjuntar a la FAT).

Como alternativa, puede colocar un formato de disco virtual aún por debajo del sistema de archivos, lo que permite la reasignación arbitraria de bloques. Entonces " libre " los bloques del sistema de archivos no necesitan aparecer en el disco, y puede asignar el disco virtual mucho más grande que el archivo contenedor real.

Suponiendo que solo necesitarás acceso de solo lectura a los archivos, ¿por qué no fusionarlos todos juntos y tener un segundo índice " " archivo (o un índice en el encabezado) que le indica el nombre del archivo, la posición inicial y la longitud. Todo lo que necesita hacer es buscar el punto de inicio y leer el número correcto de bytes. El método variará dependiendo de su idioma, pero es bastante sencillo en la mayoría de ellos.

La parte más difícil es crear tu archivo de datos + índice, ¡e incluso eso es bastante básico!

Una imagen de disco ISO podría hacer el truco. Debería poder contener tantos archivos fácilmente, y es compatible con muchas piezas de software en todos los sistemas operativos principales.

Primero, gracias por expandir tu pregunta, ayuda mucho a proporcionar mejores respuestas.

Dado que de todos modos va a necesitar una base de datos SQLite, ¿ha analizado el rendimiento de incluirlo todo en la base de datos? Mi experiencia se basa en SQL Server 2000/2005/2008, por lo que no estoy seguro de las capacidades de SQLite, pero estoy seguro de que va a ser una opción bastante rápida para buscar registros y obtener datos, a la vez que se permite la eliminación. y / u opciones de actualización.

Por lo general, no recomendaría colocar archivos dentro de la base de datos, pero dado que el tamaño total de todas las imágenes es de alrededor de 500 MB para 4500 imágenes, ¿está viendo un poco más de 100K por imagen? Si está utilizando una ruta dinámica para almacenar las imágenes, en una base de datos un poco más normalizada podría tener un " ImagePaths " tabla que asigna cada ruta a un ID, luego puede buscar imágenes con ese PathID y cargar los datos de la columna BLOB según sea necesario.

Los archivos XML también podrían estar en la base de datos SQLite, lo que le brinda un solo 'archivo de datos' para su aplicación que puede moverse entre Windows y OSX sin problemas. Simplemente puede confiar en su motor SQLite para proporcionar el rendimiento y la compatibilidad que necesita.

La forma en que lo optimices depende de su uso, por ejemplo, si con frecuencia necesita obtener todas las imágenes en una ruta determinada, entonces tener un PathID (como un entero para el rendimiento) sería rápido, pero si muestra todos imágenes que comienzan con " A " y simplemente muestre la ruta como una propiedad, entonces un índice en la columna ImageName sería más útil.

Sin embargo, estoy un poco preocupado de que esto parezca una optimización prematura, ya que realmente necesitas encontrar una solución que funcione "lo suficientemente rápido", abstraer la mecánica de la misma para tu aplicación (o ambas aplicaciones si tienes ambas Mac y PC versiones) use un repositorio simple o similar y luego puede cambiar el método de almacenamiento / recuperación a voluntad sin ninguna implicación para su aplicación.

Consulte Sistema de archivos sólidos : parece ser lo que necesita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top