【问题标题】:What is Hash and Range Primary Key?什么是哈希和范围主键?
【发布时间】:2015-02-04 10:10:59
【问题描述】:

我无法理解 Working with Tables and Data in DynamoDB 文档中的范围/主键是什么

它是如何工作的?

“哈希属性上的无序哈希索引和范围属性上的排序范围索引”是什么意思?

【问题讨论】:

    标签: hash amazon-dynamodb primary-key database nosql


    【解决方案1】:

    哈希和范围主键”表示 DynamoDB 中的单行具有由 哈希范围 组成的唯一主键强>键。例如,使用 X 的哈希键和 Y 的范围键,您的主键实际上是 XY。同一个哈希键也可以有多个范围键,但组合必须是唯一的,例如 XZXA。让我们为每种类型的表使用他们的示例:

    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 keyCoreComponents 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[]
    

    所以底线:

    1. 决定你的主键只是分区键?按分区键获取单行。

    2. 确定你的主键是分区键+排序键? 2.1 通过(分区键、排序键)获取单行或通过(分区键)获取行范围

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

    构建块是:

    1. 项目
    2. KV 属性。

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

    1. 您可以通过主键获取一个项目(一行)。
    2. 可以通过指定(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 您可以通过使用分区键的查询来检索与分区键关联的所有排序键。无需扫描。这里的重点是分区键在查询中是强制性的。排序键仅用于获取数据范围

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-03
        • 2012-01-26
        • 1970-01-01
        • 2021-02-24
        • 2016-12-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多