J'ai besoin de prendre en charge les champs et les valeurs dynamiques dans un grand datawarehouse pour stocker le journal des demandes d'API, mon cas d'utilisation est que j'ai besoin de stocker toutes les chaînes de requête des demandes d'API et capable d'effectuer des requêtes contre elles à l'avenir (il ne s'agit donc pas uniquement de stockage, donc je ne peux pas utiliser blob pour eux)
par exemple http://example.com/?action=test&foo=abc&bar=def...
J'ai besoin de stocker tous les field => value
mappages, c'est-à-dire (action => test), (foo => abc), (bar => def)
, et comme le champ est tellement dynamique, la seule solution que j'ai trouvée est d'utiliser Entity-Attribute-Value, cependant, les gens continuent à dire que c'est une très mauvaise conception.
Alors, considérez mon cas d'utilisation ci-dessus, quelle serait une alternative appropriée à l'EAV?
Mon schéma actuel en utilisant KAV
Tableau
requests
(id, timestamp, uri)
par exemple(1, 149382220, '/')
Tableau
params
(request_id, key, value)
par exemple(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')
Aucune suggestion?
Mise à jour: nous exécutons l'entrepôt sur AWS RedShift
SQL
n'est pas assez précis. On vous a demandé deux fois. Je suis le troisième.hstore
ou lesjson
types de données (oujsonb
si / quand ils « mise à niveau » à 9.4).Réponses:
Je peux penser à trois solutions - EAV, XML et colonnes éparses. Ce dernier est spécifique au fournisseur et peut ne pas vous être utile.
Quelle que soit la méthode que vous choisissez, vous pouvez envisager de stocker les données de la demande d'origine dans un format brut, dans un tableau ou un fichier plat. Cela vous permettra d'essayer facilement de nouvelles façons de stocker les données, vous permettra de recharger les données si vous découvrez une erreur dans la façon dont vous analysez vos demandes, et offrira des opportunités pour analyser les demandes d'API en utilisant le traitement par lots ou le «big data» si vous constatez que votre entrepôt de données n'est pas en mesure de traiter efficacement les données.
Considérations EAV
EAV / KVS, comme vous l'avez décrit ci-dessus, est probablement la mise en œuvre la plus simple.
Malheureusement, cela va également coûter très cher - pour obtenir toutes sortes de requêtes efficaces sur les clés couramment utilisées, vous aurez besoin d'avoir des index sur la colonne de clé, qui pourraient être très fragmentés. La recherche de clés particulières serait extrêmement coûteuse.
Vous pouvez réduire le coût de l'indexation ou des analyses d'index en prenant en charge votre magasin EAV avec des vues matérialisées (de nombreux fournisseurs le prennent en charge) pour interroger les clés ou les valeurs qui vous intéressent.
XML
La plupart des systèmes de base de données d'entreprise offrent une gestion XML très mature, y compris la validation, l'indexation et l'interrogation sophistiquée.
Le chargement de la demande d'API dans la base de données au format XML fournirait un tuple par demande, ce qui pourrait logiquement être un peu plus acceptable pour vous que d'avoir un nombre inconnu de lignes dans une table EAV.
Que cela soit efficace dépendra beaucoup de votre fournisseur de SGBDR et de votre implémentation.
Le plus gros inconvénient est que c'est probablement le seul moyen de gérer les données qui est plus compliqué que la manipulation de chaîne de la requête d'origine!
Colonnes clairsemées / tables traditionnelles
Il est possible que vous puissiez charger vos données dans une structure de table traditionnelle, avec une colonne par clé.
La fonctionnalité Sparse Columns de SQL Server est une excellente alternative à un magasin EAV. Une table avec des colonnes éparses se comporte à peu près comme une table normale, sauf qu'elle peut avoir jusqu'à 30 000 colonnes, et les valeurs NULL dans les colonnes éparses ne consomment pas d'espace dans la table.
Les combiner avec des index filtrés (une autre fonctionnalité spécifique à SQL Server) peut fournir une alternative extrêmement efficace à un magasin EAV si vous recherchez fréquemment quelques colonnes et / ou valeurs spécifiques.
L'utilisation d'une table traditionnelle avec d'autres fournisseurs peut être viable - IBM prend en charge plus de 700 colonnes par table et Oracle environ 1 000, et des fonctionnalités telles que la compression ou le traitement par Oracle des valeurs nulles finales peuvent signifier que vous pouvez stocker vos données API assez efficacement.
L'inconvénient évident de cette approche est que lorsque vous avez ajouté de nouvelles clés à votre API, vous devez ajuster votre schéma en conséquence.
la source
hstore
oujson
. Dans la prochaine 9.4jsonb
serait ma recommandation.L'EAV n'est pas une mauvaise conception, en soi, c'est simplement une conception qui nécessite une bonne dose de prévoyance et qui peut être confrontée à des problèmes de performances à mesure que la quantité de données augmente. Il se peut que pour votre système, cela fonctionne bien.
Lorsque j'ai conçu un système pour stocker des chaînes de requête, je n'avais aucune idée à l'avance des champs qui m'intéresseraient. J'ai créé une table pour stocker la chaîne de requête au format binaire sérialisé et j'ai créé un système qui m'a permis de séparer la requête ficelle dans ses pièces une fois que je connaissais les pièces qui m'intéressaient. De là, j'ai créé un ensemble de tables; un pour les ensembles de données généralement contenus dans la chaîne de requête.
Par exemple, j'ai finalement eu une table pour les données de référence, une pour les données de demande cible et une pour les éléments liés à l'utilisateur tels que la requête de recherche qu'ils ont entrée.
J'ai trouvé que la possibilité de stocker la chaîne de requête entière dans une seule table en tant qu'objet blob, tout en offrant la possibilité de diviser cet objet blob à l'avenir, répondait très bien à mes besoins.
la source
BLOB
est utilisé, ce qui signifie long objet binaire . Je préférerais utiliser unCLOB
(Object long OBject) ou quelque chose commetext
dans PostgreSQL, car nous parlons de caractères et non de données binaires.