2012-02-13 5 views
2

Je grappe une série de produits de sites Web et les stocke dans une base de données. En ce moment, j'utilise MySQL, avec deux tables:NoSQL (MongoDB/DynamoDB) Schema

products (product_id, site, product_description, etc) 
    e.g. (1234, "xyz.com", "nice product", etc) 
product_history (product_id, scrape_timestamp) 
    e.g. (1234, 2012-01-02 10:53:09) 
     (1234, 2012-01-03 11:02:09) 

Ce schéma signifie que je peux obtenir un instantané dont les produits ont été répertoriés à tout moment dans le passé.

Je considère un passage à NoSQL parce que (i) j'obtiens souvent différents champs de différents sites et (ii) le volume de données sera environ 5-10m produits par an. Je vois deux façons de structurer le schéma

Option 1: "liste intégrée"

product_id, site,  product_description, scrape_timestamp 
1234,  "xyz.com", "test product",  {2012-01-02 10:53:09, 2012-01-03 11:02:09} 

Option 2: "index secondaire"

keep both tables as above with the relational schema 

Je pense que l'option 1 fonctionnerait dans quelque chose comme MongoDB où les index secondaires sont autorisés tandis que l'option 2 fonctionnerait dans MongoDB ou DynamoDB. (Je considère ces deux parce que je veux quelque chose hébergé dans le nuage avec zéro frais généraux de maintenance pour moi).

Suis-je sur la bonne voie avec ces approches? Lequel fonctionnerait le mieux? Je ne suis pas familier avec nosql donc tout conseil serait apprécié.

+0

Je ne pense pas que le problème du volume de données soit un argument valable dans les deux cas. Les produits 5-10m devraient être réalisables dans chaque solution. – Joe

+0

Que diriez-vous de la limite pour que MySQL fonctionne bien sur un serveur? J'ai aussi d'autres tables (qui ont plusieurs rangées par produit) et, y compris celles-ci, j'arrive seulement à environ 1 produit écrit par seconde ... en espérant que nosql pourrait améliorer les performances d'écriture aussi – alan

+0

La réponse à cela est très variable, mais cela indique quelque chose de grave. Je m'attendrais à être capable de commettre des centaines, sinon des milliers, de lignes par seconde. Comment insérez-vous des enregistrements individuels? – Joe

Répondre

2

Vous dites que vous essayez de résoudre le problème de stockage des données suivantes:

  1. 10 millions ou points de données historiques par an
  2. points de données hétérogènes

10 millions ou plus points de données historiques par an

Comme indiqué dans les commentaires, 10 millions de points de données par an l'oreille n'est pas un gros ensemble de données. La plupart des bases de données, y compris MySQL, seront capables de supporter ceci, tant que vous savez comment les régler, donc ne changez pas de technologies juste pour résoudre ce problème. Si vous avez des questions spécifiques sur la façon de régler MySQL, je vous suggère de poster une question distincte. En ce qui concerne une solution basée sur MongoDB à votre problème de données historiques, vous auriez probablement une collection pour les données product_history, et il vous suffit de décider du nombre d'entrées à mettre dans chaque document. Quelques options: une par produit; un par produit/horodatage; un par produit/horodatage dans une période de temps spécifique, ex. un jour ou un mois. Un peu plus de détails:

  • The mongo docs suggère que l'intégration des données dans un tableau aura un sens "pour certains cas d'utilisation". Le vôtre ressemble à un tel cas d'utilisation, c'est-à-dire que je ne créerais PAS un document par produit/horodatage.
  • Vous ne voulez pas non plus un document par produit car mongo n'est pas très bon pour faire pousser de très longs tableaux. Par conséquent, l'option restante est une par produit/horodatage pendant une période donnée. Allez avec celui-ci. Malheureusement, vous devrez essayer quelques choses afin de déterminer exactement comment structurer ce document. Voici quelques choses à essayer:
    • Utilisez un attribut "period" pour indiquer l'heure de début de la période en question. Créer un index sur le produit/période.
    • Lorsque vous ajoutez à la structure de données dans ce document, vous pouvez simplifier votre code en utilisant la fonctionnalité upsert de mongo.
    • Choisissez la durée de la période (horaire, quotidienne, mensuelle, etc.) en fonction de la fréquence à laquelle les nouveaux points de données entrent en jeu. Vous devez probablement ajuster cette durée en fonction d'un test de charge.
    • La manière la plus simple de structurer le document par période consiste à utiliser un tableau pour contenir les données. Cependant, mongo n'est pas bon pour l'ajout de tableaux très longs, donc certaines personnes ont amélioré les performances en créant un arbre simple dans le document. Par exemple, si vous avez un document par jour, vous pouvez utiliser un tableau séparé par heure dans la journée:
{ 
    "0" : [ 123, 456 ], 
    "1" : [ 789 ] 
} 

