web-dev-qa-db-ja.com

明らかなハッシュキーなしで、日付(範囲キー)でDynamoDBをクエリする方法は?

IOSアプリのローカルデータをDynamoDBテーブルのデータと同期させる必要があります。 DynamoDBテーブルは〜2K行で、ハッシュキー(id)と次の属性のみが含まれます。

  • id(uuid)
  • lastModifiedAt(タイムスタンプ)
  • name
  • latitude
  • longitude

現在、lastModifiedAtでスキャンとフィルタリングを行っています。ここで、lastModifiedAtはアプリの最終更新日よりも大きくなりますが、高価になると思います。

最良の answer 見つけることができるのは、範囲としてlastModifiedAtを持つグローバルセカンダリインデックスを追加することですが、GSIには明らかなハッシュキーはありません。

GSIを使用して範囲ごとにクエリする必要がある場合のベストプラクティスは何ですか?ただし、明らかなハッシュキーはありませんか?または、フルスキャンが唯一のオプションである場合、コストを抑えるためのベストプラクティスはありますか?

29
James Skidmore

D.Shawleyの答えは私を正しい方向に導くのに役立ちましたが、GSIに関する2つの考慮事項を逃しました。

  1. ハッシュ+範囲は一意である必要がありますが、日+タイムスタンプ(推奨されるアプローチ)は必ずしも一意ではありません。
  2. ハッシュとして日のみを使用すると、最後の更新日(数か月または数年前)から毎日の結果を取得するために多数のクエリを使用する必要があります。

そのため、私が取ったアプローチは次のとおりです。

  • ハッシュキーがYearMonth(例:201508)で範囲がidのグローバルセカンダリインデックス(GSI)を作成しました
  • GSIを複数回、最後の更新日から毎月1回クエリします。クエリもlastModifiedAt > [given timestamp]でフィルタリングされます。
9
James Skidmore

Global Secondary Indexは要件に合っているようですが、Hash Keyの一部としてtimestamp関連情報を含めようとすると、「ホットパーティション」として知られるものが作成される可能性が非常に高くなります。望ましくない。

不正アクセスは、最新のアイテムが古いアイテムよりもはるかに頻繁に取得されるために発生します。これはパフォーマンスに影響を与えるだけでなく、ソリューションのコスト効率を低下させます。

ドキュメントの詳細を参照してください。

たとえば、テーブルに非常に少数のアクセス頻度の高いパーティションキー値があり、場合によっては1つの非常に頻繁に使用されるパーティションキー値でも、リクエストトラフィックは少数のパーティションに集中します。ワークロードが非常に不均衡である場合、つまり1つまたはいくつかのパーティションに不均衡に集中している場合、要求はプロビジョニングされたスループットレベル全体を達成しません。 DynamoDBのスループットを最大限に活用するには、パーティションキーに多数の個別の値があり、可能な限りランダムに値がかなり均一に要求されるテーブルを作成します。

記載内容に基づいて、idは実際にHash Key(別名Partition Key)に適していると思われますが、GSIキーが同じように機能するので変更しません。パーティショニングに関する限り。別の注意として、Primary Key全体を提供することでデータを取得する際のパフォーマンスが高度に最適化されているため、可能な限りそれを提供するソリューションを見つけるようにしてください。

更新された最新の日付に基づいて主キーを保存するために、個別のテーブルを作成することをお勧めします。ユースケースに最適な粒度に基づいて、データをテーブルにセグメント化できます。たとえば、更新を日ごとに分割するとします。

a。毎日の更新は、次の命名規則に従ってテーブルに保存できます。updates_DDMM

b。 updates_DDMMテーブルにはidのみがあります(他のテーブルのハッシュキー)

ここで、アプリの最新の更新日が2日前(2016年4月7日)であり、最近のレコードを取得する必要がある場合、次のようにする必要があります。

私。テーブルupdates_0504およびupdates_0604をスキャンして、すべてのハッシュキーを取得します。

ii。最後に、取得したすべてのハッシュキーでBatchGetItemを送信して、メインテーブル(lat/lng、名前などを含む)からレコードを取得します。

BatchGetItemは非常に高速で、他の操作とは異なりジョブを実行します。

追加のテーブルを作成すると、ソリューション全体にコストが追加されると考えることができます...まあ、GSIを使用すると、基本的にテーブルを複製し(すべてのフィールドを投影する場合)、すべての〜2kに追加コストを追加します記録、最近更新されたかどうか...

このようなテーブルを作成するのは直感に反しているようですが、実際には時系列データを扱うときのベストプラクティスです(AWS DynamoDBドキュメントより):

[...]アプリケーションは、最新の顧客データがより関連性の高いテーブル内のすべてのアイテムで不均一なアクセスパターンを示し、アプリケーションがより頻繁に最新のアイテムにアクセスし、時間が経過するにつれてこれらのアイテムへのアクセスが少なくなり、最終的に古いアイテムにアクセスすることはほとんどありません。これが既知のアクセスパターンである場合、テーブルスキーマを設計するときに考慮に入れることができます。すべてのアイテムを単一のテーブルに保存する代わりに、複数のテーブルを使用してこれらのアイテムを保存できます。たとえば、月ごとまたは週ごとのデータを保存するテーブルを作成できます。データアクセスレートが高い最新の月または週のデータを格納するテーブルでは、より高いスループットを要求し、古いデータを格納するテーブルでは、スループットをダイヤルダウンしてリソースを節約できます。

スループット設定が高い「ホット」アイテムを1つのテーブルに保存し、スループット設定が低い「コールド」アイテムを別のテーブルに保存することで、リソースを節約できます。テーブルを削除するだけで、古いアイテムを削除できます。オプションで、これらのテーブルをAmazon Simple Storage Service(Amazon S3)などの他のストレージオプションにバックアップできます。テーブル全体を削除することは、アイテムを1つずつ削除するよりも非常に効率的です。これは、書き込み操作を書き込み操作と同じ数だけ行うので、書き込みスループットを本質的に2倍にします。

ソース: http://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html

それがお役に立てば幸いです。よろしく。

26
bsd

タイムスタンプの「日」部分をハッシュとして使用し、完全なタイムスタンプを範囲として使用できます。

6
D.Shawley