View a markdown version of this page

性能效率支柱 - AWS 规范性指导

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

性能效率支柱

Well-Architect AWS ed Framework 的性能效率支柱侧重于如何在摄取或查询数据时优化性能。性能优化是一个循序渐进的持续过程,包括:

  • 确认业务需求

  • 衡量工作负载性能

  • 识别性能不佳的组件

  • 优化组件以满足您的业务需求

性能效率支柱提供了特定于使用案例的准则,可以帮助识别要使用的正确图表数据模型和查询语言。还包括将数据摄取到 Amazon Neptune 以及从 Amazon Neptune 使用数据时应遵循的最佳实践。

性能效率支柱侧重于以下关键领域:

  • 图形建模

  • 查询优化

  • 优化集群规模

  • 写入优化

了解图形建模

了解标签属性图(LPG)和资源描述框架(RDF)模型之间的区别。在大多数情况下,这是一个偏好问题。但是,在一些使用案例中,一种模型比另一种模型更适合。如果您需要了解连接图表中两个节点的路径,请选择 LPG。如果要跨 Neptune 集群或其他图三元组存储联合数据,请选择 RDF。

如果您正在构建软件即服务(SaaS)应用程序或需要多租户的应用程序,请考虑在数据模型中纳入租户的逻辑分离,而不是为每个集群设置一个租户。要实现该类型的设计,您可以使用 SPARQL 命名图形和标注策略,例如在标签前添加客户标识符或添加代表租户标识符的属性键值对。确保您的客户端层注入这些值以保持逻辑分离。有关多租户建议的更多信息,请参阅运行 Amazon ISVs Neptune 数据库的多租户指南

查询的性能取决于在处理查询时需要评估的图形对象(节点、边缘、属性)的数量。因此,图形模型可能会对应用程序的性能产生重大影响。尽可能使用精细标签,并仅存储实现路径确定或筛选所需的属性。要获得更高的性能,请考虑预计算图表的各个部分,例如创建汇总节点或连接公共路径的更直接的边缘。

尽量避免在具有相同标签的边缘数异常多的节点之间导航。此类节点通常有数千个边缘(其中大多数节点的边缘数仅在几十条左右)。结果是计算和数据复杂度大大增加。在某些查询模式中,这些节点可能不会出现问题,但我们建议您以不同的方式对数据进行建模以避免这种情况,尤其是在您需要通过节点作为中间步骤进行导航时。您可以使用慢速查询日志来帮助识别跨越这些节点的查询。您可能会观察到比平均查询模式更高的延迟和数据访问指标,尤其是在使用调试模式时。

如果您的用例支持,请 IDs 为节点和边使用确定性节点,而不是使用 Neptune 为其分配随机 GUID 值。 IDs通过 ID 访问节点是最有效的方法。

优化查询

在 LPG 模型上,openCypher 和 Gremlin 语言可以互换使用。如果性能是首要考虑因素,请考虑交替使用这两种语言,因为对于特定的查询模式,其中一种语言的性能可能优于另一种语言。

Neptune 正在转换为其替代查询引擎(DFE)。openCypher 仅在 DFE 上运行,但可以选择使用查询注释将 Gremlin 和 SPARQL 查询设置为在 DFE 上运行。考虑在激活 DFE 的情况下测试您的查询,并比较不使用 DFE 时的查询模式性能。

Neptune 针对事务型查询进行了优化,这些查询从单个节点或一组节点开始,然后从那里扇出,而不是评估整个图表的分析查询。对于您的分析查询工作负载,请使用 Neptune Analytics。Neptune Analytics 是需要快速迭代数据、分析和算法处理的研究、探索性或数据科学工作负载的理想选择。它还可以对图形数据执行矢量搜索,并可以直接从 Neptune 数据库实例加载数据。如果 Neptune Analytics 不能满足你的需求,你也可以考虑使用适用于 Pandas 的AWS SDK,或者将 nept une-export 与或 Amazon EMR 结合使用。AWS Glue

要识别模型和查询中的效率低下和瓶颈,请使用每种查询语言的profileexplain APIs 来获取查询计划和查询指标的详细解释。有关更多信息,请参阅 Gremlin profileopenCypher explainSPARQL explain

了解您的查询模式。如果图形中的不同边缘数太大,默认 Neptune 访问策略可能会效率低下。以下查询可能会变得非常低效:

  • 未提供边缘标签时跨边缘向后导航的查询。

  • 内部使用相同模式的子句(例如 Gremlin 中的 .both()),或者任何语言中用于删除节点的子句(这需要在不知道标签的情况下删除传入的边缘)。

  • 在不指定属性标签的情况下访问属性值的查询。这些查询可能会变得非常低效。如果您的使用模式符合这种情况,请考虑启用 OSGP 索引(对象、主题、图表、谓词)。

