我无法理解在DynamoDB中使用表和数据的文档中的范围/主键是什么

它是如何工作的?

“散列属性上的无序散列索引和范围属性上的有序范围索引”是什么意思?


“哈希和范围主键”意味着DynamoDB中的单行有一个由哈希和范围键组成的唯一主键。例如,如果哈希键为X,范围键为Y,那么主键实际上就是XY。对于同一个散列键,也可以有多个范围键,但组合必须是唯一的,如XZ和XA。让我们用他们的例子来说明每种类型的表格:

哈希主键——主键由一个属性哈希组成 属性。例如,ProductCatalog表可以将ProductID设为 它的主键。DynamoDB在此基础上构建一个无序哈希索引 主键属性。

This means that every row is keyed off of this value. Every row in DynamoDB will have a required, unique value for this attribute. Unordered hash index means what is says - the data is not ordered and you are not given any guarantees into how the data is stored. You won't be able to make queries on an unordered index such as Get me all rows that have a ProductID greater than X. You write and fetch items based on the hash key. For example, Get me the row from that table that has ProductID X. You are making a query against an unordered index so your gets against it are basically key-value lookups, are very fast, and use very little throughput.


哈希和范围主键——主键由两个组成 属性。第一个属性是散列属性,第二个属性是散列属性 Attribute是range属性。例如,论坛Thread表 可以有论坛名和主题作为其主键,论坛名在哪里 哈希属性和Subject是范围属性。DynamoDB构建 散列属性上的无序散列索引和排序范围索引 在range属性上。

This means that every row's primary key is the combination of the hash and range key. You can make direct gets on single rows if you have both the hash and range key, or you can make a query against the sorted range index. For example, get Get me all rows from the table with Hash key X that have range keys greater than Y, or other queries to that affect. They have better performance and less capacity usage compared to Scans and Queries against fields that are not indexed. From their documentation:

查询结果总是按范围键排序。的数据类型 范围键为Number,结果按数字顺序返回; 否则,结果将按ASCII字符码的顺序返回 值。默认情况下,排序顺序为升序。颠倒一下顺序, 设置ScanIndexForward参数为false

我可能错过了一些东西,因为我打出来,我只抓了表面。在使用DynamoDB表时,还有很多方面需要考虑(吞吐量、一致性、容量、其他索引、键分布等)。您应该查看示例表和数据页以获得示例。


@vnr您可以通过使用分区键查询检索与分区键关联的所有排序键。无需扫描。这里的重点是分区键在查询中是强制的。排序键仅用于获取数据范围


由于整个事情是混合的,让我们看看它的函数和代码来模拟它的意思

获取一行的唯一方法是通过主键

getRow(pk: PrimaryKey):行

主键数据结构可以是这样的:

// If you decide your primary key is just the partition key.
class PrimaryKey(partitionKey: String)

// and in thids case
getRow(somePartitionKey): Row

然而,在这种情况下,你可以决定你的主键是分区键+排序键:

// if you decide your primary key is partition key + sort key
class PrimaryKey(partitionKey: String, sortKey: String)

getRow(partitionKey, sortKey): Row
getMultipleRows(partitionKey): Row[]

所以底线是: 确定你的主键只是分区键?按分区键获取单行。 决定你的主键是分区键+排序键? 2.1通过(分区键,排序键)获取单行或通过(分区键)获取行范围

无论哪种方式,你都可以通过主键获得一行,唯一的问题是你是否将主键定义为仅为分区键或分区键+排序键

构建模块是:

表格 项 KV属性。

将Item视为一行,KV Attribute视为该行中的单元格。

您可以通过主键获取一个项(一行)。 你可以通过指定(HashKey, RangeKeyQuery)来获取多个项目(多行)

只有当你决定你的PK由(HashKey, SortKey)组成时,你才能执行(2)。

更直观的是,它的复杂,我是这样看的:

