2010-02-09 16 views
8

no pude encontrar un buen título para la cuestión, esto es lo que estoy tratando de hacer:La mejor manera de almacenar muchos archivos en el disco

  • Esta es la aplicación .NET.
  • necesito para almacenar hasta 200000 objetos (entre 3 KB-500 KB)
  • I necesidad de almacenar unos 10 de ellos por segundo desde-múltiples hilos
  • utilizo binaryserialization antes de almacenarlo
  • Necesito acceso más tarde por un entero, ID único

¿Cuál es la mejor manera de hacerlo?

  • no puedo mantenerlos en la memoria como voy a conseguir excepciones OutOfMemory
  • Cuando los almacena en el disco como archivos separados Cuáles son los posibles problemas de rendimiento? ¿Disminuiría mucho el rendimiento general?
  • Debo implementar algún tipo de almacenamiento en caché, por ejemplo, combinar 100 objetos y escribirlo una vez como un archivo. Luego analizarlos más tarde. ¿O algo similar?
  • ¿Utilizará una base de datos? (El tiempo de acceso no es importante, no habrá búsqueda y solo accederé un par de veces con el ID exclusivo conocido). En teoría, no necesito una base de datos, no quiero complicar esto.

ACTUALIZACIÓN:

  • Asumo base de datos sería más lento que el sistema de archivos, demostrar que estoy equivocado si tiene algo de eso. Entonces es por eso que también me inclino por el sistema de archivos. Pero lo que realmente me preocupa es escribir 200KB * 10 por segundo en HDD (esto puede ser cualquier HDD, no controlo hardware, es una herramienta de escritorio que se implementará en diferentes sistemas).
  • Si uso del sistema de archivos que voy a almacenar los archivos en carpetas separadas para evitar problemas relacionados con el sistema de archivos (por lo que puede pasar por alto que la limitación)
+0

es el ID único que nos brinda, o tenemos para generarlo? Si tenemos que generarlo, no lo necesitan para sobrevivir reinicios del sistema? –

+0

identificación única ya está a cargo de un proporcionada, no es necesario que viva después del reinicio. Solo se requiere durante la ejecución de la aplicación. –

+0

Tenga en cuenta que es una tontería, pero vea: http://stackoverflow.com/questions/2230032/which-is-a-better-method-for- storage-images-folder-or-sql-server-as-binary –

Respuesta

3

Si desea evitar el uso de una base de datos, puede almacenarlos como archivos en el disco (para hacerlo más simple).Pero debe tener en cuenta las consideraciones del sistema de archivos cuando mantiene una gran cantidad de archivos en un solo directorio.

Muchos sistemas de archivos comunes mantienen sus archivos por directorio en algún tipo de lista secuencial (por ejemplo, simplemente almacena punteros de archivo o inodos uno después del otro, o en listas vinculadas). Esto abre archivos que se encuentran en la parte inferior de la lista realmente lento.

Una buena solución es limitar su directorio a una pequeña cantidad de nodos (digamos n = 1000) y crear un árbol de archivos debajo del directorio.

Así que en lugar de almacenamiento de archivos como:

/dir/archivo1/dir/archivo2/dir/archivo3 .../dir/archivoN

guardarlas como:

/dir/r1/s2/archivo1/dir/r1/s2/archivo2 .../dir/rM/sN/archivoP

Al dividir sus archivos de esta manera, mejora significativamente el tiempo de acceso en la mayoría de los sistemas de archivos.

(Tenga en cuenta que hay algunos nuevos sistemas de ficheros que representan los nodos en árboles u otras formas de indexación. Esta técnica funcionará tan bien en los mismos.)

Otras consideraciones están sintonizando su sistema de archivos (tamaños de bloque, el particionamiento, etc. .) y su caché de búfer para que obtenga una buena localidad de datos. Dependiendo de su sistema operativo y sistema de archivos, hay muchas maneras de hacerlo: probablemente necesite buscarlos.

Alternativamente, si esto no funciona, puede utilizar algún tipo de base de datos incrustada como SQLlite o Firebird.

HTH.

+0

No controlo el hardware, así que puede ser cualquier cosa, desde un disco duro horrible con FAT32 (poco probable pero posible) hasta un RAID. El sistema operativo siempre es Windows, aunque esto es .NET en Windows, no tiene elementos mono. –

+0

@dr. evil: creo que en caso de un "disco duro horrible" incapaz de almacenar 2MB/seg, cualquier solución, incluido DMBS, fallará, simplemente porque cualquier DBMS agrega su propia sobrecarga al almacenar datos. –

+0

Esta es una idea terrible; Intenté algo así y es poco práctico incluso en sistemas de archivos modernos como ext4. La mayoría de los FS se ahogarán si pones más gracias a los archivos 8k en 8k dir. Mi configuración tenía un hash de cada archivo y lo ponía en una estructura dir como img/a412/8cdf/e9k4/rest_of_hash.png y básicamente me mataba porque (a) me quedaba sin inodos, (b) mataba todos los archivos de arrastre debido a miles de directorios y (c) toneladas de espacio de disco extra usado porque cada directorio es 4096k, incluso si mis imágenes son 2k. El almacenamiento del sistema de archivos para cosas como esta es una MALA IDEA para soluciones a gran escala. – Nthalk

2