使用慢速查询日志记录来识别慢速查询。查询速度慢可能是由于未优化的查询计划或不必要的大量索引查找造成的,这可能会增加成本。 I/O 适用于 GremlinSPARQLopenCypher 的 Neptune explain 和 profile 端点可以帮助您了解为什么这些查询速度很慢。原因可能包括:

  • 与图中的平均节点相比,边缘数异常多的节点(例如,数千条和十条)可能会增加计算复杂性,从而延长延迟并增加资源消耗。确定这些节点的建模是否正确,或者是否可以改进访问模式,以减少必须遍历的边缘数。

  • 未优化的查询将包含警告,提示特定步骤未经过优化。重写这些查询以使用优化步骤可能会提高性能。

  • 冗余筛选条件可能会导致不必要的索引查找。同样,冗余模式可能会导致重复的索引查找,而这可以通过改进查询来优化(请参阅配置文件输出中的 Index Operations - Duplication ratio)。

  • 某些语言(例如 Gremlin)没有强类型的数值,而是使用类型提升。例如,如果值为 55,则 Neptune 会查找与 55 等效的整数、长数、浮点数和其他数值类型的值。这会导致其他操作。如果您事先知道自己的类型匹配,则可以使用查询提示来避免这种情况。

  • 您的图形模型会极大地影响性能。考虑通过使用更精细的标签或预计算多跳线性路径的快捷方式,来减少需要评估的对象数量。

如果仅靠查询优化无法满足性能要求,请考虑将各种缓存技术与 Neptune 配合使用来满足这些要求。

每个版本的 Neptune 性能都在不断提高。查看发行说明,了解每个版本的改进细节。考虑计划定期更新 Neptune 数据库集群,以帮助实现最佳性能。较新的版本也支持较新的实例。考虑升级到 1.4.5.0 或更高版本,以便能够使用这些实例。r8g有关这如何提高工作负载性能的更多信息,请参阅使用 Amazon N eptune v1.4.5 的 G AWS raviton4 r8g 实例的写入查询性价比提高 4.7 倍

优化集群规模

根据您的并发和吞吐量要求调整集群规模。集群中每个实例可以处理的并发查询数量等于该实例上虚拟 CPUs (vCPUs) 数量的两倍。在所有 Worker 都被占用时到达的额外查询将放入服务器端队列。当工作线程可用时,将在 first-in-first-out (FIFO) 基础上处理这些查询。A MainRequestQueuePendingRequests mazon CloudWatch 指标显示每个实例的当前队列深度。如果此值经常大于零,请考虑选择一个具有更多 v 的实例CPUs。 如果队列深度超过 8,192,Neptune 将返回ThrottlingException错误。

每个实例的大约 65% 的 RAM 是为缓冲区缓存预留的。缓冲区缓存保存数据的工作数据集(不是整个图表;只是正在查询的数据)。要确定从缓冲区缓存而不是存储中提取的数据的百分比,请监控该 CloudWatch 指标BufferCacheHitRatio。如果该指标经常降至99.9%以下,请考虑尝试使用具有更多内存的实例,以确定它能否降低延迟和 I/O 成本。

只读副本的大小不必与您的写入器实例的大小相同。但是,繁重的写入工作负载可能会导致较小的副本落后并重启,因为它们无法跟上复制的速度。因此,我们建议创建等于或大于写入器实例的副本。

对只读副本使用自动扩缩时,请记住,将新的只读副本上线可能需要长达 15 分钟的时间。当客户端流量快速但可预测地增加时,考虑使用计划扩展来设置更高的只读副本的最小数量,以考虑该初始化时间。

无服务器实例支持多种不同的使用案例和工作负载。在以下情况下,考虑使用无服务器而不是预调配实例:

  • 您一天中的工作负载经常波动。

  • 您创建了一个新应用程序,但不确定工作负载的大小。

  • 您正在进行开发和测试。

值得注意的是,按每 GB RAM 的美元计算,无服务器实例比同等预调配实例更昂贵。每个无服务器实例由 2GB 的 RAM 以及关联的 vCPU 和网络组成。在您的选项之间进行成本分析,以避免意外账单。通常,只有当您的工作负载每天只有几小时非常繁重,而其余时间几乎为零,或者当您的工作负载在一天中波动很大时,使用无服务器才能节省成本。

利用 Amazon Neptune 定价计算器,根据 queries-per-second (QPS) 要求等因素,帮助评估集群的正确配置。

优化写入

要优化写入情况,请考虑以下事项:

  • Neptune 批量加载程序是初始加载数据库或附加到现有数据的最佳方式。Neptune 加载程序不是事务性的,也无法删除数据,因此如果您有这些要求,请不要使用它。

  • 可以使用支持的查询语言进行事务更新。要优化写入 I/O 操作,请在每次提交时以 50-100 个对象为单位批量写入数据。对象是 LPG 中节点或边缘上的节点、边缘或属性,或者是 RDF 中的三元组存储或四元组。

  • 每个连接的所有事务性 Neptune 写入操作都是单线程的。向 Neptune 发送大量数据时,考虑建立多个并行连接,每个连接都写入数据。当您选择 Neptune 预配置的实例时,实例大小与数字 v 相关联。CPUs Neptune 为实例上的每个 vCPU 创建两个数据库线程,因此在测试最佳并行化CPUs 时,从 v 数的两倍开始。  无服务器实例以大约每 4 NCUs 个 1 的速率缩放 v CPUs 的数量。

    注意

    这不适用于批量加载 API,仅适用于直接连接。

  • 即使任何时候只有一个连接ConcurrentModificationExceptions在写入数据,也要做好所有写入过程的规划和高效处理。设计客户端时,要确保在发生 ConcurrentModificationExceptions 时也能可靠运行。

  • 如果您想删除所有数据,请考虑使用快速重置 API,而不是发出并发删除查询。与前者相比,后者将花费更长的时间并产生可观 I/O 的成本。

  • 如果您要删除大部分数据,请考虑使用 neptune-export 将数据加载到新集群来导出要保留的数据。然后删除原始集群。