Si vous avez une tonne de données qui ne entrer en mémoire sur un serveur, et vous devez être capable de lire les données historiques très rapidement, alors vous pouvez tirer un certain bénéfice de la prise en charge de sharding par MongoDB. Fondamentalement, vous serez en mesure de diviser vos données de telle sorte qu'une lecture ne doit pas frapper le disque. Mais votre question ne précise pas si les performances de lecture sont importantes et quels types de lectures vous effectuez, alors postez une nouvelle question si vous souhaitez plus d'informations.

points de données hétérogènes

En ce qui concerne une solution de SGBDR à votre problème, voici les approches les plus courantes que je l'ai vu:

  • dénormaliser les données. Vous dites que vous avez 85 attributs par produit? Ensuite, créez une table avec 85 colonnes! Vous dites qu'un autre produit a 20 attributs différents? Ensuite, ajoutez 20 autres colonnes à votre table! Cette solution:
    • Est simple. Fonctionne bien, puisque tous les avantages habituels de la dénormalisation s'appliquent.
    • Affaiblit certains des avantages de l'utilisation d'une base de données relationnelle. Par exemple, la plupart de vos colonnes ne peuvent pas avoir une contrainte "non nulle".
  • Normaliser les données. Créez une table pour capturer les attributs de type X, une autre table pour capturer le type Y, etc. Si vous avez un nouveau type de produit, ajoutez une nouvelle table. Cette solution:
    • Peut être compliqué. Par exemple, comment décidez-vous quelle table mettre certains attributs communs?
    • Peut mal fonctionner. Par exemple, si vous devez joindre 10 tables afin d'extraire des informations utiles de la base de données, vous avez un problème.
    • Cela rendra les puristes de base de données heureux.
  • Utilisez des lignes à la place des colonnes. Cette solution:
    • Est compliqué et difficile à maintenir.
    • Fonctionne mal.
    • Affaiblit certains des avantages de l'utilisation d'une base de données relationnelle.

(Notez qu'il existe d'autres solutions basées SGBDR sur le marché. Par exemple, certaines personnes aiment put XML documents into DB2.)

Vous essayez la dernière approche, il est donc pas étonnant que vous êtes malheureux! Si vous voulez conserver un SGBDR, je vous recommande de passer à l'une des autres approches que j'ai énumérées.

Maintenant, revenons à votre question à propos de NoSQL. Une base de données NoSQL basée sur des documents, telle que MongoDB, est une solution intéressante pour votre problème de "points de données hétérogènes", car il est sans schéma. Vous pouvez lister les spécifications d'un produit dans un document, et lorsque vous voulez ajouter de nouveaux attributs, alors, faites-le. MongoDB vous permet d'indexer les attributs, donc si vous voulez trouver un produit avec l'attribut A, vous pouvez le faire rapidement via un index. (Il n'y a pas de magie ici: comme avec n'importe quelle base de données, les index peuvent être coûteux à maintenir, alors créez-les avec parcimonie).

+0

C'est utile, merci. Pourriez-vous développer vos commentaires sur product_history - quels facteurs favoriseraient une taille de document plutôt qu'une autre? – alan

+0

développé avec quelques commentaires généraux. vous aurez vraiment besoin de faire quelques tests afin de choisir des paramètres spécifiques, car ceux-ci dépendent des éléments de données en question. – jtoberon