使用哈希和范围主键的性能:Dynamodb

我正在使用Node.js和环回来构build一个应用程序。 应用程序的一个组件是将login尝试存储到DynamoDB中。 我对这个数据库很新,而且遇到了问题。

目前,我的散列键是一个电子邮件,我的范围键是login尝试发生时刻的unix时间戳。 基本上,我需要从数据库中获取所有数据,以生成最后一次login尝试的列表。 首先想到的是使用扫描 ,但是它不允许根据持续的login尝试sorting列表。 使用查询的问题是,我必须访问所有的电子邮件,而不仅仅是特定于一个特定电子邮件的项目。 我认为我可以使所有的哈希值相同,但是这样会根据dynamoDB存储它的数据的方式来创build性能问题。

有没有其他人遇到这种types的问题,并有一个解决scheme?

像Amazon DynamoDB这样的NoSQL数据库通过使用特定的主键(“Hash”)来存储和检索数据,效果最佳。 也可以通过主键加上附加值来识别数据(“散列和范围”)。

然而,你想知道“最后一次login”的要求并不适合NoSQL数据库,因为通过数据扫描是非常耗费CPU和IO的。

另一种方法是为每个用户创build一个项目(logging),并在该用户上次login时间的该项目上存储一个属性(类似于“列”的概念)。 这样,你只需要检索一个特定的logging来发现最后的login时间。

如果您还希望保留完整的login尝试历史logging,可以在单独的表上完成,每个login尝试都有一个哈希和范围和一个项目。 这与上面的表格是分开的,每个用户只有一个项目。

您可以尝试缩短您的unix时间戳以从DynamoDB的查询function中受益。

示例模式:

  • 散列键=date
  • 范围键=时间戳
  • 其他属性=电子邮件

示例项目:{“date”:“07/31/2015”,“timestamp”:1438393927,“email”:“abc@def.com”}

使用该模式,特定date内的所有login尝试都将存储在相同的散列键下。 通过提供当前date作为您的散列键,您可以高效地查询最近的login。 你甚至可以进一步钻取,并有一个散列键代表一个小时。

示例查询:

  • KeyConditions:{“date”=“01/01/2015”}
  • ScanIndexForward:false //最近的login名首先

示例结果:

  • {“date”:“01/01/2015”,“timestamp”:1420153200,“email”:“abc@xyz.com”}
  • {“date”:“01/01/2015”,“timestamp”:1420153199,“email”:“def@xyz.com”}
  • {“date”:“01/01/2015”,“timestamp”:1420153198,“email”:“abc@xyz.com”}

Pro :均匀分布的数据,可扩展的,良好的时间局部性,有效的基于时间的查询

Con :在date范围/桶中查询login尝试并不那么简单。 即过去3天的login需要3个独立的查询(每个date一个)

PS :如果您的查询模式需要同时查询date和电子邮件,请使用全局二级索引(GSI) http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html