Amazon web services 如何在没有明显哈希键的情况下按日期(范围键)查询DynamoDB?

Amazon web services 如何在没有明显哈希键的情况下按日期(范围键)查询DynamoDB?,amazon-web-services,amazon-dynamodb,aws-sdk,Amazon Web Services,Amazon Dynamodb,Aws Sdk,我需要保持iOS应用程序上的本地数据与DynamoDB表中的数据同步。DynamoDB表约有2K行,只有一个散列键(id)和以下属性: id(uuid) lastModifiedAt(时间戳) name 纬度 经度 我目前正在通过lastModifiedAt进行扫描和筛选,其中lastModifiedAt大于应用程序的上次刷新日期,但我认为这将变得昂贵 我能找到的最好方法是添加一个全局二级索引,范围为lastModifiedAt,但GSI没有明显的哈希键 当需要使用GSI按范围查询,但没有明

我需要保持iOS应用程序上的本地数据与DynamoDB表中的数据同步。DynamoDB表约有2K行,只有一个散列键(
id
)和以下属性:

  • id
    (uuid)
  • lastModifiedAt
    (时间戳)
  • name
  • 纬度
  • 经度
我目前正在通过
lastModifiedAt
进行扫描和筛选,其中
lastModifiedAt
大于应用程序的上次刷新日期,但我认为这将变得昂贵

我能找到的最好方法是添加一个全局二级索引,范围为
lastModifiedAt
,但GSI没有明显的哈希键


当需要使用GSI按范围查询,但没有明显的哈希键时,最佳做法是什么?或者,如果完全扫描是唯一选项,是否有任何最佳做法可以降低成本?

您可以使用时间戳的“天”部分作为哈希,并使用完整时间戳作为范围

虽然D.Shawley的回答为我指明了正确的方向,但它忽略了GSI的两个考虑因素:

  • hash+范围需要是唯一的,但是day+时间戳(他推荐的方法)不一定是唯一的
  • 通过仅使用日期作为散列,我需要使用大量查询来获取自上次刷新日期(可能是几个月或几年前)以来每天的结果
  • 因此,以下是我采取的方法:

    • 创建了一个全局二级索引(GSI),哈希键为
      YearMonth
      (例如
      201508
      ),范围为
      id
    • 多次查询GSI,自上次刷新日期起每月查询一次。查询也会通过
      lastModifiedAt>[给定时间戳]
      进行过滤

    尽管
    全局二级索引似乎符合您的要求,但任何试图将
    时间戳
    相关信息作为
    哈希键
    的一部分的尝试都很可能会创建所谓的“热分区”,这是极不可取的

    由于检索最新项目的频率要比检索旧项目的频率高,因此会出现访问不均匀的情况。这不仅会影响您的性能,还会降低解决方案的成本效益

    请参阅文档中的一些详细信息:

    例如,如果一个表有非常少的大量访问 分区键值,甚至可能是一个非常频繁使用的 分区键值,请求流量集中在一个小数目上 分区数–可能只有一个分区。如果工作量 严重失衡,意味着它过度关注 在一个或几个分区中,请求将无法实现总体目标 配置的吞吐量级别。充分利用DynamoDB 吞吐量,创建分区键有大量数据的表 具有不同的值,并且请求的值相当一致,如下所示 尽可能随机地

    根据所述,
    id
    似乎确实是
    散列键
    (又名
    分区键
    )的一个不错的选择,我不会改变这一点,因为GSI键的工作方式与分区相同。另请注意,通过提供整个
    主键
    检索数据时,性能会得到高度优化,因此我们应该尽可能找到一个提供此功能的解决方案

    我建议创建单独的表,根据主键最近的更新情况存储主键。您可以根据最适合您的用例的粒度将数据分割成表。例如,假设您希望按天对更新进行分段:

    a。您的每日更新可以按照以下命名约定存储在表中:
    updates\u DDMM

    b。
    updates\u DDMM
    表将仅具有
    id
    (另一个表的哈希键)

    现在假设最新的应用程序刷新日期是2天前(2016年7月4日),您需要获取最近的记录,然后您需要:

    一,。扫描表
    updates_0504
    updates_0604
    以获取所有哈希键

    二,。最后,通过提交带有所有获得的散列键的
    BatchGetItem
    ,从主表(包含lat/lng、name等)中获取记录

    BatchGetItem
    速度非常快,可以像其他操作一样完成这项工作

    有人可能会说,创建额外的表会增加总体解决方案的成本。。。好吧,使用
    GSI
    您实际上是在复制您的表(如果您投影所有字段),并为所有~2k条记录添加额外的成本,不管这些记录是最近更新的还是未更新的

    创建这样的表似乎有悖直觉,但实际上这是处理时间序列数据的最佳实践(来自AWS DynamoDB文档):

    […]应用程序可能会在所有项目中显示不均匀的访问模式 在表中,最新的客户数据与您的 应用程序可能会更频繁地访问最新的项目,并且随着时间的推移 如果访问这些项目的次数较少,则最终会访问较旧的项目 很少访问。如果这是一个已知的访问模式,您可以使用它 在设计表架构时要考虑到这一点。而不是 将所有项目存储在一个表中,可以使用多个表来 储存这些物品。例如,您可以创建要存储的表 每月或每周数据。用于存储最新版本中的数据的表 数据访问率高的月份或周,要求更高 吞吐量和存储旧数据的表,您可以向下拨 吞吐量和节省资源

    通过将“热”项存储在一个表中,可以节省资源 更高的吞吐量设置,以及另一个表中的“冷”项