web-dev-qa-db-fra.com

Interrogation de DynamoDB par date

Je viens d'une base de données relationnelle et j'essaie de travailler avec DynamoDB d'Amazon

J'ai une table avec une clé de hachage "DataID" et une plage "CreatedAt" et un tas d'éléments à l'intérieur.

J'essaie d'obtenir tous les éléments créés après une date spécifique et triés par date. Ce qui est assez simple dans une base de données relationnelle.

Dans DynamoDB, la chose la plus proche que je puisse trouver est une requête et l'utilisation de la clé de plage supérieure au filtre. Le seul problème est que pour effectuer une requête, j'ai besoin d'une clé de hachage qui va à l'encontre de l'objectif recherché.

Alors qu'est-ce que je fais mal? Mon schéma de table est faux, la clé de hachage ne devrait-elle pas être unique? ou y a-t-il un autre moyen d'interroger?

82
applechief

Réponse mise à jour:

DynamoDB permet de spécifier des index secondaires pour faciliter ce type de requête. Les index secondaires peuvent être globaux, ce qui signifie qu’ils couvrent l’ensemble de la table sur des clés de hachage ou locaux, ce qui signifie qu’ils existeraient au sein de chaque partition de clé de hachage, ce qui obligera à spécifier la clé de hachage lors de l’interrogation.

Pour le cas d'utilisation de cette question, vous voudriez utiliser un index secondaire global sur le champ "CreatedAt".

Pour plus d'informations sur les index secondaires DynamoDB voir la documentation de l'index secondaire

Réponse originale:

DynamoDB n'autorise pas les recherches indexées sur la clé de plage uniquement. La clé de hachage est requise pour que le service sache quelle partition rechercher dans les données.

Vous pouvez bien sûr effectuer une opération d'analyse pour filtrer en fonction de la date, mais cela nécessiterait une analyse complète de la table, ce qui n'est donc pas idéal.

Si vous devez effectuer une recherche indexée des enregistrements dans le temps sur plusieurs clés principales, DynamoDB peut ne pas être le service idéal à utiliser ou vous devez peut-être utiliser une table distincte (dans DynamoDB ou dans un magasin relationnel) pour stocker des éléments. métadonnées sur lesquelles vous pouvez effectuer une recherche indexée.

34
Mike Brant

Compte tenu de la structure actuelle de votre table, cela n’est pas possible dans DynamoDB. Le défi consiste à comprendre que la clé de hachage de la table (partition) doit être traitée comme une création de tables séparées. À certains égards, cela est vraiment puissant (imaginez les clés de partition comme créant une nouvelle table pour chaque utilisateur ou client, etc.).

Les requêtes ne peuvent être effectuées que dans une seule partition. C'est vraiment la fin de l'histoire. Cela signifie que si vous souhaitez interroger par date (vous souhaitez utiliser msec depuis Epoch), tous les éléments que vous souhaitez récupérer dans une requête unique doivent avoir le même hachage (clé de partition).

Je devrais qualifier cela. Vous pouvez absolument scan par le critère que vous recherchez, ce n'est pas un problème, mais cela signifie que vous examinerez chaque ligne de votre tableau, puis que vous vérifierez si la date de cette ligne correspond à vos paramètres. C’est très coûteux, surtout si vous voulez stocker des événements par date (c’est-à-dire que vous avez beaucoup de lignes).

Vous pouvez être tenté de regrouper toutes les données dans une seule partition pour résoudre le problème. Vous pouvez le faire, mais votre débit sera extrêmement faible, car chaque partition ne reçoit qu'une fraction de la quantité totale définie.

La meilleure chose à faire est de déterminer les partitions les plus utiles à créer pour enregistrer les données:

  • Avez-vous vraiment besoin de regarder toutes les lignes, ou est-ce seulement les lignes d'un utilisateur spécifique?

  • Serait-il possible de commencer par réduire la liste par mois et d'effectuer plusieurs requêtes (une par mois)? Ou par année?

  • Si vous effectuez une analyse de série chronologique, il existe plusieurs options, remplacez la clé de partition par un élément calculé sur PUT pour simplifier l'utilisation de query, ou utilisez un autre produit aws, tel que kinesis, qui se prête bien à enregistrement en ajout uniquement.

35
Warren Parad

Votre clé de hachage (primaire de type) doit être unique (à moins que vous n'ayez une plage comme celle indiquée par d'autres).

Dans votre cas, pour interroger votre table, vous devez avoir un index secondaire.

