Alternative à l'EAV pour les champs dynamiques dans un entrepôt de données de schéma en étoile

13

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 => valuemappages, 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

  1. Tableau requests
    (id, timestamp, uri)
    par exemple(1, 149382220, '/')

  2. 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

Howard
la source
2
Quel est le problème d'essayer ce que vous proposez sur une base de données de développement? Parlez-vous également de SQL Server? La balise sql est assez large.
Max Vernon
Mise à jour de ma question
Howard
1
Quel SGBD utilisez-vous? Certains ont de très bonnes capacités d'indexation de texte, donc je n'exclurais pas d'utiliser un champ "texte long" pour stocker les demandes. Cela dit, je n'aurais aucun problème à utiliser le modèle que vous proposez. Bien que l'EAV au sens strict, il ne soit utilisé qu'à cette fin très spécifique. Encore une fois, cela dit, quel genre de requêtes devez-vous être en mesure de faire? Essayez d'écrire ces requêtes sur ce modèle pour voir si cela fonctionne pour vous.
Colin 't Hart
1
Quel SGBDR utilisez-vous? SQLn'est pas assez précis. On vous a demandé deux fois. Je suis le troisième.
Erwin Brandstetter
2
Depuis RedShift est basé sur PostgreSQL, je voudrais essayer d'utiliser le hstoreou les jsontypes de données (ou jsonbsi / quand ils « mise à niveau » à 9.4).
Colin 't Hart

Réponses:

11

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.

Nathan Jolly
la source
2
Dans PostgreSQL, je ne recommanderais pas XML mais soit hstoreou json. Dans la prochaine 9.4 jsonbserait ma recommandation.
Colin 't Hart
J'aime vraiment cette réponse avec les avantages et les explications de chacun. Très instructif - j'apprécie vraiment les informations des colonnes éparses. Je voudrais un exemple d'EAV utilisant l'approche à colonnes éparses.
StixO
9

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.

Max Vernon
la source
1
Dans la question comme dans la réponse, le terme BLOBest utilisé, ce qui signifie long objet binaire . Je préférerais utiliser un CLOB(Object long OBject) ou quelque chose comme textdans PostgreSQL, car nous parlons de caractères et non de données binaires.
Colin 't Hart
2
J'ai utilisé un champ binaire car j'ai sérialisé l'objet de session entier et stocké le tout dans la base de données.
Max Vernon