estaría tentado a usar una base de datos, en C++ ya sea sqlite o coucheDB.
Ambos funcionarían en .Net pero no sé si existe una mejor alternativa específica para .Net.

Incluso en sistemas de archivos que pueden manejar 200.000 archivos en un directorio que tomará para que nunca para abrir el directorio

Editar - La base de datos será probablemente más rápido!
El sistema de archivos no está diseñado para un gran número de objetos pequeños, el DB sí lo está.
Implementará todo tipo de estrategias ingeniosas de caché/transacción que nunca pensaste.

Hay sitios de fotos que eligen el sistema de archivos en una base de datos. Pero en su mayoría hacen lecturas en blobs bastante más grandes y tienen muchos administradores que son expertos en ajustar sus servidores para esta aplicación específica.

+0

¿Hay alguna ventaja de rendimiento de cualquier base de datos? Supongo que será más lento, si lo hay, cuál es la ventaja sobre el sistema de archivos (suponiendo que agruparé los archivos 1000 por carpeta en el sistema de archivos, lo cual resuelve abrir el problema del directorio fácilmente). –

1

puede consultar mongoDb, es compatible con los archivos de la tienda.

+0

¿Hay alguna ventaja de rendimiento de MongoDB? Supongo que será más lento, si es la ventaja sobre el sistema de archivos (suponiendo que agrupe archivos 1000 por carpeta en el sistema de archivos) –

0

La única forma de saberlo con certeza es conocer más acerca de su escenario de uso.

Por ejemplo, ¿el uso posterior de los archivos los necesitará en grupos de 100 archivos a la vez? Tal vez si lo tuviera, tendría sentido combinarlos.

En cualquier caso, trataría de hacer una solución simple para empezar, y solo cámbiela si luego encuentra que tiene un problema de rendimiento.

Esto es lo que yo haría:

  1. hacer una clase que se encarga del almacenamiento y recuperación (para que pueda más tarde en el cambio de esta clase, y no todos los puntos de la aplicación que lo utiliza)
  2. Almacene los archivos en el disco como está, no los combine
  3. Extiéndalos en subdirectorios, manteniendo 1000 o menos archivos en cada directorio (el acceso al directorio agrega sobrecarga si tiene muchos archivos en un único directorio)
+0

el escenario de uso es claro como se explica en la pregunta, el uso posterior no es importante en absoluto, Solo accederé a ella de 0 a 10 veces, y necesito acceder por ID. No importa cuánto tiempo dura apenas 15-30 segundos. –

0

En realidad, no uso .NET, así que no estoy seguro de qué es fácil, pero en general ofrezco dos consejos.

Si necesita escribir mucho y leer raramente (por ejemplo, archivos de registro), debe crear a.archivo zip o similar (elija un nivel de compresión que no disminuya demasiado el rendimiento; en la calificación de 1 a 9, 5 o más suelen funcionar para mí). Esto le brinda varias ventajas: no golpea el sistema de archivos con tanta fuerza, su espacio de almacenamiento se reduce y naturalmente puede agrupar archivos en bloques de 100 o 1000 o lo que sea.

Si necesita escribir mucho y leer mucho, se podría definir su propio formato de archivo plano (a menos que tenga acceso a los servicios públicos para leer y escribir archivos .tar o similares, o engañar y poner los datos binarios en un TIFF de 8 bits en escala de grises). Defina registros para cada encabezado, tal vez 1024 bytes cada uno que contenga el desplazamiento en el archivo y el nombre del archivo y cualquier otra cosa que necesite almacenar, y luego escriba los datos en fragmentos. Cuando necesite leer un fragmento, primero lea el encabezado (tal vez 100k) y luego salte al desplazamiento que necesita y lea la cantidad que necesita. La ventaja de los encabezados de tamaño fijo es que puede escribir datos vacíos al principio y luego seguir agregando cosas nuevas al final del archivo y luego volver atrás y sobrescribir el registro correspondiente.

Finalmente, es posible que vea algo como HDF5; No sé para qué sirve el soporte de .NET, pero es una buena forma de almacenar datos genéricos.

0

Puede considerar el uso del Bloque de aplicaciones de almacenamiento en caché de Microsoft. Puede configurarlo para utilizar IsolatedStorage como un almacén de respaldo, de modo que los elementos en el caché se serializarán en el disco. El rendimiento puede ser un problema: creo que, de manera automática, bloquea las escrituras, por lo que es posible que deba modificarlo para que haga las escrituras asíncronas.

0

en su caso memchached puede cubrir algunos problemas de rendimiento.

2

Recomiendo hacer una clase que tenga una única cola con hilos para volcar imágenes (gzip) al final de un archivo y luego guardar los archivos de desplazamiento/metainformación en una pequeña base de datos como sqlite. Esto le permite almacenar todos sus archivos de forma rápida y segura desde múltiples hilos, y volver a leerlos, de manera eficiente y sin tener que lidiar con ninguna peculiaridad del sistema de archivos (que no sea el máximo tamaño de archivo, que puede solucionarse con algunos metadatos adicionales).

File: 
file.1.gzipack 

Table: 
compressed_files { 
    id, 
    storage_file_id, 
    storage_offset, 
    storage_compressed_length, 
    mime_type, 
    original_file_name 
} 
Cuestiones relacionadas