常见问题与故障排除
常规问题
该软件与 Morpheus 或 Cypher for Apache Spark (CAPS) 有关联吗?
没有。两者之间没有任何共享的代码或方法,并且它们采用的方法截然不同。Cypher® for Apache Spark/Morpheus 采取的方法是在 Spark 环境中提供一个可以执行 Cypher 查询的解释器,并为 Spark 提供原生图表示。相比之下,本连接器不提供该功能,而是专注于在 Neo4j 和 Spark 之间进行数据的读写操作。通过此连接器,所有 Cypher 代码严格在 Neo4j 内部执行。Spark 环境像往常一样基于 DataFrame 进行操作,此连接器不为 Spark 提供图 API 原语。
如何加快向 Neo4j 的写入速度?
Spark 连接器本质上是以批处理方式将数据写入 Neo4j 的。Neo4j 是一个事务型数据库,所有的修改都在事务中完成。而这些事务本身是有开销的。
提高写入性能的最简单方法如下:
-
您可以增加批处理大小(选项
batch.size)。批次越大,写入所有数据所需执行的事务就越少,产生的事务开销也就越少。 -
确保您的 Neo4j 实例拥有充足的可用堆内存和大小合适的页面缓存(page cache)。堆内存太小会导致无法提交大批次数据,从而减慢整体导入速度。
| 为了获得最佳性能,请确保您熟悉 Operations manual(操作手册)中的内容。 |
请务必记住,Neo4j 的写入是垂直扩展的,而读取是水平扩展的。在 Causal Cluster Model(因果集群模型)中,只有集群领导者(1 台机器)可以接受写入。因此,为了最大化写入吞吐量,请专注于提升集群领导者的硬件配置和性能。
为什么返回的列顺序与我在查询中指定的顺序不一致?
遗憾的是,这是一个已知问题,存在于 Neo4j 3.x 和 Neo4j 4.0 版本中。从 Neo4j 4.1 开始,您将获得与 return 语句中指定的相同顺序。
我该从哪里获得帮助?
Neo4j 社区网站是一个提问、与使用该连接器的其他用户交流以及从 Neo4j 专家处获取帮助的好地方。您也可以在 Neo4j Discord 频道中留言。
错误
我的写入因死锁异常(Deadlock Exceptions)而失败,我该怎么办?
在某些情况下,Neo4j 会因为您可能在堆栈跟踪中看到的死锁异常而拒绝写入事务。
这篇 Neo4j 知识库文章描述了该问题。
通常这是由于向 Neo4j 写入时的并行度过高导致的。例如,当您写入关系 (:A)-[:REL]→(:B) 时,这会在数据库中对两个节点创建“锁”。如果其他并发线程过于频繁地尝试写入这些节点,可能会导致死锁异常并使事务失败。
通常,解决方案是在写入 Neo4j 之前对 DataFrame 进行重新分区(repartition),以避免多个分区写入同时锁定相同的节点和关系。
我遇到了类似 UTF8String cannot be cast to Long 的类型转换错误。有什么解决方案?
您可能会遇到类似以下的错误,或者是不同类型的错误:
java.lang.ClassCastException: org.apache.spark.unsafe.types.UTF8String cannot be cast to java.lang.Long
这通常是因为同一个节点标签上的某个字段具有不同的类型。您可以通过安装 APOC 来解决此问题:这消除了错误,但该字段的所有值都会被强制转换为 String 类型。发生这种情况的原因是 Spark 不是无模式(schema-free)的,它要求每一列必须始终具有其固定的类型。
您可以在此处阅读更多内容。
我遇到了 TableProvider implementation org.neo4j.spark.DataSource cannot be written with ErrorIfExists mode, please use Append or Overwrite modes instead 的错误。我该怎么办?
如果您在尝试向 Neo4j 写入时遇到此错误,请注意,当前版本的连接器不支持 Spark 3 上的 SaveMode.ErrorIfExists,而这是默认的保存模式。因此,请将保存模式更改为 SaveMode.Append 或 SaveMode.Overwrite 中的一种。
我们正在努力在 Spark 3 上完全支持所有的保存模式。
我遇到了 NoClassDefFoundError 或 ClassNotFoundException 错误。我该怎么办?
您可能会遇到以下类型的错误之一:
NoClassDefFoundError: org/apache/spark/sql/sources/v2/ReadSupport Caused by: ClassNotFoundException: org.apache.spark.sql.sources.v2.ReadSupport
java.lang.NoClassDefFoundError: scala/collection/IterableOnce Caused by: java.lang.ClassNotFoundException: scala.collection.IterableOnce
这意味着您的 Spark 版本与连接器上的 Spark 版本不匹配。请参考此页面了解您需要哪个版本。
我遇到了 Failed to invoke procedure gds.graph.create.cypher: Caused by: java.lang.IllegalArgumentException: A graph with name [name] already exists 的错误。我该怎么办?
在使用 GDS 库创建新图时可能会发生这种情况。问题在于查询被执行了两次:第一次是为了提取 DataFrame 的模式(schema),第二次是为了获取数据。
为避免此问题,您可以使用用户定义模式(user defined schema)的方法。
Databricks 设置
连接到 Aura 时我遇到了 SSL 握手错误。
由于 Databricks 的自定义 Java 安全设置移除了对某些加密密码的支持,从 Databricks 连接的 Aura 客户可能会遇到 SSL 握手错误。
有关详细信息,请参阅 Aura 支持文章:Connecting to Aura with Databricks。
故障排除
如何获取底层的 Neo4j 驱动程序调试日志?
|
这仅适用于 Spark 连接器 4.1.4 及更高版本。 |
Spark 程序需要按照 Spark 手册中的说明进行日志记录配置。
将 org.neo4j.driver 包的级别设置为 TRACE,并将 org.neo4j.driver.internal.shaded 下包的级别设置为 WARN 或 ERROR。
随后将出现类似于以下的日志消息,提供有关 Neo4j Bolt 服务器与 Spark 连接器 Neo4j 驱动程序之间 Bolt 交换的详细视图(格式可能会根据您的日志记录配置而有所不同)
2025-06-23 16:32:22 INFO org.neo4j.driver.internal.DriverFactory:41 - Direct driver instance 584203303 created for server address localhost:63380
2025-06-23 16:32:22 TRACE org.neo4j.driver.internal.async.pool.ConnectionPoolImpl:76 - Acquiring a connection from pool towards localhost:63380
2025-06-23 16:32:22 TRACE org.neo4j.driver.internal.async.connection.ChannelConnectedListener:76 - [0x6651d7e4][localhost:63380][] Channel [id: 0x6651d7e4, L:/127.0.0.1:63395 - R:localhost/127.0.0.1:63380] connected, initiating bolt handshake
2025-06-23 16:32:22 DEBUG org.neo4j.driver.internal.async.connection.ChannelConnectedListener:62 - [0x6651d7e4][localhost:63380][] C: [Bolt Handshake] [0x6060b017, 132100, 260, 4, 3]
2025-06-23 16:32:22 DEBUG org.neo4j.driver.internal.async.connection.HandshakeHandler:62 - [0x6651d7e4][localhost:63380][] S: [Bolt Handshake] 4.4