客户的期望和相应的应用需求从未如此之高。用户期望应用程序快速、可靠且可用。此外,数据为王,用户希望能够根据需要对聚合数据进行切片和切块以找到见解。用户不想等待数据工程师提供新索引或构建新 ETL 链。他们希望不受限制地访问可用的最新数据。 但对于任何单一数据库来说,处理所有应用程序需求都是一项艰巨的任务。对于数据库来说,针对单个记录的频繁、低延迟操作进行优化不同于针对不那么频繁的聚合或跨多个记录的大量过滤进行优化。很多时候,我们尝试使用相同的数据库处理这两种模式,并随着应用程序的扩展而处理不一致的性能。我们认为我们正在以最小的努力或成本进行优化,而事实上我们正在做相反的事情。在 OLTP 数据库上运行分析通常需要我们过度配置数据库以应对流量峰值。这最终会花费大量资金,并且通常无法提供令人满意的最终用户体验。 在本演练中,我们将了解如何使用这两种访问模式来满足用户的高要求。我们将构建一个金融应用程序,用户可以在其中记录交易并查看最近的交易,同时还希望对过去的交易进行复杂的过滤或聚合。 混合方法 为了满足我们的应用程序需求,我们将使用 和 。 DynamoDB 将处理我们的核心事务访问模式——记录事务并提供最近事务的提要供用户浏览。 Rockset 将补充 DynamoDB 来处理我们的数据密集型、“令人愉快的”访问模式。我们将让用户按时间、商家、类别或其他字段进行过滤,以查找相关交易,或执行强大的聚合以查看一段时间内的支出趋势。 Amazon DynamoDB Rockset 当我们研究这些模式时,我们将看到每个系统如何适合手头的工作。 DynamoDB 擅长核心 OLTP 操作 - 读取或写入单个项目,或基于已知过滤器获取一系列连续项目。由于基于主键对数据进行分区的方式,DynamoDB 能够为任何规模的这些类型的查询提供一致的性能。 相反,Rockset 擅长连续摄取大量数据,并对这些数据采用多种索引策略,以提供高度选择性的过滤、实时或查询时聚合以及 DynamoDB 无法轻松处理的其他模式。 当我们完成这个示例时,我们将学习这两个系统的基本概念以及实现目标的实际步骤。您可以使用 来跟踪该应用程序。 GitHub 存储库 使用 DynamoDB 实施核心功能 我们将通过实现应用程序的核心功能来开始本演练。这是任何应用程序的共同起点,因为您构建标准“CRUDL”操作以提供操作单个记录和列出一组相关记录的能力。 对于电子商务应用程序,这将是下订单和查看以前的订单的功能。对于社交媒体应用程序,这将是创建帖子、添加朋友或查看您关注的人。此功能通常由专门 工作流的数据库实现,该工作流强调针对少量行的许多并发操作。 从事联机事务处理 (OLTP) 对于此示例,我们正在构建一个企业财务应用程序,用户可以在其中进行付款和接收付款,以及查看其交易历史记录。 在本演练中,该示例将被有意简化,但您可以为我们的应用程序想到三种核心访问模式: ,它将存储企业支付或收到的付款记录; 记录交易 ,这将允许用户查看企业最近支付和收到的付款;和 按日期范围查看交易 ,这将允许用户深入了解单个交易的细节。 查看单个交易 这些访问模式中的每一种都是关键的、大容量的访问模式。我们将不断地为用户记录交易,交易源将是他们打开应用程序时的第一个视图。此外,这些访问模式中的每一个都将使用已知的、一致的参数来获取相关记录。 我们将使用 DynamoDB 来处理这些访问模式。 DynamoDB 是 AWS 提供的 NoSQL 数据库。它是一个完全托管的数据库,在大规模应用程序和无服务器应用程序中越来越受欢迎。 DynamoDB 最独特的功能之一是它如何在任何规模下提供一致的性能。无论您的表是 1 MB 还是 1 PB,您都应该看到相同的操作响应时间。对于像我们在这里实施的那样的核心 OLTP 用例来说,这是一个理想的品质。这是一项伟大而有价值的工程成就,但重要的是要了解它是通过选择性执行良好的查询类型来实现的。 DynamoDB 能够通过两个核心设计决策提供这种一致的性能。首先,DynamoDB 表中的每条记录都必须包含一个主键。该主键由分区键和可选的排序键组成。 DynamoDB 的第二个关键设计决策是 API 严格强制使用主键 - 稍后将详细介绍。 在下图中,我们的金融科技应用程序中有一些示例交易数据。我们的表使用应用程序中组织名称的分区键,以及基于 的排序键,该排序键提供 UUID 的唯一性特征以及按创建时间的可排序性,使我们能够进行基于时间的查询。 ULID 表中的记录包括其他属性,例如商家名称、类别和金额,这些属性在我们的应用程序中很有用,但对于 DynamoDB 的底层架构并不那么重要。重要的部分是主键,特别是分区键。 在幕后,DynamoDB 会将您的数据拆分为多个存储分区,每个分区都包含表中数据的子集。 DynamoDB 使用主键的分区键元素将给定记录分配给特定存储分区。 随着表中的数据量或表的流量增加,DynamoDB 将添加分区作为水平扩展数据库的一种方式。 如上所述,DynamoDB 的第二个关键设计决策是 API 严格强制使用主键。 DynamoDB 中的几乎所有 API 操作都至少需要主键的分区键。因此,DynamoDB 能够快速将任何请求路由到正确的存储分区,无论分区数量和表的总大小如何。 考虑到这两个权衡,您使用 DynamoDB 的方式必然会受到限制。您必须预先仔细规划和设计您的访问模式,因为您的主键必须包含在您的访问模式中。稍后更改访问模式可能会很困难,并且可能需要一些手动迁移步骤。 当您的用例属于 DynamoDB 的核心能力时,您将受益匪浅。无论规模如何,您都将获得一致、可预测的性能,并且您的应用程序不会随着时间的推移而出现长期性能下降。此外,您将获得完全托管的体验和较低的运营负担,使您能够专注于对业务重要的事情。 我们示例中的核心操作与该模型完美契合。检索组织的交易源时,我们的应用程序中将提供可用的组织 ID,这将允许我们使用 DynamoDB 操作来获取具有相同分区键的连续记录集。要检索特定事务的其他详细信息,我们将拥有组织 ID 和事务 ID,以发出 DynamoDB 请求来获取所需的项目。 查询 GetItem 您可以通过 查看这些操作的实际效果。按照说明部署应用程序并为其添加示例数据。然后,向已部署的服务发出 HTTP 请求以获取各个用户的事务源。无论并发请求数量或 DynamoDB 表的大小如何,这些操作都将是快速、高效的操作。 示例应用程序 使用 Rockset 补充 DynamoDB 到目前为止,我们已经使用 DynamoDB 来处理我们的核心访问模式。 DynamoDB 非常适合这些模式,因为其基于键的分区将在任何规模下提供一致的性能。 然而,DynamoDB 不擅长处理其他访问模式。 DynamoDB 不允许您通过主键以外的属性进行高效查询。您可以使用 通过附加属性重新索引数据,但如果您有许多不同的属性可用于对数据进行索引,则仍然可能出现问题。 DynamoDB 的二级索引 此外,DynamoDB 不提供任何开箱即用的聚合功能。您可以使用 DynamoDB 计算自己的聚合,但与预先设计聚合的解决方案相比,它的灵活性可能会降低或读取消耗未优化。 为了处理这些模式,我们将 。 使用 Rockset 来补充 DynamoDB Rockset 最好被视为数据的辅助索引集。 Rockset 仅在查询时使用这些索引,并且在读取期间不会将任何负载投射回 DynamoDB。 Rockset 不是从应用程序客户端进行单独的事务性更新,而是为从主数据存储中进行连续的流式摄取而设计。它具有许多主要数据存储的直接连接器,包括 DynamoDB、MongoDB、Kafka 和许多关系数据库。 当 Rockset 从主数据库获取数据时,它会在 中对数据进行索引,该索引借用了以下概念:行索引、倒排索引和列索引。其他索引(例如范围、类型和地理空间)会根据提取的数据类型自动创建。我们将在下面讨论这些索引的具体细节,但此聚合索引允许对数据进行更灵活的访问模式。 聚合索引 这是 Rockset 背后的核心概念——它是数据的二级索引,使用来自主数据存储的完全托管、近乎实时的摄取管道。 长期以来,团队一直在从 DynamoDB 中提取数据并将其插入到另一个系统中以处理其他用例。在详细介绍 Rockset 如何从表中提取数据之前,我们先简要讨论一下 Rockset 与该领域其他选项的不同之处。 Rockset 和其他方法之间存在一些核心差异。 首先,Rockset 是完全托管的。您不仅不需要管理数据库基础设施,而且也不需要维护将数据提取、转换和加载到 Rockset 中的管道。对于许多其他解决方案,您负责系统之间的“粘合”代码。这些系统至关重要但容易出现故障,因为您必须防御性地防止数据结构发生任何变化。上游的变化可能会给下游系统的维护人员带来痛苦。 其次,Rockset可以以可变的方式处理实时数据。对于许多其他系统,您可以选择其中之一。您可以选择定期导出和批量加载数据,但这会导致加载之间的数据过时。或者,您可以以仅追加的方式将数据流式传输到数据仓库中,但无法对更改的数据执行就地更新。 Rockset 能够像插入新数据一样快速高效地处理现有项目的更新,因此可以让您实时查看不断变化的数据。 第三,Rockset自动生成索引。其他“完全托管”解决方案仍然需要您配置索引,因为您需要它们支持新查询。 Rockset 的查询引擎旨在使用一组索引来支持任何和所有查询。当您向系统添加越来越多的查询时,您不需要添加额外的索引,从而占用越来越多的空间和计算资源。这也意味着即席查询也可以充分利用索引,使其速度更快,而无需等待管理员添加定制索引来支持它们。 Rockset 如何从 DynamoDB 获取数据 现在我们已经了解了 Rockset 是什么以及它如何帮助我们的基础知识,让我们将 DynamoDB 表连接到 Rockset。在此过程中,我们将了解 Rockset 摄取过程的工作原理以及它与其他选项的不同之处。 Rockset 为许多数据源提供了专门构建的连接器,具体的连接器实现取决于上游数据源的具体情况。 为了与 DynamoDB 连接,Rockset 依赖 。 DynamoDB Streams 是 DynamoDB 的一项更改数据捕获功能,其中针对 DynamoDB 表的每个写入操作的详细信息都记录在流中。流的使用者可以按照表中发生的相同顺序处理这些更改,以更新下游系统。 DynamoDB Streams DynamoDB Stream 非常适合 Rockset 近乎实时地了解 DynamoDB 表的最新情况,但这并不是全部。 DynamoDB Stream 仅包含在表上启用 Stream 后发生的写入操作的记录。此外, 。在启用流之前或超过 24 小时之前发生的操作将不会出现在流中。 DynamoDB Stream 仅保留记录 24 小时 但 Rockset 不仅需要最新的数据,还需要数据库中的所有数据才能正确回答您的查询。为了处理这个问题,它会执行初始批量导出(使用 DynamoDB Scan 或 ,具体取决于您的表大小)以获取表的初始状态。 导出到 S3 因此,Rockset 的 DynamoDB 连接过程分为两部分: 用于导出完整表以摄取到 Rockset 的初始 过程; 引导 随后的 过程,用于使用 DynamoDB Stream 中的更新并更新 Rockset 中的数据。 连续 请注意,这两个进程均由 Rockset 完全管理,并且对用户而言是透明的。您将不负责维护这些管道并在出现错误时响应警报。 此外,如果您为初始摄取过程选择 S3 导出方法,则两个 Rockset 摄取过程都不会消耗主表中的读取容量单位。因此,Rockset 不会占用您的应用程序用例的消耗或影响生产可用性。 应用程序:将 DynamoDB 连接到 Rockset 在继续在我们的应用程序中使用 Rockset 之前,让我们将 Rockset 连接到我们的 DynamoDB 表。 首先,我们需要在 Rockset 和我们的表之间创建一个新的集成。我们将逐步完成下面的高级步骤,但如果需要,您可以 。 在应用程序存储库中找到更详细的分步说明 在 Rockset 控制台中,导航到 以启动此过程。 新的集成向导 在集成向导中,选择 作为您的集成类型。然后,单击 进入下一步。 Amazon DynamoDB “开始” DynamoDB 集成向导提供了授权 Rockset 访问您的 DynamoDB 表的分步说明。这需要为表导出创建 IAM 策略、IAM 角色和 S3 存储桶。 如果您愿意,可以按照这些说明手动创建资源。在无服务器世界中,我们更喜欢尽可能通过 来创建事物,其中包括这些支持资源。 基础设施即代码 示例存储库包含创建 Rockset 集成资源所需的基础设施即代码。要使用这些,首先在 Rockset 集成向导底部找到 Rockset 帐户 ID 和外部 ID 值。 将这些值复制并粘贴到 serverless.yml 文件的 块 中。然后, 以创建这些资源。 custom 的相关部分 取消注释 serverless.yml 第 71 到 122 行的资源 重新部署您的应用程序以创建这些新资源。在部署的输出中,将 S3 存储桶名称和 IAM 角色 ARN 复制并粘贴到 Rockset 控制台中的适当位置。 然后,单击保存集成按钮以保存您的集成。 创建集成后,您将需要从集成创建 。导航到 Rockset 控制台中的 ,然后按照步骤使用集成创建集合。您还可以在应用程序存储库中找到 。 Rockset 集合 集合创建向导 创建集合的分步说明 一旦完成此连接,通常在一组适当大小的实例上,对 DynamoDB 中数据的插入、更新或删除将反映在 Rockset 的索引中,并可在不到 2 秒的时间内进行查询。 使用 Rockset 进行复杂过滤 现在我们已将 Rockset 连接到 DynamoDB 表,让我们看看 Rockset 如何在现有数据上启用新的访问模式。 回想一下我们的核心功能部分,DynamoDB 非常关注您的主键。您必须使用主键才能有效访问数据。因此,我们构建表以在主键中使用组织名称和交易时间。 这种结构适用于我们的核心访问模式,但我们可能希望为用户提供更灵活的方式来浏览其交易。有许多有用的属性——类别、商家名称、金额等——可用于过滤。 我们可以使用 DynamoDB 的二级索引来过滤更多属性,但这仍然不太适合。 DynamoDB 的主键结构不容易实现涉及许多可选属性组合的灵活查询。您可以有一个二级索引来按商家名称和日期进行过滤,但如果您想允许按商家名称、日期和金额进行过滤,则需要另一个二级索引。按类别过滤的访问模式需要第三个二级索引。 我们将在这里依靠 Rockset,而不是处理这种复杂性。 我们之前看到 Rockset 使用聚合索引以多种方式对数据进行索引。其中一种方法是倒排索引。通过倒排索引,Rockset 直接对每个属性进行索引。 请注意该索引的组织方式。每个属性名称和值用作索引的键,值是包含相应属性名称和值的文档ID列表。键的构造使其自然排序顺序可以有效地支持范围查询。 倒排索引非常适合具有选择性过滤条件的查询。想象一下,我们希望允许用户过滤他们的交易以查找符合特定条件的交易。 Vandelay Industries 组织中的某人对他们最近订购 Chipotle 的次数感兴趣。 您可以通过如下查询找到它: SELECT * FROM transactions WHERE organization = 'Vandelay Industries' AND merchant_name = 'Chipotle' 因为我们对客户和商家名称进行选择性过滤,所以我们可以使用倒排索引来快速找到匹配的文档。 Rockset 将在倒排索引中查找属性名称和值对,以找到匹配文档的列表。 一旦有了这两个列表,它就可以将它们合并以找到与两组条件都匹配的记录集,并将结果返回给客户端。 就像 DynamoDB 基于分区的索引对于使用分区键的操作非常有效一样,Rockset 的倒排索引可以让您对数据集中的任何字段进行高效查找,甚至可以对嵌入对象的属性或嵌入数组内的值进行高效查找。 应用程序:在您的应用程序中使用 Rockset API 现在我们知道了 Rockset 如何有效地对我们的数据集执行选择性查询,让我们逐步了解将 Rockset 查询集成到我们的应用程序中的实际方面。 Rockset 公开受授权令牌保护的 RESTful 服务。 SDK 也可用于流行的编程语言。这使得它非常适合与无服务器应用程序集成,因为您不需要设置复杂的专用网络配置来访问数据库。 为了与我们的应用程序中的 Rockset API 进行交互,我们需要一个 Rockset API 密钥。您可以在 Rockset 控制台的 创建一个。完成此操作后,将其值复制到您的 serverless.yml 文件中并重新部署以使其可供您的应用程序使用。 API 密钥部分 附注:为了简单起见,我们使用此 API 密钥作为环境变量。在实际应用程序中,您应该使用 或 之类的工具来存储您的密钥并避免环境变量。 Parameter Store AWS Secrets Manager 查看我们的 了解我们如何与 Rockset API 交互。类初始化采用 Rockset 客户端对象,该对象将用于调用 Rockset。 TransactionService 类, 在 中,我们有以下查询来与Rockset交互: 我们的服务类的filterTransactions方法 const response = await this._rocksetClient.queries.query({ sql: { query: ` SELECT * FROM Transactions WHERE organization = :organization AND category = :category AND amount BETWEEN :minAmount AND :maxAmount ORDER BY transactionTime DESC LIMIT 20`, parameters: [ { name: "organization", type: "string", value: organization, }, { name: "category", type: "string", value: category, }, { name: "minAmount", type: "float", value: minAmount, }, { name: "maxAmount", type: "float", value: maxAmount, }, ], }, }); 关于这种互动,有两点需要注意。首先,在处理用户输入时,我们在查询中使用命名参数。这是 SQL 数据库的常见做法,以避免 SQL 注入攻击。 其次,SQL 代码与我们的应用程序代码混合在一起,随着时间的推移可能很难跟踪。虽然这可行,但还有更好的方法。当我们应用下一个用例时,我们将了解如何在应用程序中使用 Rockset Query Lambda。 使用 Rockset 进行聚合 到目前为止,我们已经回顾了 DynamoDB 和 Rockset 的索引策略,讨论了数据库如何找到与特定过滤谓词匹配的单个记录或记录集。例如,我们看到 DynamoDB 推动您使用主键来查找记录,而 Rockset 的倒排索引可以使用高度选择性的过滤条件有效地查找记录。 在最后一节中,我们将稍微调整一下方向,重点关注数据布局而不是直接索引。在考虑数据布局时,我们将对比两种方法:基于行与基于列。 基于行的数据库,顾名思义,将其数据按行排列在磁盘上。大多数关系数据库(例如 PostgreSQL 和 MySQL)都是基于行的数据库。许多 NoSQL 数据库(例如 DynamoDB)也是如此,即使它们的记录在技术上不是关系数据库意义上的“行”。 基于行的数据库非常适合我们迄今为止所了解的访问模式。当通过 ID 获取单个交易或根据某些过滤条件获取一组交易时,我们通常希望返回每个交易的所有字段。由于记录的所有字段都存储在一起,因此通常需要一次读取才能返回记录。 (注意:稍后会出现一些细微差别)。 聚合则完全是另一回事。通过聚合查询,我们希望计算聚合——所有交易的计数、交易总额的总和或一组交易的每月平均支出。 回到 Vandelay Industries 组织的用户,假设他们想要查看过去三个月并查找每个月按类别的总支出。该查询的简化版本如下所示: SELECT category, EXTRACT(month FROM transactionTime) AS month, sum(amount) AS amount FROM transactions WHERE organization = 'Vandelay Industries' AND transactionTime > CURRENT_TIMESTAMP() - INTERVAL 3 MONTH GROUP BY category, month ORDER BY category, month DESC 对于此查询,可能需要读取大量记录来计算结果。但是,请注意,我们的每条记录并不需要很多字段。我们只需要四个——类别、交易时间、组织和金额——来确定这个结果。 因此,我们不仅需要读取更多记录来满足此查询,而且基于行的布局将读取一堆对我们的结果来说不必要的字段。 相反,基于列的布局将数据按列存储在磁盘上。 Rockset 的聚合索引使用列式索引以基于列的布局存储数据。在基于列的布局中,数据按列存储在一起。单个记录被分解为其组成列以进行索引。 如果我的查询需要进行聚合来对大量记录的“金额”属性求和,Rockset 可以通过简单地扫描列式索引的“金额”部分来完成此操作。与基于行的布局相比,这大大减少了读取和处理的数据量。 请注意,默认情况下,Rockset 的列索引不会对列中的属性进行排序。因为我们有面向用户的用例,这些用例将对特定客户的数据进行操作,所以我们更愿意按客户组织列式索引,以减少使用列式索引时要扫描的数据量。 Rockset 来帮助解决此问题。通过集群,我们可以表明我们希望我们的列式索引通过“组织”属性进行集群。这将按列索引中的组织对所有列值进行分组。因此,当 Vandelay Industries 对其数据进行聚合时,Rockset 的查询处理器可以跳过其他客户的列式索引部分。 在列式索引上提供数据集群 Rockset 的基于行的索引如何帮助处理 在我们继续在应用程序中使用柱状索引之前,我想谈谈 Rockset 聚合索引的另一个方面。 之前,我提到在检索完整记录时使用基于行的布局,并指出 DynamoDB 和我们的 Rockset 反向索引查询都在使用这些布局。 这只是部分正确。倒排索引与基于列的索引有一些相似之处,因为它将列名和值存储在一起,以便通过任何属性进行高效查找。每个索引条目都包含一个指向包含给定列名和值组合的记录 ID 的指针。一旦从倒排索引中发现了相关的 ID,Rockset 就可以使用行索引检索完整记录。 Rockset 使用字典编码和其他先进的压缩技术来最小化数据存储大小。 因此,我们现在已经了解了 Rockset 的聚合索引如何组合在一起: 用于快速扫描特定列中的大量值进行聚合; 基于列的索引 用于对任何列名和值进行选择性过滤; 倒排索引 用于获取投影子句中可能引用的任何附加属性。 基于行的索引 在幕后,Rockset 强大的索引和查询引擎正在跟踪数据统计信息并生成最佳计划来高效执行查询。 应用程序:在应用程序中使用 Rockset Query Lambda 让我们实现使用列索引的 Rockset 聚合查询。 对于之前的查询,我们将 SQL 查询直接写入 Rockset API。虽然对于某些高度可定制的用户界面来说这是正确的做法,但当 SQL 代码更加静态时,还有更好的选择。我们希望避免在应用程序逻辑中维护混乱的 SQL 代码。 为了帮助解决这个问题,Rockset 有一个名为 Query Lambdas 的功能。查询 Lambda 是在 Rockset 控制台中注册的命名、版本化、参数化查询。在 Rockset 中配置查询 Lambda 后,您将收到一个完全托管、可扩展的查询 Lambda 端点,您可以使用要由 Rockset 执行的参数进行调用。此外,您甚至可以获得每个 Query Lambda 的监控统计信息,以便您可以跟踪 Query Lambda 在您进行更改时的执行情况。 您可以 ,但让我们设置第一个 Query Lambda 来处理聚合查询。 。 在此处了解有关 Query Lambda 的更多信息 完整的演练可以在应用程序存储库中找到 导航到 Rockset 控制台的 。将以下查询粘贴到编辑器中: 查询编辑器部分 SELECT category, EXTRACT( month FROM transactionTime ) as month, EXTRACT( year FROM transactionTime ) as year, TRUNCATE(sum(amount), 2) AS amount FROM Transactions WHERE organization = :organization AND transactionTime > CURRENT_TIMESTAMP() - INTERVAL 3 MONTH GROUP BY category, month, year ORDER BY category, month, year DESC 此查询将根据给定类别和交易月份将给定组织过去三个月的交易分组到存储桶中。然后,它将按月对某个类别的值进行求和,以找出每个月的支出总额。 请注意,它包含“organization”属性的参数,如查询中的“:organization”语法所示。这表示必须向上传递组织值才能执行查询。 在 Rockset 控制台中将查询保存为查询 Lambda。然后,查看 。它按名称调用 Query Lambda 并传递用户指定的“组织”属性。 我们的 TransactionService 类中的 fetchTransactionsByCategoryAndMonth 代码 这是我们应用程序中处理起来更简单的代码。此外,Rockset 为每个 Query Lambda 提供版本控制和特定于查询的监控。这使得您可以更轻松地长期维护查询并了解查询语法的更改如何影响性能。 结论 在这篇文章中,我们了解了如何结合使用 DynamoDB 和 Rockset 为用户构建快速、愉快的应用程序体验。在此过程中,我们学习了实现应用程序的概念基础和实际步骤。 首先,我们使用 DynamoDB 来处理应用程序的核心功能。这包括访问模式,例如检索特定客户的交易源或查看单个交易。由于 DynamoDB 基于主键的分区策略,它能够在任何规模下提供一致的性能。 但DynamoDB的设计也限制了它的灵活性。它无法处理对任意字段的选择性查询或跨大量记录的聚合。 为了处理这些模式,我们使用了 Rockset。 Rockset 提供完全托管的二级索引来支持数据密集型应用程序。我们了解了 Rockset 如何从主数据存储中维护一个连续的摄取管道,该管道在聚合索引中对数据进行索引,该索引结合了倒排索引、列式索引和行索引。当我们浏览我们的模式时,我们看到了 Rockset 的每种索引技术如何协同工作来处理令人愉快的用户体验。最后,我们完成了将 Rockset 连接到 DynamoDB 表并在应用程序中与 Rockset 交互的实际步骤。 也出现 。 在这里