¿Mejor (gratis) manera de almacenar datos? ¿Qué hay de las actualizaciones del sistema de archivos?

StackOverflow https://stackoverflow.com/questions/142114

  •  02-07-2019
  •  | 
  •  

Pregunta

Tengo una idea de cómo resolver este problema, pero quería saber si hay algo más fácil y más extensible a mi problema.

El programa en el que estoy trabajando tiene dos formas básicas de datos: imágenes y la información asociada con esas imágenes. La información asociada con las imágenes se ha almacenado previamente en una base de datos JET de extrema simplicidad (cuatro tablas) que resultó lenta e incompleta en los campos almacenados. Nos estamos moviendo a una nueva implementación de almacenamiento de datos. Dada la simplicidad de las estructuras de datos involucradas, estaba pensando que una base de datos era una exageración.

Cada imagen tendrá información propia (parámetros de captura), formará parte de un grupo de imágenes que están interrelacionadas (tomadas en el mismo período de treinta minutos, por ejemplo), y luego formará parte de un grupo más grande en conjunto (tomada de la misma persona). En este momento, estoy almacenando personas en un diccionario con un identificador único. Cada persona tiene una Lista de los diferentes grupos de imágenes y cada grupo de imágenes tiene una Lista de imágenes. Todas estas clases son serializables, y solo estoy serializando y deserializando el diccionario. Cosas bastante sencillas. Las imágenes se almacenan por separado, para que el diccionario no tenga un tamaño astronómico.

El problema es: ¿qué sucede cuando necesito agregar nuevos campos de información? ¿Existe una manera fácil de configurar estas estructuras de datos para tener en cuenta las posibles revisiones futuras? En el pasado, la forma en que manejaría esto en C era crear una estructura serializable con muchos bytes vacíos (al menos una k) para una extensibilidad futura, con uno de los bytes en la estructura que indica la versión. Luego, cuando el programa leyó la estructura, sabría qué deserialización utilizar en función de una instrucción de cambio masivo (y las versiones antiguas podrían leer datos nuevos, porque los datos extraños solo irían a los campos que se ignoran).

¿Existe tal esquema en C #? Por ejemplo, si tengo una clase que es un grupo de objetos String e Int, y luego agrego otro objeto String a la estructura, ¿cómo puedo deserializar un objeto del disco y luego agregarle la cadena? ¿Debo resignarme a tener varias versiones de las clases de datos y una fábrica que toma un flujo de deserialización y maneja la deserialización en función de la información de la versión almacenada en una clase base? ¿O es una clase como el Diccionario ideal para almacenar este tipo de información, ya que deserializará automáticamente todos los campos en el disco, y si se agregan nuevos campos, puedo capturar excepciones y sustituirlas en Cadenas e Ints en blanco para esos valores?

Si sigo con el enfoque del diccionario, ¿hay un golpe de velocidad asociado con la lectura / escritura de archivos, así como los tiempos de recuperación de parámetros? Me imagino que si solo hay campos en una clase, entonces la recuperación de campos es instantánea, pero en un diccionario, hay una pequeña sobrecarga asociada con esa clase.

¡Gracias!

¿Fue útil?

Solución

Mi cerebro está frito en este momento, por lo que no estoy seguro de poder recomendar una base de datos, pero si está buscando una serialización independiente de la versión, sería un tonto al menos no comprobar Búferes de protocolo .

Aquí hay una lista rápida de las implementaciones que conozco para C # / .NET:

Otros consejos

Sqlite es lo que desea. Es una base de datos de un solo archivo rápida e integrable que tiene enlaces a la mayoría de los idiomas.

Con respecto a la extensibilidad, puede almacenar sus modelos con atributos predeterminados y luego tener una tabla separada para las extensiones de atributos para futuros cambios.

Un año o dos más adelante, si el código aún está en uso, estará contento de que 1) Otros desarrolladores no tendrán que aprender una estructura de código personalizada para mantener el código, 2) Puede exportar, vea, modifique los datos con herramientas de base de datos estándar (hay un controlador ODBC para archivos sqlite y varias herramientas de consulta), y 3) podrá escalar hasta una base de datos con cambios mínimos de código.

Solo una pequeña palabra de advertencia, SQLLite, Protocol Buffers, mmap et al ... todo muy bien, pero debe crear un prototipo y probar cada implementación y asegurarse de que no vaya a tener los mismos problemas de perfección o diferentes cuellos de botella.

