dynamodb中的scan和query有什么区别?什么时候使用扫描/查询?


84

DynamoDb文档中指定的查询操作:

查询操作仅搜索主键属性值,并支持键属性值上的比较运算符的子集,以优化搜索过程。

和扫描操作:

扫描操作将扫描整个表。在完成扫描后,您可以指定要应用于结果的过滤器,以优化返回给您的值。

最好基于性能和成本方面的考虑。

Answers:


52

创建动态表时,请选择“主键”和“本地二级索引(LSI)”,以便“查询”操作返回所需的项目。

查询操作仅支持对主键进行相等的运算符评估,但对排序键有条件(=,<,<=,>,> =,介于,开始)。

扫描操作通常较慢且较昂贵,因为该操作必须遍历表中的每个项目以获取您要的项目。

例:

Table: CustomerId, AccountType, Country, LastPurchase

Primary Key: CustomerId + AccountType

在此示例中,您可以使用查询操作获取:

  1. 在AccountType上带有条件过滤器的CustomerId

需要使用Scan操作返回:

  1. 具有特定帐户类型的所有客户
  2. 基于国家/地区的条件过滤器的商品,即来自美国的所有客户
  3. 基于LastPurchase的条件过滤器的商品,即上个月进行过购买的所有客户

为了避免对经常使用的操作进行扫描操作,请创建本地二级索引(LSI)或全局二级索引(GSI)。

例:

Table: CustomerId, AccountType, Country, LastPurchase

Primary Key: CustomerId + AccountType
GSI: AccountType + CustomerId
LSI: CustomerId + LastPurchase

在此示例中,查询操作可以使您获得:

  1. 在AccountType上带有条件过滤器的CustomerId
  2. [GSI]针对特定AccountType的CustomerIds的条件过滤器
  3. [LSI]在LastPurchase上具有条件过滤器的CustomerId

1
如果主键:CustomerId + AccountType(我知道CustomerID是分区键,而AccountType是排序键)我认为您只能通过CustomerID或CustomerID + AccountType运行查询操作。如果仅按AccountType搜索,则将进行扫描
-Adil

1
谢谢@Adil。您是正确的,我已经编辑了答案以反映这一点。
金曼


34

您将dynamodb表分区键/主键设置为customer_country。如果使用查询,customer_country则是进行查询操作的必填字段。所有过滤器只能设为所属的项customer_country

如果执行表扫描,则将对所有分区键/主键执行筛选。首先,它从表中获取所有数据并应用过滤器。

例如:

customer_country分区键/主键idsort_key

-----------------------------------

customer_country | name   | id

-----------------------------------
VV               | Tom    | 1

VV               | Jack   | 2

VV               | Mary   | 4

BB               | Nancy  | 5

BB               | Lom    | 6

BB               | XX     | 7

CC               | YY     | 8

CC               | ZZ     | 9

------------------------------------
  • 如果执行查询操作,则仅适用于customer_country值。该值应仅等于运算符(=)。

  • 因此,仅提取与该分区键/主键值相等的项。

  • 如果执行扫描操作,它将获取该表中的所有项目,并在获取数据后过滤掉数据。

注意:请勿执行超出RCU的扫描操作。


您能否说明答案的来源?
AlikElzin-kilaka


10

查询比“扫描”要好得多-明智地执行。顾名思义,scan将扫描整个表。但是您必须非常了解表键,排序键,索引和相关的排序索引,以便知道可以使用查询。如果使用以下方法过滤查询:

  • 键和键排序
  • 指数
  • 索引及其相关的排序键

使用查询!否则,请使用scan,它可以更灵活地选择要过滤的列。

您不能查询是否:

  • 过滤器中超过2个字段(例如键,排序和索引)
  • 仅排序键(具有主键或索引)
  • 常规字段(不是键,索引或排序)
  • 混合索引和排序(带有索引2的索引1)\
  • ...

很好的解释:https : //medium.com/@amos.shahar/dynamodb-query-vs-scan-sql-syntax-and-join-tables-part-1-371288a7cb8f


9

在性能方面,我认为最好将表设计为供应用程序使用,Query而不是Scan。因为扫描操作总是在过滤掉所需的值之前先扫描整个表,所以这意味着需要更多的时间和空间来处理数据操作,例如读取,写入和删除。有关更多信息,请参阅正式文件


7

它与关系数据库中的相似。

query您在使用主键的where情况下,计算复杂度log(n)最高,因为关键结构是二叉树。

scan查询你要扫描整个表,然后应用在每一个过滤器row,以找到合适的结果。表演是O(n)。如果您的桌子很大,它的速度要慢得多。

简而言之,get如果您知道主键,请尝试使用。仅scan在最坏的情况下。

另外,考虑一下全局二级索引以支持对不同键的不同类型的查询,从而获得性能目标。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.