web-dev-qa-db-fra.com

Comment interroger DynamoDB par date (clé de plage), sans clé de hachage évidente?

Je dois synchroniser les données locales d'une application iOS avec les données d'une table DynamoDB. La table DynamoDB comprend environ 2 000 lignes, avec uniquement une clé de hachage (id) et les attributs suivants:

  • id (uuid)
  • lastModifiedAt (horodatage)
  • name
  • latitude
  • longitude

Je scanne et filtre actuellement par lastModifiedAt, où lastModifiedAt est supérieur à la dernière date de rafraîchissement de l'application, mais j'imagine que cela deviendra coûteux.

Le meilleur réponse que je peux trouver est d'ajouter un index secondaire global avec lastModifiedAt comme plage, mais il n'y a pas de clé de hachage évidente pour le GSI.

Quelle est la meilleure pratique lorsque vous devez interroger par plage à l'aide d'un GSI, mais il n'y a pas de clé de hachage évidente? Alternativement, si une analyse complète est la seule option , existe-t-il des meilleures pratiques pour réduire les coûts?

29
James Skidmore

Alors que la réponse de D.Shawley m'a aidé à me diriger dans la bonne direction, elle a manqué deux considérations pour un GSI:

  1. La plage de hachage + doit être unique, mais l'horodatage jour + (son approche recommandée) ne serait pas nécessairement unique.
  2. En utilisant uniquement le jour comme hachage, j'aurais besoin d'utiliser un grand nombre de requêtes pour obtenir les résultats de chaque jour depuis la dernière date de rafraîchissement (qui pourrait être des mois ou des années auparavant).

En tant que tel, voici l'approche que j'ai adoptée:

  • Création d'un index secondaire global (GSI) avec la clé de hachage sous la forme YearMonth (par exemple, 201508) et varie comme id
  • Recherchez le GSI plusieurs fois, une requête pour chaque mois depuis la dernière date d'actualisation. Les requêtes sont également filtrées avec lastModifiedAt > [given timestamp].
9
James Skidmore

Bien qu'un Global Secondary Index semble correspondre à vos besoins, toute tentative d'inclure des informations relatives à timestamp dans votre Hash Key créera très probablement ce qui est connu comme "Hot Partition", ce qui est extrêmement indésirable.

L'accès inégal se produira car les éléments les plus récents vont être récupérés avec beaucoup plus de fréquence que les anciens. Cela aura non seulement un impact sur vos performances, mais rendra également votre solution moins rentable.

Voir quelques détails dans la documentation:

Par exemple, si une table a un très petit nombre de valeurs de clé de partition très utilisées, peut-être même une seule valeur de clé de partition très utilisée, le trafic de demande est concentré sur un petit nombre de partitions - potentiellement une seule partition. Si la charge de travail est fortement déséquilibrée, ce qui signifie qu'elle est concentrée de manière disproportionnée sur une ou quelques partitions, les demandes n'atteindront pas le niveau de débit provisionné global. Pour tirer le meilleur parti du débit DynamoDB, créez des tables dans lesquelles la clé de partition a un grand nombre de valeurs distinctes et les valeurs sont demandées de manière assez uniforme, aussi aléatoire que possible.

D'après ce qui est dit, le id semble en effet être un bon choix pour votre Hash Key (alias. Partition Key), Je ne changerais pas cela car les clés GSI fonctionnent de la même manière que le partitionnement. Comme note distincte, les performances sont hautement optimisées lorsque vous récupérez vos données en fournissant l'intégralité de Primary Key, nous devrions donc essayer de trouver une solution qui fournit cela dans la mesure du possible.

Je suggère de créer des tables distinctes pour stocker les clés primaires en fonction de leur date de mise à jour. Vous pouvez segmenter les données en tableaux en fonction de la granularité qui correspond le mieux à vos cas d'utilisation. Par exemple, supposons que vous souhaitiez segmenter les mises à jour par jour:

une. Vos mises à jour quotidiennes peuvent être stockées dans des tableaux avec la convention de dénomination suivante: updates_DDMM

b. Le updates_DDMM les tables n'auraient que les id (clés de hachage de l'autre table)

Supposons maintenant que la dernière date d'actualisation de l'application date d'il y a 2 jours (04/07/16) et que vous devez obtenir les enregistrements récents, vous aurez alors besoin de:

je. Scannez les tableaux updates_0504 et updates_0604 pour obtenir toutes les clés de hachage.

ii. Enfin, obtenez les enregistrements de la table principale (contenant lat/lng, nom, etc.) en soumettant un BatchGetItem avec toutes les clés de hachage obtenues.

BatchGetItem est super rapide et fera le travail comme aucune autre opération.

On peut affirmer que la création de tables supplémentaires ajoutera des coûts à votre solution globale ... eh bien, avec GSI vous dupliquez essentiellement votre table (au cas où vous projetez tous les champs) et ajoutez ce coût supplémentaire pour tous ~ 2k les enregistrements, qu'ils soient récemment mis à jour ou non ...

Il semble contre-intuitif de créer des tableaux comme celui-ci, mais c'est en fait une meilleure pratique lors du traitement des données de séries chronologiques (à partir de la documentation AWS DynamoDB):

[...] les applications peuvent afficher un modèle d'accès inégal sur tous les éléments du tableau où les dernières données client sont plus pertinentes et votre application peut accéder aux derniers éléments plus fréquemment et avec le temps, ces éléments sont moins accessibles, éventuellement les plus anciens les articles sont rarement consultés. S'il s'agit d'un modèle d'accès connu, vous pouvez en tenir compte lors de la conception de votre schéma de table. Au lieu de stocker tous les éléments dans une seule table, vous pouvez utiliser plusieurs tables pour stocker ces éléments. Par exemple, vous pouvez créer des tableaux pour stocker des données mensuelles ou hebdomadaires. Pour la table stockant des données du dernier mois ou de la dernière semaine, où le taux d'accès aux données est élevé, demandez un débit plus élevé et pour les tables stockant des données plus anciennes, vous pouvez réduire le débit et économiser sur les ressources.

Vous pouvez économiser sur les ressources en stockant des éléments "chauds" dans une table avec des paramètres de débit plus élevés et des éléments "froids" dans une autre table avec des paramètres de débit inférieurs. Vous pouvez supprimer les anciens éléments en supprimant simplement les tableaux. Vous pouvez éventuellement sauvegarder ces tables vers d'autres options de stockage telles que Amazon Simple Storage Service (Amazon S3). La suppression d'une table entière est beaucoup plus efficace que la suppression d'éléments un par un, ce qui double essentiellement le débit d'écriture car vous effectuez autant d'opérations de suppression que d'opérations de mise.

Source: http://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html

J'espère que ça aide. Cordialement.

26
bsd

Vous pouvez utiliser la partie "jour" de l'horodatage comme hachage et utiliser l'horodatage complet comme plage.

6
D.Shawley