|  ID  | DataID | Created | Data |
|------+--------+---------+------|
| hash | xxxxx  | 1234567 | blah |

Votre clé de hachage est ID Votre index secondaire est défini comme suit: DataID-Created-index (c'est le nom que DynamoDB utilisera)

Ensuite, vous pouvez faire une requête comme ceci:

var params = {
    TableName: "Table",
    IndexName: "DataID-Created-index",
    KeyConditionExpression: "DataID = :v_ID AND Created > :v_created",
    ExpressionAttributeValues: {":v_ID": {S: "some_id"},
                                ":v_created": {N: "timestamp"}
    },
    ProjectionExpression: "ID, DataID, Created, Data"
};

ddb.query(params, function(err, data) {
    if (err) 
        console.log(err);
    else {
        data.Items.sort(function(a, b) {
            return parseFloat(a.Created.N) - parseFloat(b.Created.N);
        });
        // More code here
    }
});

Essentiellement, votre requête ressemble à:

SELECT * FROM TABLE WHERE DataID = "some_id" AND Created > timestamp;

L'index secondaire augmentera la capacité de lecture/écriture requise, vous devez donc en tenir compte. C'est toujours beaucoup mieux que de faire un scan qui sera coûteux en lecture et en temps (et limité à 100 items je crois).

Ce n'est peut-être pas la meilleure façon de le faire, mais pour quelqu'un qui est habitué à RD (je suis aussi habitué à SQL), c'est le moyen le plus rapide d'être productif. Comme il n'y a pas de contrainte en ce qui concerne le schéma, vous pouvez créer quelque chose qui fonctionne et une fois que vous disposez de la bande passante pour travailler de la manière la plus efficace, vous pouvez changer les choses.

8
E.T

L’approche que j’ai suivie pour résoudre ce problème consiste à créer un index secondaire global comme ci-dessous. Pas sûr que ce soit la meilleure approche mais, espérons-le, utile à quelqu'un.

Hash Key                 | Range Key
------------------------------------
Date value of CreatedAt  | CreatedAt

Limitation imposée à l'utilisateur de l'API HTTP pour spécifier le nombre de jours pour extraire les données, par défaut à 24 heures.

De cette façon, je peux toujours spécifier HashKey comme jour de la date actuelle et RangeKey peut utiliser les opérateurs> et <lors de la récupération. De cette façon, les données sont également réparties sur plusieurs fragments.

7
Gireesh

Vous pouvez faire en sorte que la clé de hachage ressemble à un identifiant de "catégorie de produit", puis à la touche de plage en combinant un horodatage avec un identifiant unique ajouté à la fin. De cette façon, vous connaissez la clé de hachage et pouvez toujours interroger la date avec une valeur supérieure à.

3
greg

Vous pouvez avoir plusieurs clés de hachage identiques. mais seulement si vous avez une clé de plage qui varie. Pensez-y comme aux formats de fichiers; vous pouvez avoir 2 fichiers portant le même nom dans le même dossier tant que leur format est différent. Si leur format est identique, leur nom doit être différent. Le même concept s'applique aux clés de hachage/plage de DynamoDB; il suffit de penser au hachage comme nom et à la plage comme format.

De plus, je ne me souviens pas s’ils en avaient au moment de l’opération (je ne le crois pas), mais ils offrent maintenant des index locaux secondaires.

D'après ce que je comprends, cela devrait maintenant vous permettre d'effectuer les requêtes souhaitées sans avoir à effectuer une analyse complète. L'inconvénient est que ces index doivent être spécifiés lors de la création de la table et (je crois que) ne peuvent pas être vides lors de la création d'un élément. En outre, ils nécessitent un débit supplémentaire (bien que généralement pas autant qu'une analyse) et un stockage, de sorte que ce n'est pas une solution parfaite, mais une alternative viable pour certains.

Je recommande tout de même la réponse de Mike Brant comme méthode privilégiée d'utilisation de DynamoDB; et utiliser cette méthode moi-même. Dans mon cas, je n'ai qu'une table centrale avec uniquement une clé de hachage comme identifiant, puis des tables secondaires comportant un hachage et une plage pouvant être interrogée, puis l'élément pointe le code vers "l'élément d'intérêt" de la table centrale, directement .

Des données supplémentaires concernant les index secondaires peuvent être trouvées dans la documentation DynamoDB d'Amazon ici pour les personnes intéressées.

Quoi qu'il en soit, j'espère que cela aidera tout le monde sur ce sujet.

1
DGolberg