我阅读了亚马逊入门指南,但是在最终让我的DynamoDB应用程序完成我想要的所有事情之前,仍然花了很长时间陷入多个陷阱并且摸不着头脑。我这样写是为了帮助其他人避免一些陷阱。
您需要做的第一件事就是清除关于关系数据库的所有知识。在设计关系数据库时,您需要从数据模型开始,然后添加索引以支持您要对该模型进行的查询。在DynamoDB中,反过来说,您必须首先考虑要进行的查询,然后构建表以使这些查询高效。在DynamoDB中,您还需要保存多个数据副本以提高查询效率,因此整个方法完全不同。
使用此概念填充您刚刚在脑海中创造的空间。想象一下,您的DynamoDB数据库具有分布在几千台服务器上的数万亿项(行)。每个服务器包含几百万个项目,每个项目仅存在于一个服务器上。每次查询DynamoDB时,它只会将请求发送到其中一个服务器,因此服务器必须包含必须返回的所有数据才能满足您的查询。再慢慢阅读,并考虑一下如何组织数据。
请注意,这是一个非常有用的模型,但实际上,DynamoDB会保留项目的副本副本以确保可靠性。
这意味着如果您想通过姓氏返回所有具有相同姓氏的人必须存储在同一服务器上。如果您还希望按出生年份返回人员,则所有具有相同出生年份的人必须存储在同一服务器上。要同时满足这两个条件,您必须存储两个数据副本!
由于每个查询的结果必须来自一台服务器,因此您必须根据打算查询的方式将数据存储在服务器上。通过在每个表上设置分区键,告诉DynamoDB此信息的方式。分区键是项目属性的名称,用于确定项目将存储在哪个服务器上。查询表时,必须在分区键中传递您要查找的值,以便DynamoDB知道将查询发送到哪个服务器。
例如,如果您创建一个姓氏为人的表作为分区键,那么所有具有相同姓氏的人将存储在同一服务器上。这意味着每次查询此表时,必须选择与姓氏完全匹配的项(以便结果集中的所有项都来自同一服务器),因此针对此表的查询只能返回姓氏相同的人。
如果分区键不是唯一的,则必须指定另一个属性(排序键),该属性在与分区键组合时产生唯一值。在这种情况下,每个服务器将存储按排序键排序的项目,并且在此属性上选择的查询将是高效且便宜的。要继续使用person表示例,因为surname不是唯一的,你需要一个表的排序键,它必须是与姓氏结合时唯一的东西 - 你可以使用政府颁发的ID或GUID作为例子
请注意,无法存储两个具有相同分区键值和排序键值的项目,添加第二个项目时将覆盖第一个项目。
起初这似乎非常严格,但请耐心等待,我们尚未完成。
回顾一下,当您查询表时,查询执行分三个阶段进行。
我在线阅读了一些建议,通过添加一个包含每个项目相同值的属性,并使该属性成为分区键,可以使DynamoDB更加灵活,但请考虑在这种情况下会发生什么。首先,由于所有项目都具有相同的分区键值,因此它们都存储在一台服务器上(请记住,DynamoDB适用于数千台服务器上有数十亿项目的情况,以及它的扩展方式)。其次,任何不包含排序键的查询都需要进行全表扫描,即使只有少数项与查询匹配,也会从后备存储中读取所有这些数十亿项,并且每个项目都需要付费从存储,而不是返回到您的应用程序的项目。
请注意,DynamoDB还有一个scan
函数,可以向所有服务器发送请求,并将结果整理为一个巨大的结果集。这仅适用于导出所有数据的特殊情况,不应用于常规应用程序编程。
许多应用程序需要以多种方式查询数据而不会降低效率。 DynamoDB为此提供了两种二级索引。
本地二级索引与关系数据库中的索引类似,因为它们提供了一种基于特定属性查找项目的有效方法,但它们与关系数据库不同,因为每个服务器仅索引存储在该服务器上的项目。这意味着您必须在匹配二级索引之前选择与基础表的分区键匹配的项(以选择正确的服务器)。这意味着如果人员表上的分区键是姓氏,则针对所有本地二级索引的查询只能返回所有姓氏相同的人。
全局二级索引更像是表而不是索引,因为它们包含它们索引的数据的副本。它们必须包含数据的副本,因为它们具有与基础表不同的分区键,因此这些项目在存储它们的服务器的不同服务器上编制索引。这也意味着如果使用全局二级索引选择项目,则只能返回索引中包含的属性。例如,如果将全局二级索引添加到按名字分区的人员表,则此索引的重复人员记录将分布在服务器上,以使具有相同名字的所有人员都存储在同一服务器上。对此索引的任何查询将始终返回具有完全相同名字的人。
全局二级索引必须包含基础表中的分区键和排序键的副本,以便在更新表时可以自动更新索引。这涉及将数据复制到其他需要时间的服务器,这也是DynamoDB最终一致的原因。
将关系数据库与DynamoDB进行比较:
玩得开心!!
答案 0 :(得分:0)
您需要做的第一件事是清除有关关系数据库的所有知识。在设计关系数据库时,您将从数据模型开始,然后添加索引以支持要针对该模型进行的查询。在DynamoDB中,反之亦然,您必须首先考虑要进行的查询,然后构造表以提高这些查询的效率。在DynamoDB中,您还需要保存多个数据副本以提高查询效率,因此整个方法完全不同。
使用此概念填充您刚刚在脑海中腾出的空间。想象一下,您的DynamoDB数据库中有数千亿个项目(行)分布在数千台服务器上。每个服务器包含几百万个项目,并且每个项目仅存在于一个服务器上。每次查询DynamoDB时,它只会将请求发送到其中一台服务器,因此该服务器必须包含必须返回才能满足您的查询的所有数据。再次慢慢阅读,并思考它对组织数据的意义。
请注意,这是一个有用的模型,但是在实践中,DynamoDB会保留项目的副本副本以确保可靠性。
这意味着,如果要按姓氏返回人,则所有具有相同姓氏的人必须存储在同一服务器上。如果您还想按出生年份返回人员,那么所有具有相同出生年份的人员都必须存储在同一服务器上。为了同时满足这两个条件,您必须存储数据的两个副本!
由于每个查询的结果必须来自一台服务器,因此必须根据查询的方式将数据存储在服务器上。告诉DynamoDB此信息的方式是通过在每个表上设置分区键。分区键是项目属性的名称,该属性确定将项目存储在哪个服务器上。查询表时,必须在分区键中传递要查找的值,以便DynamoDB知道将查询发送到哪个服务器。
例如,如果您创建一个姓氏作为分区键的人表,则所有具有相同姓氏的人都将存储在同一服务器上。这意味着每次查询该表时,您都必须选择与姓氏完全匹配的项(以便结果集中的所有项都来自同一服务器),因此,对该表的查询只能返回姓氏相同的人。
如果分区键不是唯一的,则必须指定另一个属性(排序键),该属性与分区键结合使用时将具有唯一的值。在这种情况下,每个服务器将存储按排序键排序的项目,并且在此属性上选择的查询将是高效且廉价的。要继续进行人员表示例,因为姓氏不是唯一的,所以您需要为该表排序,并且与姓氏结合使用时必须具有唯一性-例如,可以使用政府颁发的ID或GUID
请注意,无法存储两个具有相同分区键和排序键值的项目,当添加第二个项目时,它将覆盖第一个项目。
起初这似乎很严格,但是请允许我,我们还没有完成。
回顾一下,查询表时,查询执行分为三个阶段。
您必须在分区键属性上指定完全匹配。这用于确定哪个服务器包含数据。 只有一台服务器处理该请求。数据按分区键和排序键的顺序物理存储在该服务器上,因此可以使用索引有效地找到匹配的记录。您的查询不必在排序键上完全匹配,可以使用小于,大于等。 如果您的查询选择了其他属性,则这是DynamoDB中的一个筛选器,并且将其应用于在步骤2中选择的所有项目。请注意,所有这些项目都必须从后备存储中读取,并且将向您收费。 我在线阅读了一些建议,可以通过添加包含每个项目相同值的属性并将该属性设置为分区键来使DynamoDB更加灵活,但是请考虑这种情况下会发生什么。首先,由于所有项目都具有相同的分区键值,因此它们都存储在一台服务器上(请记住,DynamoDB是为在数十亿台服务器上分布数十亿个项目的情况而设计的,这就是它的扩展方式)。其次,任何不包含排序键的查询都将需要进行全表扫描,即使只有少数几个与查询匹配的项,也会从后备存储中读取所有数十亿个项,并对从存储中读取的每个项收费,而不是返回给您应用程序的项目。
请注意,DynamoDB还具有扫描功能,该功能将请求发送到所有服务器,并将结果整理到一个巨型结果集中。这仅适用于导出所有数据之类的特殊情况,不应在常规应用程序编程中使用。
许多应用程序需要以多种方式查询数据而不会降低效率。 DynamoDB为此提供了两种辅助索引。
本地二级索引与关系数据库上的索引相似,因为它们提供了一种基于特定属性查找项目的有效方法,但是它们与关系数据库不同,因为每个服务器仅索引该服务器上存储的项目。这意味着您必须先选择与基础表的分区键匹配的项(以选择正确的服务器),然后才能在二级索引上进行匹配。这意味着,如果您的人员表上的分区键是姓氏,则对所有本地二级索引的查询只能返回全部具有相同姓氏的人员。
全局二级索引比索引更像表,因为它们包含索引数据的副本。它们必须包含数据的副本,因为它们具有与基础表不同的分区键,因此,这些项在与存储它们的服务器不同的服务器上建立索引。这也意味着,如果您使用全局二级索引选择项目,则只能返回索引中包含的属性。例如,如果将全局二级索引添加到按名字分区的人员表中,则该索引的重复人员记录将在服务器之间分布,以便所有具有相同名字的人员都存储在同一服务器上。对该索引进行的任何查询都将始终返回姓氏完全相同的人。
全局二级索引必须包含基础表的分区键和排序键的副本,以便在更新表时可以自动更新索引。这涉及到将数据复制到其他服务器上需要花费时间,这就是DynamoDB最终保持一致的原因。
将关系数据库与DynamoDB进行比较:
它们都可以水平扩展以进行读取,因为关系数据库可以具有只读副本。 DynamoDB将自动扩展到数千台服务器,而拥有数千个关系只读副本是不切实际的。 DynamoDB还可以水平扩展写入操作,因为分区键决定了哪个服务器存储每个项目。 关系数据库对于临时查询而言更加灵活和强大。 DynamoDB中的数据必须经过结构化以有效支持非常特定的查询,但是即使存储了数万亿个项目,它也将在几位毫秒内执行这些查询。 玩得开心!