我应该始终使用哈希和范围主键类型创建我的 DynamoDB 表吗?

Should I always create my DynamoDB tables using hash and range primary key type?

在文档 (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/APISummary.html) 中指出:

You can query only tables whose primary key is of hash-and-range type

we recommend that you design your applications so that you can use the Query operation mostly, and use Scan only where appropriate

虽然没有直接说明,但这是否成为使用散列范围主键的最佳实践?

编辑:

回答 TL;DR:使用对您的数据模型有意义的主键类型,并使用二级索引以获得更好的查询支持。

参考文献:

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html

http://www.allthingsdistributed.com/2013/12/dynamodb-global-secondary-indexes.html

https://forums.aws.amazon.com/thread.jspa?messageID=604862

不一定。最好选择一个支持您的用例访问模式的主键。

例如,假设您想要 用户 的 table。您将存储单个用户的详细信息(姓名、电子邮件、创建者等)。您的访问模式可能是您正在获取特定 User 的详细信息。在这种情况下,使用 hash 类型的主键和 userId.

的散列键更有意义

假设您还想要另一个 table 来存储 Groups。您的访问模式可能是您想要获取给定组的所有成员。在这里,使用 hash 和 range 类型的主键更有意义,您的散列键和范围键分别为 groupIduserId.

需要了解的重要事项是 differences between both key types (quote below) and the Guidelines for Working with Tables:

  • Hash Type Primary Key—The primary key is made of one attribute, a hash attribute. DynamoDB builds an unordered hash index on this
    primary key attribute. Each item in the table is uniquely identified
    by its hash key value.

  • Hash and Range Type Primary Key—The primary key is made of two attributes. The first attribute is the hash attribute and the second
    one is the range attribute. DynamoDB builds an unordered hash index
    on the hash primary key attribute, and a sorted range index on the
    range primary key attribute. Each item in the table is uniquely
    identified by the combination of its hash and range key values. It is possible for two items to have the same hash key value, but those two items must have different range key values.

您可以在 Dynamo DB 中查看有关最佳实践的更多信息Guidelines for Working with Tables documentation

选择使用哪个密钥取决于特定场景的用例和数据要求。例如,如果您要存储 User Session 数据,使用 Range Key 可能没有多大意义,因为每条记录都可以由 GUID 引用,并且无需分组即可直接访问。一般来说,一旦您知道会话 ID,您就可以通过键查询特定项目。另一个例子可能是存储用户帐户或配置文件数据,每个用户都有自己的数据,您很可能会直接访问它(通过用户 ID 或其他方式)。

但是,如果您正在存储 Order Items,那么 Range Key 更有意义,因为您可能想要检索分组的项目根据他们的订单

数据模型 而言,哈希键 允许您从 table 中唯一标识一条记录, Range Key 可以选择性地用于对通常一起检索的几条记录进行分组和排序。示例:如果您正在定义一个聚合来存储 Order ItemsOrder Id 可能是您的 Hash Key,以及 OrderItemId Range Key。每当您想从特定的 Order 中搜索 Order Items 时,只需通过哈希键(Order Id)进行查询,您就会得到您所有的订单商品

您可以在下面找到使用这两个键的正式定义:

"Composite Hash Key with Range Key allows the developer to create a primary key that is the composite of two attributes, a 'hash attribute' and a 'range attribute.' When querying against a composite key, the hash attribute needs to be uniquely matched but a range operation can be specified for the range attribute: e.g. all orders from Werner in the past 24 hours, or all games played by an individual player in the past 24 hours." [VOGELS]

因此Range KeyData Model增加了分组能力,然而,这两个键的使用也有一定的隐含意义存储模型

"Dynamo uses consistent hashing to partition its key space across its replicas and to ensure uniform load distribution. A uniform key distribution can help us achieve uniform load distribution assuming the access distribution of keys is not highly skewed." [DDB-SOSP2007]

Hash Key不仅可以唯一标识记录,而且是保证负载分配的机制。 Range Key(使用时)有助于指示大部分将一起检索的记录,因此,存储也可以针对此类需求进行优化。

选择正确的键来表示您的数据是设计过程中最关键的方面之一,它直接影响您的应用程序的性能、规模和成本。


脚注:

  • 数据模型是我们感知和操作数据的模型。它描述了我们如何与数据库中的数据交互 [FOWLER]。换句话说,它是抽象数据模型的方式、实体分组的方式、选择为主键的属性等

  • 存储模型描述了数据库如何在内部存储和操作数据 [FOWLER]。虽然您不能直接控制它,但您肯定可以通过了解数据库内部的工作方式来优化数据的检索或写入方式。

正如其他人已经说过的 - 不,你不应该。

首先让您感到困惑并导致您提出这个问题的陈述是错误的

You can query only tables whose primary key is of hash-and-range type

可以查询主键为单属性(仅分区)类型的表

证明:

# Create single-attribute primary key table
aws dynamodb create-table --table-name testdb6 --attribute-definitions '[{"AttributeName": "Id", "AttributeType": "S"}]' --key-schema '[{"AttributeName": "Id", "KeyType": "HASH"}]' --provisioned-throughput '{"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}' 

# Populate table
aws dynamodb put-item --table-name testdb6 --item '{ "Id": {"S": "1"}, "LastName": {"S": "Lopez"}, "FirstName": {"S": "Maria"}}'
aws dynamodb put-item --table-name testdb6 --item '{ "Id": {"S": "2"}, "LastName": {"S": "Fernandez"}, "FirstName": {"S": "Augusto"}}'

# Query table using only partition attribute
aws dynamodb query --table-name testdb6 --select ALL_ATTRIBUTES --key-conditions '{"Id": {"AttributeValueList": [{"S": "1"}], "ComparisonOperator": "EQ"}}'

最后一个命令的输出(有效):

{
"Count": 1,
"Items": [
    {
        "LastName": {
            "S": "Lopez"
        },
        "Id": {
            "S": "1"
        },
        "FirstName": {
            "S": "Maria"
        }
    }
],
"ScannedCount": 1,
"ConsumedCapacity": null
}