参数调优

为了在读取(尤其是写入)Neo4j 时获得最佳性能,请确保您已完成以下核对清单

调整批处理大小

将数据写入 Neo4j 是以批处理方式进行的事务操作;如果您想写入 100 万个节点,可以将其拆分为 40 个批次,每批 25,000 个。连接器的批处理大小由 batch.size 选项控制,默认设为一个相当低且保守的值。对于许多应用程序而言,这个值可能太低,可以通过更好地了解您的数据来提升性能

批处理大小的权衡如下

  • 批处理大小越大,整体摄取性能越好,因为这意味着更少的事务数和更少的总体事务开销。

  • 当批处理大小过大,导致 Neo4j 的堆内存无法容纳时,可能会导致服务器内存溢出错误并引发失败。

当您在服务器可用内存范围内使用尽可能大的批处理大小,即可获得最佳写入吞吐量。

不可能选择一个适用于所有人的单一批处理大小,因为您的事务占用的内存量取决于属性和关系的数量以及其他因素。一个通用的积极建议值大约是 20,000 - 但如果您的数据较小,或者服务器内存充足,则可以增加该数字。如果数据库服务器较小,或者您推送的数据具有许多大属性,则应调低该数字。

调整 Neo4j 内存配置。

Neo4j 操作手册中,给出了关于如何设置服务器堆内存和页面缓存大小的重要建议。对于 Spark 而言,重要的是

  • 堆内存影响事务的大小。堆内存越大,可使用的批处理大小就越大。

  • 页面缓存影响数据库在任何给定时间驻留在 RAM 中的数据量。如果页面缓存远小于数据库大小,性能会受到影响。

调整并行度

Spark 的核心在于分区和并行性;常用的技术是将一批数据拆分为多个分区,供每台机器并行处理。在 Neo4j 中,并行性的工作方式大不相同,我们将在本章中进行描述。

Neo4j 中的写入并行度

对于大多数写入 Neo4j 的操作,强烈建议将您的 DataFrame 重新分区为仅一个分区。

在 Neo4j 中写入节点和关系时

  • 写入关系会锁定两个节点。

  • 写入节点会锁定该节点。

此外,在 Neo4j 因果集群模型中,只有集群领导者(Leader)可以写入数据。由于 Neo4j 的写入是垂直扩展的,因此实际的并行度仅限于领导者节点上的核心数。

建议写入使用单一分区的原因是它消除了写入之间的锁竞争。假设一个分区正在写入

(:Person { name: "Michael" })-[:KNOWS]->(:Person { name: "Andrea" })

同时另一个分区也在写入

(:Person { name: "Andrea" })-[:KNOWS]->(:Person { name: "Davide" })

关系写入锁定了“Andrea”节点——无论如何,这些写入都无法并行进行。因此,如果线程必须等待彼此的锁,增加并行度可能无法提高性能。在并行度过高的极端情况下,Neo4j 可能会因锁竞争错误而拒绝写入。

数据集分区

如果您已正确分区数据以避免 Neo4j 锁,则可以使用与 Neo4j 服务器中核心数一样多的分区。

上述“一个分区”规则有一个例外:如果您的数据写入已提前分区以避免锁,通常可以使用与服务器中核心数一样多的写入线程向 Neo4j 写入数据。假设我们想要写入一长串 :Person 节点,并且我们知道它们通过人员 id 是唯一的。我们可以将这些数据分流到四个不同的分区中,因为不会有任何锁竞争。

调整模式采样

由于采样过程可能成本高昂并影响数据提取作业的性能,因此正确调整采样参数至关重要。

APOC 采样

如果安装了 APOC,模式推断将使用 apoc.meta.nodeTypePropertiesapoc.meta.relTypeProperties 过程。

您可以分别通过 apoc.meta.nodeTypePropertiesapoc.meta.relTypeProperties 选项调整 sample 参数。例如

df.read
  .format(classOf[DataSource].getName)
  .option("labels", ":Product")
  .option("apoc.meta.nodeTypeProperties", """{"sample": 10}""")
  .load()

该选项支持除以下之外的所有配置参数

  • apoc.meta.nodeTypePropertiesincludeLabels,因为标签由 labels 选项定义。

  • apoc.meta.relTypePropertiesincludeRels,因为关系由 relationship 选项定义。

自动采样

当未安装 APOC 或使用 query 选项时,连接器会根据一定数量的记录推断模式。

您可以调整 schema.flatten.limit 选项来增加或减少此数量。