284 votes

Stockage de JSON dans la base de données ou création d'une nouvelle ligne pour chaque clé

Je suis en œuvre le modèle suivant pour le stockage de l'utilisateur des données dans ma table j'ai 2 colonnes - uid (clé primaire) et un meta colonne qui stocke d'autres données concernant l'utilisateur dans le format JSON.

 uid   | meta
--------------------------------------------------
 1     | {name:['foo'], 
       |  emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
 2     | {name:['sann'], 
       |  emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------

Est-ce une meilleure façon (en terme de performance, de conception-sage) de la colonne par propriété modèle, où la table a de nombreuses lignes comme uid, name, emailid.

Ce que j'aime dans le premier modèle, vous pouvez ajouter autant de champs que possible, il n'y a pas de limitation.

Aussi, je me demandais, maintenant que j'ai mis en place le premier modèle. Comment dois-je effectuer une requête sur elle, comme, je veux récupérer tous les utilisateurs qui ont un nom comme 'foo'?

Question - quelle est la meilleure manière de stocker des données associées (en gardant à l'esprit que le nombre de champs n'est pas fixe) dans la base de données à l'aide de - JSON ou colonne-par-champ? Aussi, si le premier modèle est mis en œuvre, comment interroger la base de données comme décrit ci-dessus? Dois-je utiliser à la fois les modèles, en stockant toutes les données qui peuvent être recherchés par une requête dans une ligne distincte et d'autres données en JSON (est une ligne différente)?


Mise à jour

Depuis il n'y aura pas trop de colonnes sur lequel j'ai besoin d'effectuer de la recherche, est-il sage d'utiliser les deux modèles? Touche-par-colonne pour les données que j'ai besoin de rechercher et de JSON pour les autres (dans la même base de données MySQL)?

258voto

Colin Morelli Points 6539

Si vous voulez vraiment être en mesure d'ajouter autant de champs que vous le souhaitez sans limite de (autre qu'un document arbitraire limite de taille), envisager une solution NoSQL comme MongoDB.

Pour les bases de données relationnelles: utiliser une colonne par valeur. Mettre un JSON blob dans une colonne, il est pratiquement impossible de requête (et douloureusement lent lorsque vous trouvez une requête qui fonctionne).

Les bases de données relationnelles profiter de types de données lors de l'indexation, et sont destinés à être mis en œuvre avec un normalisée de la structure.

Comme une note de côté: ce n'est pas à dire que vous ne devriez jamais conserver JSON dans une base de données relationnelle. Si vous ajoutez vrai métadonnées, ou si votre JSON est de décrire l'information qui n'a pas besoin d'être interrogé et n'est utilisé que pour l'affichage, il est peut-être exagéré pour créer une colonne séparée pour tous les points de données.

32voto

Adam Points 7600

Juste le jeter dehors, mais WordPress a une structure de ce genre de choses (à moins de WordPress a été le premier endroit que j'ai observé, il vient probablement d'ailleurs).

Il permet illimité de clés, et est plus rapide à la recherche de l'aide d'un JSON blob, mais pas aussi vite que certains les solutions NoSQL.

uid   |   meta_key    |   meta_val
----------------------------------
1         name            Frank
1         age             12
2         name            Jeremiah
3         fav_food        pizza
.................

MODIFIER

Pour le stockage de l'histoire/plusieurs clés

uid   | meta_id    |   meta_key    |   meta_val
----------------------------------------------------
1        1             name            Frank
1        2             name            John
1        3             age             12
2        4             name            Jeremiah
3        5             fav_food        pizza
.................

et une requête via quelque chose comme ceci:

select meta_val from `table` where meta_key = 'name' and uid = 1 order by meta_id desc

19voto

hexblot Points 4531

l'inconvénient de cette approche est exactement ce que vous avez mentionné :

c'est TRÈS lent à trouver des choses, étant donné que chaque fois que vous avez besoin pour effectuer une recherche de texte sur elle.

la valeur par colonne correspond à l'ensemble de la chaîne.

Votre approche JSON (base de données) est très bien pour les données que vous n'avez pas besoin de rechercher, et juste besoin d'affichage le long avec vos données normales.

Edit: Juste pour préciser, le ci-dessus va pour le classique des bases de données relationnelles. NoSQL utiliser JSON en interne, et sont probablement une meilleure option si c'est le comportement souhaité.

12voto

Girish Points 433

Fondamentalement, le premier modèle utilisé est appelé en tant que document de base de stockage. Vous devriez regarder populaire NoSQL document de base de données comme MongoDB et CouchDB. Fondamentalement, dans le document en fonction de la db, vous pouvez stocker des données dans des fichiers json et puis vous pouvez interroger sur ces fichiers json.

Le Second modèle est le populaire relationnel de la base de données de la structure.

Si vous souhaitez utiliser relationnel de la base de données comme MySql alors je vous suggère d'utiliser seulement le deuxième modèle. Il n'y a pas de point à l'aide de MySql et de stockage des données, comme dans le premier modèle.

Pour répondre à votre deuxième question, il n'y a aucun moyen de le nom de la requête comme " foo " si vous utilisez un premier modèle.

6voto

Bruno Points 47560

Il semble que vous êtes principalement hésiter si l'utilisation d'un modèle relationnel ou pas.

Comme il se trouve, à votre exemple, l'ajustement d'un modèle relationnel raisonnablement bien, mais le problème peut venir bien sûr, quand vous en avez besoin pour faire de ce modèle d'évoluer.

Si vous avez seulement une (ou quelques pré-déterminé) les niveaux des attributs de l'entité (utilisateur), vous pouvez toujours utiliser une Entité, la Valeur de l'Attribut (VAE) modèle dans une base de données relationnelle. (Cela a aussi ses avantages et inconvénients.)

Si vous pensez que vous aurez moins structuré de valeurs que vous aurez envie de rechercher à l'aide de votre application, MySQL peut-être pas le meilleur choix ici.

Si vous utilisez PostgreSQL, vous pourriez potentiellement obtenir le meilleur des deux mondes. (Ce vraiment dépend de la structure des données ici... MySQL n'est pas forcément un mauvais choix non plus, et le NoSQL options peuvent être d'intérêt, je suis juste suggérer d'autres solutions.)

En effet, PostgreSQL peut construire des index sur (immuable) fonctions (MySQL ne peut pas pour autant que je sache) et dans les versions récentes, vous pouvez utiliser PLV8 sur les données JSON directement pour construire des index spécifiques JSON éléments d'intérêt, ce qui permettrait d'améliorer la vitesse de vos requêtes lors de la recherche de données.

EDIT:

Depuis il n'y aura pas trop de colonnes dont j'ai besoin pour effectuer de recherche, est-il sage d'utiliser les deux modèles? Touche-par-colonne pour les données J'ai besoin de rechercher et de JSON pour les autres (dans la même base de données MySQL)?

Le mélange des deux modèles n'est pas forcément mauvais (en supposant que l'espace supplémentaire est négligeable), mais il peut causer des problèmes si vous n'avez pas assurez-vous que les deux ensembles de données sont synchronisées: votre demande ne doit pas modifier l'un sans aussi la mise à jour de l'autre.

Une bonne façon d'y parvenir serait d'avoir un déclencheur d'effectuer la mise à jour automatique, par l'exécution d'une procédure stockée dans la base de données du serveur à chaque fois qu'une mise à jour ou l'insert est fabriqué. Pour autant que je suis au courant, MySQL procédure stockée langue probablement le manque de soutien pour toute sorte de JSON traitement. Nouveau PostgreSQL avec PLV8 de soutien (et éventuellement d'autres SGBDR avec plus flexible procédure stockée langues) devrait être plus utile (mise à jour de votre colonne relationnelle automatiquement à l'aide d'un déclencheur est assez similaire à la mise à jour d'un index de la même façon).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X