什么是哈希和范围主键?
Posted
技术标签:
【中文标题】什么是哈希和范围主键?【英文标题】:What is Hash and Range Primary Key? 【发布时间】:2015-02-04 10:10:59 【问题描述】:我无法理解 Working with Tables and Data in DynamoDB 文档中的范围/主键是什么
它是如何工作的?
“哈希属性上的无序哈希索引和范围属性上的排序范围索引”是什么意思?
【问题讨论】:
【参考方案1】:“哈希和范围主键”表示 DynamoDB 中的单行具有由 哈希 和 范围 组成的唯一主键强>键。例如,使用 X 的哈希键和 Y 的范围键,您的主键实际上是 XY。同一个哈希键也可以有多个范围键,但组合必须是唯一的,例如 XZ 和 XA。让我们为每种类型的表使用他们的示例:
Hash Primary Key - 主键由一个属性组成,一个哈希 属性。例如,ProductCatalog 表的 ProductID 可以为 它的主键。 DynamoDB 在此基础上构建无序哈希索引 主键属性。
这意味着每一行都与该值无关。 DynamoDB 中的每一行都将为此属性设置一个必需的唯一值。无序哈希索引意味着所说的 - 数据没有排序,并且您无法保证数据的存储方式。 您将无法对无序索引进行查询,例如获取 ProductID 大于 X 的所有行。您根据散列键写入和获取项目。例如,从表中获取 ProductID X 的行。您正在对无序索引进行查询,因此您对它的查询基本上是键值查找,速度非常快,并且使用的吞吐量非常小。
Hash and Range Primary Key – 主键由两个组成 属性。第一个属性是哈希属性,第二个 属性是范围属性。例如论坛 Thread 表 可以将 ForumName 和 Subject 作为其主键,其中 ForumName 是 哈希属性和主题是范围属性。 DynamoDB 构建 散列属性上的无序散列索引和排序范围索引 在范围属性上。
这意味着每一行的主键是散列键和范围键的组合。如果您同时拥有散列键和范围键,则可以直接获取单行,或者您可以针对排序范围索引进行查询。例如,get Get me all rows from the table with Hash key X that have range keys greater than Y,或其他有影响的查询。与针对未索引字段的扫描和查询相比,它们具有更好的性能和更少的容量使用。来自their documentation:
查询结果始终按范围键排序。如果数据类型为 range键为Number,结果按数字顺序返回; 否则,结果按 ASCII 字符码的顺序返回 价值观。默认情况下,排序顺序是升序。要颠倒顺序, 将 ScanIndexForward 参数设置为 false
我在输入此内容时可能遗漏了一些东西,而我只是触及了表面。还有很多更多aspects to take into consideration when working with DynamoDB tables(吞吐量、一致性、容量、其他指标、密钥分布等)。您应该查看sample tables and data 页面以获取示例。
【讨论】:
这是我读过的最有用的堆栈溢出答案之一。 为什么没有选项只能使用没有哈希的范围?例如,如果我的所有数据都以其时间戳作为主键存储,我希望能够选择“2015 年 10 月 15 日下午 2 点到 4 点之间的所有数据” @Teofrostus,哈希键用于标识包含项目的分区。没有它,DynamoDB 将不会查看哪个分区。不知道在哪里查看会破坏查询,并且是扫描(或全局二级索引)的用例,但这不适合您只使用时间的用例系列选择数据)。 @mkobit 有什么方法可以在不扫描的情况下检索给定分区键的所有排序键? @VNR 我不确定我是否理解您在 DynamoDB 上下文中的问题。您是说在提供哈希键时获取所有哈希+范围键吗?【参考方案2】:@mkobit 已经给出了很好解释的答案,但我将添加范围键和哈希键的大图。
简单来说range + hash key = composite primary key
CoreComponents of Dynamodb
主键由散列键和可选范围键组成。 哈希键用于选择 DynamoDB 分区。分区是 部分表数据。范围键用于对 分区(如果存在)。
所以两者都有不同的目的,并且共同帮助进行复杂的查询。
上面的例子hashkey1 can have multiple n-range.
range和hashkey的另一个例子是game,userA(hashkey)
可以玩Ngame(range)
表、项目和属性中描述的 Music 表是一个 具有复合主键的表示例(Artist 和 歌名)。您可以直接访问 Music 表中的任何项目,如果 您为该项目提供 Artist 和 SongTitle 值。
复合主键在查询时为您提供了额外的灵活性 数据。例如,如果您仅提供 Artist、DynamoDB 的值 检索该艺术家的所有歌曲。仅检索子集 特定艺术家的歌曲,您可以为 Artist 提供一个值 以及 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
【讨论】:
在Music
表的示例中,一位艺术家无法制作两首具有相同标题的歌曲,但令人惊讶的是 - 在视频游戏中,我们有 1993 年的《毁灭战士》和 2016 年的《毁灭战士》en.wikipedia.org/wiki/Doom_(franchise) 具有相同的“艺术家” "(开发者):id Software
.
一个超级简单的解释。谢谢!
谢谢,有帮助的回答。【参考方案3】:
由于整个事情正在混淆,让我们看一下它的功能和代码,以简明扼要地模拟它的含义
获取行的唯一方法是通过主键
getRow(pk: PrimaryKey): Row
主键数据结构可以是这样的:
// 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 ||
| +-----------+ +---------------+ | ||
| +--------------------------+|
+----------------------------------------------------------------------------------+
那么上面发生了什么。请注意以下观察结果。正如我们所说,我们的数据属于(Table、Item、KVAttribute)。然后每个项目都有一个主键。现在,您构成该主键的方式对于您如何访问数据是有意义的。
如果您决定 PrimaryKey 只是一个哈希键,那么您可以从中得到一个项目。但是,如果您决定主键是 hashKey + SortKey,那么您还可以对主键进行范围查询,因为您将通过 (HashKey + SomeRangeFunction(on range key)) 获取项目。因此,您可以通过主键查询获取多个项目。
注意:我没有提到二级索引。
【讨论】:
【参考方案4】:@vnr 您可以通过使用分区键的查询来检索与分区键关联的所有排序键。无需扫描。这里的重点是分区键在查询中是强制性的。排序键仅用于获取数据范围
【讨论】:
以上是关于什么是哈希和范围主键?的主要内容,如果未能解决你的问题,请参考以下文章