La simplicidad puede ser solo para aumentar el tamaño a SQL (Express) (puede que te sorprenda la ganancia de rendimiento) y corregir lo que falta en el diseño de la base de datos actual. Luego, si la perf aún es un problema, comienza a investigar estas otras tecnologías.

Hay un esquema de base de datos, para el cual no puedo recordar el nombre, que puede manejar este tipo de situación. Básicamente tienes dos mesas. Una tabla almacena el nombre de la variable y la otra almacena el valor de la variable. Si desea agrupar las variables, a continuación, agregue una tercera tabla que tendrá una relación de uno a muchos con la tabla de nombres de variables. Esta configuración tiene la ventaja de permitirle seguir agregando diferentes variables sin tener que seguir cambiando el esquema de su base de datos. Guardé mi tocino varias veces al tratar con departamentos que cambian de opinión con frecuencia (como Marketing).

El único inconveniente es que la tabla de valores variables necesitará almacenar el valor real como una columna de cadena (varchar o nvarchar en realidad). Luego tienes que lidiar con la molestia de convertir los valores de nuevo a sus representaciones nativas. Actualmente mantengo algo como esto. La tabla de variables actualmente tiene alrededor de 800 millones de filas. Todavía es bastante rápido, ya que todavía puedo recuperar ciertas variaciones de valores en menos de un segundo.

No soy programador de C #, pero me gusta la llamada mmap () y vi que hay un proyecto que hace algo así para C #.

Consulte Mmap

  

Los archivos estructurados tienen un gran rendimiento si se adaptan a una aplicación específica, pero son difíciles de administrar y son un recurso de código difícilmente reutilizable. Una mejor solución es una implementación similar a la memoria virtual.

     
      
  • Se pueden administrar hasta 4 gigabytes de información.
  •   
  • El espacio se puede optimizar a tamaño de datos real.
  •   
  • Todos los datos se pueden ver como una única matriz y se puede acceder a ellos con operaciones de lectura / escritura.
  •   
  • No es necesario estructurar para almacenar, solo usar y almacenar.
  •   
  • Se puede almacenar en caché.   Es altamente reutilizable.
  •   

Vaya con sqllite por las siguientes razones:
1. No necesita leer / escribir toda la base de datos desde el disco cada vez que lo haga. 2. Mucho más fácil de agregar, incluso si no deja suficientes marcadores de posición al principio
3. Más fácil de buscar según lo que quieras
4. más fácil de cambiar los datos en formas más allá de la aplicación fue diseñada

Problemas con el enfoque de diccionario
1. A menos que haya creado un diccionario inteligente, necesita leer / escribir toda la base de datos cada vez (a menos que diseñe cuidadosamente la estructura de datos, será muy difícil mantener la compatibilidad con versiones anteriores)
----- a) si no dejaste suficientes titulares adiós
2. Parece como si tuvieras que realizar una búsqueda lineal en todas las fotos para buscar en uno de los Atributos de captura
3. ¿Puede una imagen estar en más de un grupo? ¿Puede una imagen estar debajo de más de una persona? ¿Pueden dos personas estar en el mismo grupo? Con los diccionarios estas cosas pueden volverse peludas ...

Con una tabla de base de datos, si obtiene un nuevo atributo, simplemente puede decir Alter Table Picture Add Attribute DataType. Luego, mientras no establezca una regla que indique que el atributo debe tener un valor, aún puede cargar y guardar versiones anteriores. Al mismo tiempo, las versiones más nuevas pueden usar los nuevos atributos.

Además, no es necesario guardar la imagen en la base de datos. Usted podría simplemente almacenar la ruta a la imagen en la base de datos. Luego, cuando la aplicación necesite la imagen, simplemente cárguela desde un archivo de disco. Esto mantiene el tamaño de la base de datos más pequeño. Además, el tiempo adicional de búsqueda para obtener el archivo de disco probablemente sea insignificante en comparación con el tiempo para cargar la imagen.

Probablemente tu mesa debería ser
Imagen (PictureID, GroupID, File Path, Capture Parameter 1, Capture Parameter 2, etc.)

Si quieres más flexibilidad puedes hacer una tabla. CaptureParameter (PictureID, ParameterName, ParameterValue) ... No recomendaría esto porque es mucho menos eficiente que solo ponerlos en una tabla (sin mencionar las consultas para recuperar / buscar los parámetros de captura sería más complicado).

Persona (ID de persona, Atributos de cualquier persona como Nombre / Etc.)
Grupo (GroupID, Nombre del grupo, ¿ID de la persona?)
PersonGroup? (PersonID, GroupID)
PictureGroup? (GroupID, PictureID)

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