microsoft manager emulator azcopy design-patterns database-design azure

design patterns - manager - ¿Cómo guardo adecuadamente las relaciones de datos con Microsoft Azure Table Storage?



download azcopy on windows (2)

Viniendo de un mundo Relacional, las cosas son obviamente muy diferentes con el almacenamiento de Azure Table. La primera gran cosa con la que me he encontrado es cómo almacenar correctamente las relaciones de muchos a muchos.

Por ejemplo, puedo tener un sistema que realiza un seguimiento de los usuarios y libros que poseen. Encontré otra publicación aquí en SO que sugería tener una propiedad de cadena en el usuario que básicamente almacenaba una lista de las identificaciones de libros que poseía el usuario. Si bien entiendo que a veces esta es una forma aceptada de almacenar datos, el problema es que Azure solo le permite almacenar 64 KB de datos en una Cadena. Eso definitivamente pone un límite a la cantidad de libros que un usuario podría poseer.

Otra posible solución es tener datos duplicados. Es posible que tenga una tabla que almacena todos los libros conocidos en el sistema. Pero cuando un usuario necesita estar asociado con un libro, copio los datos del libro en una tabla diferente llamada OwnedBooks que, en esencia, es exactamente igual a la tabla de libros, excepto que también tiene una propiedad OwnedByUserID.

¿Hay otras soluciones posibles?

Además de este problema, ¿alguien tiene alguna buena sugerencia para otros patrones y prácticas al usar el almacenamiento de tablas Azure?


Hay una serie de soluciones para esto, todas con inconvenientes, por supuesto :-)

  1. Use una tabla de asignación simple como lo haría en un RDBMS. Cada fila contendría una tecla Libro y una tecla Usuario.

    Luego, para buscar todos los libros para un usuario, debe seleccionar las teclas del libro en la tabla de asignación y luego, para cada una de esas teclas, seleccionar la entidad Libro de la tabla Libros. Podrías hacer las recuperaciones de libros en paralelo usando la recuperación asíncrona, pero aun así, esta solución obviamente no escala.

  2. Use una tabla de asignación como la anterior, pero incluya todos los datos del Libro que necesite en la tabla de asignación también. Esta es la solución denormalizada o de "datos duplicados" que ya ha propuesto con su tabla de OwnedBooks.

    El inconveniente principal de este método es que si necesita actualizar alguno de los datos del Libro, potencialmente estará actualizando muchas entidades, y como viven en una tabla separada del Libro mismo, no podrá completarse en una sola transacción / lote (y me imagino que usaría la identidad del Usuario como la clave de Partición en la tabla de asignación de todos modos, lo que ya impide una actualización por lotes única en esa tabla).

  3. Almacene las claves del Libro unidas en una sola propiedad del Usuario. De nuevo, ya sugirió este método.

    En realidad, esto no sería tan malo si no fuera por el hecho de que Azure no admite actualmente consultas de tipo "contiene", es decir, no puede buscar en una subcadena, por lo que si alguna vez desea saber qué usuarios poseía un Libro en particular, esto sería imposible. Curiosamente, Google App Engine admite esto de forma bastante transparente en su sistema de almacenamiento, e indexará la lista también para usted. En cualquier caso, igual tendrá que recuperar los datos de cada libro con este método también.

  4. Utilice la naturaleza "sin esquema" del almacenamiento de tabla de Azure para almacenar claves de libro asociadas como propiedades individuales. Por ejemplo, una entidad de Usuario puede verse así:

    { Name: "User1", Book_4325: true, Book_5123: true }

    Mientras que otro puede verse así:

    { Name: "User2", Book_5346: true, Book_8753: true, Book_6135: true }

    Entonces, si desea buscar todos los Usuarios que poseen un Libro en particular, puede seleccionar dónde esa propiedad en particular es verdadera (bueno, solo necesita existir en realidad).

    Los inconvenientes obvios de esto son que es un poco frágil, necesita manipular las claves en los nombres de las propiedades, y no podría usar los métodos estándar de StorageClient para esto; tendría que hacer las suyas propias. Además, Azure solo admite 255 propiedades en una entidad. Dicho todo esto, creo que se escalaría bastante bien, aunque nunca lo intenté.

De todas estas opciones, diría que la que elegiría, la opción 2, sería la mejor, solo por el hecho de que actualmente es compatible con Azure y normalmente puede lograr todo con menos consultas.

Solo necesita analizar sus Casos de uso para decidir cómo y cuándo se actualizarían los datos, teniendo en cuenta que las transacciones atómicas están fuera de la ventana. Casi puedo garantizarle que podrá vivir con cosas "eventualmente consistentes" y solo dar cuenta del hecho de que su tabla de mapeo puede no estar siempre 100% actualizada.

Si resulta demasiado costoso actualizar los datos en la tabla de asignación al mismo tiempo que la tabla principal, puede colocar un mensaje en una cola y obtener un rol de trabajador para realizar las actualizaciones de forma asincrónica.