Estoy implementando el siguiente modelo para almacenar datos relacionados con el usuario en mi tabla (tengo 2 columnas) uid
(clave principal) y una meta
columna que almacena otros datos sobre el usuario en formato JSON.
uid | meta
--------------------------------------------------
1 | {name:['foo'],
| emailid:['[email protected]','[email protected]']}
--------------------------------------------------
2 | {name:['sann'],
| emailid:['[email protected]','[email protected]']}
--------------------------------------------------
Es esta una manera mejor (en cuanto al rendimiento, diseño inteligente) que el modelo de una columna-por-propiedad, donde la mesa tendrá tantas columnas como uid
, name
, emailid
.
Lo que me gusta del primer modelo es que puede agregar tantos campos como sea posible, no hay limitación.
Además, me preguntaba, ahora que he implementado el primer modelo. ¿Cómo realizo una consulta en él, como, quiero buscar a todos los usuarios que tienen nombre como 'foo'?
Pregunta : ¿Cuál es la mejor manera de almacenar datos relacionados con el usuario (teniendo en cuenta que el número de campos no es fijo) en la base de datos usando - JSON o columna por campo? Además, si se implementa el primer modelo, ¿cómo consultar la base de datos como se describió anteriormente? ¿Debo usar ambos modelos, almacenando todos los datos que pueden ser buscados por una consulta en una fila separada y los otros datos en JSON (es una fila diferente)?
Actualizar
Dado que no habrá demasiadas columnas en las que deba realizar la búsqueda, ¿es aconsejable utilizar ambos modelos? ¿Clave por columna para los datos que necesito buscar y JSON para otros (en la misma base de datos MySQL)?
fuente
Respuestas:
Actualizado 4 de junio de 2017
Dado que esta pregunta / respuesta ha ganado cierta popularidad, pensé que valía la pena una actualización.
Cuando esta pregunta se publicó originalmente, MySQL no tenía soporte para los tipos de datos JSON y el soporte en PostgreSQL estaba en su infancia. Desde 5.7, MySQL ahora admite un tipo de datos JSON (en un formato de almacenamiento binario), y PostgreSQL JSONB ha madurado significativamente. Ambos productos proporcionan tipos JSON con rendimiento que pueden almacenar documentos arbitrarios, incluido el soporte para indexar claves específicas del objeto JSON.
Sin embargo, aún mantengo mi afirmación original de que su preferencia predeterminada, cuando usa una base de datos relacional, aún debe ser columna por valor. Las bases de datos relacionales todavía se basan en el supuesto de que los datos dentro de ellas estarán bastante bien normalizados. El planificador de consultas tiene mejor información de optimización al mirar columnas que al mirar claves en un documento JSON. Las claves externas se pueden crear entre columnas (pero no entre claves en documentos JSON). Importante: si la mayoría de su esquema es lo suficientemente volátil como para justificar el uso de JSON, es posible que desee al menos considerar si una base de datos relacional es la opción correcta.
Dicho esto, pocas aplicaciones son perfectamente relacionales u orientadas a documentos. La mayoría de las aplicaciones tienen una mezcla de ambos. Aquí hay algunos ejemplos en los que personalmente he encontrado que JSON es útil en una base de datos relacional:
Al almacenar direcciones de correo electrónico y números de teléfono para un contacto, donde almacenarlos como valores en una matriz JSON es mucho más fácil de administrar que varias tablas separadas
Guardar preferencias arbitrarias de usuario de clave / valor (donde el valor puede ser booleano, textual o numérico, y no desea tener columnas separadas para diferentes tipos de datos)
Almacenar datos de configuración que no tienen un esquema definido (si está creando Zapier o IFTTT y necesita almacenar datos de configuración para cada integración)
Estoy seguro de que también hay otros, pero estos son solo algunos ejemplos rápidos.
Respuesta original
Si realmente desea poder agregar tantos campos como desee sin limitación (aparte de un límite de tamaño de documento arbitrario), considere una solución NoSQL como MongoDB.
Para bases de datos relacionales: use una columna por valor. Poner un blob JSON en una columna hace que sea prácticamente imposible realizar consultas (y muy lento cuando realmente encuentra una consulta que funciona).
Las bases de datos relacionales aprovechan los tipos de datos al indexar, y están destinadas a implementarse con un sistema normalizado. estructura .
Como nota al margen: esto no quiere decir que nunca debe almacenar JSON en una base de datos relacional. Si está agregando metadatos verdaderos, o si su JSON está describiendo información que no necesita consultarse y solo se usa para mostrar, puede ser excesivo crear una columna separada para todos los puntos de datos.
fuente
virtually impossible to query
" - hoy psql le permite buscar e indexar su jsonb"For relational databases"
en su respuesta = PComo la mayoría de las cosas "depende". No es correcto o incorrecto / bueno o malo en sí mismo almacenar datos en columnas o JSON. Depende de lo que necesite hacer más tarde. ¿Cuál es su forma prevista de acceder a estos datos? ¿Necesitará hacer referencia cruzada a otros datos?
Otras personas han respondido bastante bien cuáles son las compensaciones técnicas.
No muchas personas han discutido que su aplicación y características evolucionan con el tiempo y cómo esta decisión de almacenamiento de datos afecta a su equipo.
Debido a que una de las tentaciones de usar JSON es evitar la migración del esquema y, por lo tanto, si el equipo no es disciplinado, es muy fácil pegar otro par clave / valor en un campo JSON. No hay migración para ello, nadie recuerda para qué sirve. No hay validación en ello.
Mi equipo usó JSON junto a columnas tradicionales en postgres y al principio fue lo mejor desde el pan rebanado. JSON era atractivo y poderoso, hasta que un día nos dimos cuenta de que la flexibilidad tenía un costo y de repente es un verdadero problema. A veces, ese punto avanza muy rápido y luego se vuelve difícil de cambiar porque hemos construido muchas otras cosas además de esta decisión de diseño.
Las horas extraordinarias, al agregar nuevas funciones, tener los datos en JSON condujeron a consultas de aspecto más complicadas que las que podrían haberse agregado si nos limitáramos a las columnas tradicionales. Entonces, comenzamos a buscar ciertos valores clave en columnas para poder hacer uniones y hacer comparaciones entre valores. Mala idea. Ahora tuvimos duplicación. ¿Un nuevo desarrollador se uniría y se confundiría? ¿Cuál es el valor en el que debería estar guardando? ¿El JSON o la columna?
Los campos JSON se convirtieron en cajones basura para pequeñas piezas de esto y aquello. Sin validación de datos a nivel de base de datos, sin consistencia o integridad entre documentos. Eso llevó toda esa responsabilidad a la aplicación en lugar de obtener un tipo duro y una verificación de restricciones de las columnas tradicionales.
Mirando hacia atrás, JSON nos permitió iterar muy rápidamente y sacar algo por la puerta. Fue grandioso. Sin embargo, después de alcanzar un cierto tamaño de equipo, su flexibilidad también nos permitió colgarnos de una larga cuerda de deuda técnica que luego ralentizó el progreso posterior de la evolución de las características. Usar con precaución.
Piense detenidamente sobre la naturaleza de sus datos. Es la base de tu aplicación. Cómo se utilizarán los datos a lo largo del tiempo. ¿Y cómo es probable que CAMBIE?
fuente
Solo lo lancé, pero WordPress tiene una estructura para este tipo de cosas (al menos WordPress fue el primer lugar donde lo observé, probablemente se originó en otro lugar).
Permite claves ilimitadas y es más rápido buscar que usar un blob JSON, pero no tan rápido como algunas de las soluciones NoSQL.
EDITAR
Para almacenar historial / claves múltiples
y consulta a través de algo como esto:
fuente
emailid
clave en el ejemplo que he dado en mi pregunta.El inconveniente del enfoque es exactamente lo que mencionó:
hace que sea MUY lento para encontrar cosas, ya que cada vez que necesita realizar una búsqueda de texto en él.
el valor por columna coincide con la cadena completa.
Su enfoque (datos basados en JSON) está bien para los datos que no necesita buscar, y solo necesita mostrar junto con sus datos normales.
Editar: solo para aclarar, lo anterior se aplica a las bases de datos relacionales clásicas. NoSQL usa JSON internamente, y probablemente sea una mejor opción si ese es el comportamiento deseado.
fuente
Básicamente, el primer modelo que está utilizando se llama almacenamiento basado en documentos. Debe echar un vistazo a la popular base de datos basada en documentos NoSQL como MongoDB y CouchDB . Básicamente, en bases de datos basadas en documentos, usted almacena datos en archivos json y luego puede consultar estos archivos json.
El segundo modelo es la estructura de base de datos relacional popular.
Si desea usar una base de datos relacional como MySql, le sugiero que use solo el segundo modelo. No tiene sentido usar MySql y almacenar datos como en el primer modelo .
Para responder a su segunda pregunta, no hay forma de consultar el nombre como 'foo' si usa el primer modelo .
fuente
Parece que estás dudando principalmente si usar un modelo relacional o no.
Tal como está, su ejemplo encajaría en un modelo relacional razonablemente bien, pero el problema puede surgir, por supuesto, cuando necesite hacer que este modelo evolucione.
Si solo tiene uno (o algunos niveles predeterminados) de atributos para su entidad principal (usuario), aún podría usar un modelo de Valor de atributo de entidad (EAV) en una base de datos relacional. (Esto también tiene sus pros y sus contras).
Si anticipa que obtendrá valores menos estructurados que desea buscar utilizando su aplicación, MySQL podría no ser la mejor opción aquí.
Si estaba utilizando PostgreSQL, podría obtener lo mejor de ambos mundos. (Esta realmente depende de la estructura real de los datos aquí ... MySQL tampoco es necesariamente la elección incorrecta, y las opciones NoSQL pueden ser de interés, solo estoy sugiriendo alternativas).
De hecho, PostgreSQL puede construir índices en funciones (inmutables) (que MySQL no puede, hasta donde yo sé) y en versiones recientes, podría usar PLV8 en los datos JSON directamente para construir índices en elementos JSON específicos de interés, lo que mejoraría la velocidad de sus consultas al buscar esos datos.
EDITAR:
Mezclar los dos modelos no es necesariamente incorrecto (suponiendo que el espacio extra sea insignificante), pero puede causar problemas si no se asegura de que los dos conjuntos de datos estén sincronizados: su aplicación nunca debe cambiar uno sin actualizar el otro .
Una buena manera de lograr esto sería hacer que un disparador realice la actualización automática, ejecutando un procedimiento almacenado dentro del servidor de la base de datos cada vez que se realice una actualización o inserción. Hasta donde yo sé, el lenguaje de procedimiento almacenado MySQL probablemente carece de soporte para cualquier tipo de procesamiento JSON. Una vez más, PostgreSQL con soporte PLV8 (y posiblemente otros RDBMS con lenguajes de procedimientos almacenados más flexibles) debería ser más útil (actualizar su columna relacional automáticamente usando un disparador es bastante similar a actualizar un índice de la misma manera).
fuente
algún tiempo se une en la mesa será una sobrecarga. digamos para OLAP. si tengo dos tablas, una es la tabla ORDERS y la otra es ORDER_DETAILS. Para obtener todos los detalles del pedido, tenemos que unir dos tablas, esto hará que la consulta sea más lenta cuando ninguna de las filas en las tablas aumente, digamos en millones más o menos ... la unión izquierda / derecha es demasiado lenta que la unión interna. Creo que si agregamos cadena / objeto JSON en la entrada ORDERS respectiva, JOIN se evitará. agregar generación de informes será más rápido ...
fuente
respuesta corta que debe mezclar entre ellos, use json para datos que no va a establecer relaciones con ellos, como datos de contacto, dirección, variables de productos
fuente
Está intentando ajustar un modelo no relacional en una base de datos relacional, creo que sería mejor utilizar una base de datos NoSQL como MongoDB . No existe un esquema predefinido que se ajuste a su requisito de no tener limitaciones en el número de campos (consulte el ejemplo típico de la colección MongoDB). Consulte la documentación de MongoDB para tener una idea de cómo consultaría sus documentos, p. Ej.
fuente
Como otros han señalado, las consultas serán más lentas. Sugeriría agregar al menos una columna '_ID' para consultar por eso en su lugar.
fuente