+----------------------------------------------------------------------------------+
|Table                                                                             |
|+------------------------------------------------------------------------------+  |
||Item                                                                          |  |
||+-----------+ +-----------+ +-----------+ +-----------+                       |  |
|||primaryKey | |kv attr    | |kv attr ...| |kv attr ...|                       |  |
||+-----------+ +-----------+ +-----------+ +-----------+                       |  |
|+------------------------------------------------------------------------------+  |
|+------------------------------------------------------------------------------+  |
||Item                                                                          |  |
||+-----------+ +-----------+ +-----------+ +-----------+ +-----------+         |  |
|||primaryKey | |kv attr    | |kv attr ...| |kv attr ...| |kv attr ...|         |  |
||+-----------+ +-----------+ +-----------+ +-----------+ +-----------+         |  |
|+------------------------------------------------------------------------------+  |
|                                                                                  |
+----------------------------------------------------------------------------------+

+----------------------------------------------------------------------------------+
|1. Always get item by PrimaryKey                                                  |
|2. PK is (Hash,RangeKey), great get MULTIPLE Items by Hash, filter/sort by range     |
|3. PK is HashKey: just get a SINGLE ITEM by hashKey                               |
|                                                      +--------------------------+|
|                                 +---------------+    |getByPK => getBy(1        ||
|                 +-----------+ +>|(HashKey,Range)|--->|hashKey, > < or startWith ||
|              +->|Composite  |-+ +---------------+    |of rangeKeys)             ||
|              |  +-----------+                        +--------------------------+|
|+-----------+ |                                                                   |
||PrimaryKey |-+                                                                   |
|+-----------+ |                                       +--------------------------+|
|              |  +-----------+   +---------------+    |getByPK => get by specific||
|              +->|HashType   |-->|get one item   |--->|hashKey                   ||
|                 +-----------+   +---------------+    |                          ||
|                                                      +--------------------------+|
+----------------------------------------------------------------------------------+

上面发生了什么。请注意以下观察结果。正如我们所说,我们的数据属于(表,项目,KVAttribute)。那么每个项目都有一个主键。现在,组成主键的方式对于如何访问数据是有意义的。

如果你决定你的PrimaryKey只是一个哈希键,那么很好,你可以得到一个单一的项目。如果你决定你的主键是hashKey + SortKey,那么你也可以在你的主键上进行范围查询,因为你将通过(hashKey + SomeRangeFunction(在范围键上))获得你的项目。所以你可以用你的主键查询得到多个项目。

注:我没有提到二级索引。


@mkobit已经给出了一个很好的解释,但我将添加一个范围键和散列键的大图片。

简单地说,范围+哈希键=复合主键

主键由一个散列键和一个可选的范围键组成。 哈希键用于选择DynamoDB分区。分区 部分表数据。列表中的项进行排序 分区,如果存在的话。

所以两者都有不同的目的,一起帮助做复杂的查询。 在上面的例子中,hashkey1可以有多个n-range。范围和hashkey的另一个例子是game, userA(hashkey)可以玩Ngame(range)

The Music table described in Tables, Items, and Attributes is an example of a table with a composite primary key (Artist and SongTitle). You can access any item in the Music table directly, if you provide the Artist and SongTitle values for that item. A composite primary key gives you additional flexibility when querying data. For example, if you provide only the value for Artist, DynamoDB retrieves all of the songs by that artist. To retrieve only a subset of songs by a particular artist, you can provide a value for Artist along with a range of values for SongTitle.

https://www.slideshare.net/InfoQ/amazon-dynamodb-design-patterns-best-practices https://www.slideshare.net/AmazonWebServices/awsome-day-2016-module-4-databases-amazon-dynamodb-and-amazon-rds https://ceyhunozgun.blogspot.com/2017/04/implementing-object-persistence-with-dynamodb.html


对于那些同样对术语感到困惑的人来说:

项的分区键也称为其哈希属性。的 术语哈希属性来源于内部哈希函数的使用 在DynamoDB中,在各个分区中均匀分布数据项, 基于它们的分区键值。 项的排序键也称为它的范围属性。这个词 range属性派生自DynamoDB存储项的方式 相同的分区键物理上紧靠在一起,按 排序键值。

来源:“Amazon DynamoDB的核心组件”