暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何将数据从 Neo4j 迁移到星云图

原创 Ellison 2023-01-05
630

在本文中,了解如何将数据从 Neo4j 迁移到星云图。

本文主要介绍如何使用星云图交换(简称Exchange)将数据从Neo4j迁移到星云图,星云图团队支持的数据迁移工具。在介绍如何导入数据之前,我们先来看看星云图内部的数据迁移是如何实现的。

星云图交换中的数据处理

我们的数据迁移工具的名称是星云图交换。它使用Spark作为导入平台,支持庞大的数据集导入并确保性能。数据帧是组织成命名列的分布式数据集合,由 Spark 提供,支持各种数据源。使用数据帧,若要添加新数据源,只需提供要读取的配置文件的代码和数据帧返回的读取器类型。

如上所述,数据帧是组织成行和列的分布式数据集合。一个数据帧可以存储在多个分区中。分区存储在不同的计算机上以支持并行操作。此外,Spark还提供了一组API,允许用户轻松操作DataFrames,就像在本地操作一样。此外,大多数数据库都支持将数据导出到数据帧中。即使数据库不提供此类功能,也可以使用数据库驱动程序手动生成数据帧。

将数据转换为数据帧后,星云图交换遍历数据帧中的每一行,根据配置文件中的字段映射关系,通过列名获取对应的值。遍历行后,Exchange将获取的数据一次性写入星云图。目前,Exchange 生成 nGQL 语句,然后由星云客户端异步写入数据。我们将支持导出存储在星云图底层存储中的 sst 文件,以获得更好的性能。接下来,让我们继续实现 Neo4j 数据导入。batchSize

实现从 Neo4j 导入数据

Neo4j提供了一个官方库,可以直接将数据导出为数据帧。但是,它不支持可恢复下载。因此,我们没有直接使用此库。相反,我们使用官方的 Neo4j 驱动程序来读取数据。为了获得更好的性能,Exchange 通过调用不同分区上的 Neo4j 驱动程序来执行不同的 Cypher 语句,并将数据分发到不同的分区。分区数由配置参数 指定。skiplimitpartition

Exchange 通过以下步骤导入 Neo4j 数据:首先,Exchange 中的 Neo4jReader 类将用户配置中的 Cypher 语句和语句替换为并执行它们以获得总数据大小。其次,交易所根据分区号计算每个分区的初始偏移量和大小。如果配置了参数,Exchange 也会读取此目录下的文件。如果下载处于可恢复状态,Exchange 将计算每个分区的初始偏移量和大小,然后在每个分区中的 Cypher 语句之后添加不同的 和,并调用驱动程序执行。最后,Exchange 将返回的数据转换为数据帧。execreturncount(*)check_point_pathskiplimit

下图演示了该过程:

练习数据从 Neo4j 导入星云图

我们使用以下系统环境来演示导入:

硬件:

  • CPU 名称: 英特尔® 至强(R) CPU E5-2697 v3 @ 2.60GHz
  • 处理器核心数:14
  • 内存大小:251G

软件:

  • Neo4j版本:3.5.20社区
  • Nebula Graph:使用 Docker Compose 部署。我们使用默认配置,在前面的机器上部署星云图。
  • 火花:单节点。版本:2.4.6 Hadoop2.7预构建。

由于星云图是一个强类型模式数据库,因此在导入数据之前需要创建空格、标签和边类型。有关详细信息,请参阅创建空间语法。

在这里,我们创建一个名为 test 的空间,复制编号为 1。我们创建两种类型的标签:标签 A 和标签 B。两者都有四个属性。此外,我们创建了一个边缘类型 edgeAB,它也具有四个属性。nGQL 查询如下所示:


1# Create graph space test

2CREATE SPACE test(replica_factor=1);

3# Use graph space test

4USE test;

5# Create tag tagA

6CREATE TAG tagA(idInt int, idString string, tboolean bool, tdouble double);

7# Create tag tagB

8CREATE TAG tagB(idInt int, idString string, tboolean bool, tdouble double);

9# Create edge type edgeAB

10CREATE EDGE edgeAB(idInt int, idString string, tboolean bool, tdouble double);




现在让我们将模拟数据导入 Neo4j。模拟数据包含 100 万个标有标签 A 和标签 B 的顶点,1000 万个标有 edgeAB 的边。注意,从Neo4j导出的数据必须具有属性,数据类型必须与星云图完全相同。

最后,为了加快 Mock 数据导入到 Neo4j 的速度并提高读取性能,我们在 tagA 和 tagB 中为该属性创建了索引。请注意,Exchange 不会将索引和约束导入星云图。因此,请记住创建和重建索引。idInt

然后我们将数据从 Neo4j 导入到星云图。首先,让我们下载并打包项目。您可以在星云-java 仓库的目录中找到该项目。运行以下命令:tools/exchange


  1. it clone https://github.com/vesoft-inc/nebula-java.git
  2. cd nebula-java/tools/exchange
  3. mvn package -DskipTests


然后你会看到该文件。target/exchange-1.0.1.jar

接下来,我们转到配置文件。配置文件的格式为 HOCON(人类优化配置对象表示法)。让我们根据文件进行修改。首先,为星云图配置地址、用户、pswd 和空间。我们在此处使用默认测试环境,因此我们不会在此处修改任何内容。接下来,配置标签。我们仅演示标签 A 的配置,因为标签 B 的配置与标签 A 的配置相同。src/main/resources/server_application.conf

  1. {
  2. # ====== connection configuration for neo4j=======
  3. name: tagA
  4. # Must be exactly the same as the tag name in Nebula Graph. Must be created before importing.
  5. server: "bolt://127.0.0.1:7687"
  6. #  address configuration for neo4j7user: neo4j
  7. # neo4j username
  8. password: neo4j

  9. # neo4j password
  10. encryption: false
  11. # (Optional): Whether to encrypt the transformation. The default value is false.
  12. database: graph.db
  13. # (Optional): neo4j databases name, not supported in the Community version

  14. # ======import configurations============
  15. type: {
  16. source: neo4j
  17. # PARQUET, ORC, JSON, CSV, HIVE, MYSQL, PULSAR, KAFKA...
  18. sink: client
  19. # Write method to Nebula Graph, only client is supported at present. We will support direct export from Nebula Graph in the future.
  20. }

  21. nebula.fields: [idInt, idString, tdouble, tboolean]
  22. fields       : [idInt, idString, tdouble, tboolean]
  23. # Mapping relationship fields. The upper is the nebula property names, the lower is the neo4j property names. All the property names are correspondent with each other.
  24. # We use the List instead of the Map to configure the mapping relationship to keep the field order, which is needed when exporting nebula storage files.

  25. vertex: idInt
  26. # The neo4j field corresponds to the nebula vid field. The type must be int.

  27. partition: 10

  28. # Partition number.
  29. batch: 2000
  30. # Max data write limit.

  31. check_point_path: "file:///tmp/test"
  32. # (Optional): Save the import information directory, used for resumable downloads.

  33. exec: "match (n:tagA) return n.idInt as idInt, n.idString as idString, n.tdouble as tdouble, n.tboolean as tboolean order by n.idInt"
  34. }




边的配置与顶点的配置类似。但是,您需要为边配置源 vid 和目标 vid,因为星云图边包含源 vid 和目标 vid。边缘配置如下:


  1. source: {
  2. field: a.idInt
  3.  # policy: "hash"
  4. }
  5. # configuration for source vertex ID
  6. target: {
  7. field: b.idInt
  8. # policy: "uuid"
  9. }
  10. # configuration for destination vertex ID

  11. ranking: idInt
  12. # (Optional): The rank field.

  13. partition: 1
  14. # Set partition number as 1. We set it to one here. We will talk about the reason later.

  15. exec: "match (a:tagA)-[r:edgeAB]->(b:tagB) return a.idInt, b.idInt, r.idInt as idInt, r.idString as idString, r.tdouble as tdouble, r.tboolean as tboolean order by id(r)"




您可以将哈希策略或 UUID 策略用于折点、边源折点和边目标折点。哈希/uuid 函数将字符串类型字段映射到整数类型字段。

由于前面的示例使用整数 VID,因此不需要策略设置。请参阅此处以了解哈希和uuid之间的区别。

在Cypher中,我们使用关键字来确保同一查询的顺序相同。虽然返回的数据顺序看起来是一样的,为了避免数据导入中的数据丢失,我们强烈建议在 Cypher 中使用,尽管导入速度在一定程度上被牺牲了。要提高导入速度,最好对索引属性进行排序。如果没有任何索引,请检查默认顺序并选择合适的顺序以提高性能。如果在默认返回的数据中找不到任何排序规则,可以按顶点/边 ID 对数据进行排序,并设置尽可能小的值,以减轻 Neo4j 的排序压力。这就是我们在此示例中将数字设置为 1 的原因。ORDER BYORDER BYORDER BYpartitionpartition

此外,星云图在创建顶点和边时使用ID作为唯一的主键。如果在插入新数据之前主键存在,则主键下的旧数据将被覆盖。因此,使用重复的 Neo4j 属性值作为星云图 ID 将导致数据丢失,因为具有相同 ID 的顶点被视为一个顶点,并且只保存最后一次写入。由于导入星云图的数据是并行的,我们不保证最终数据是 Neo4j 中的最新数据。

您需要注意的另一件事是可恢复下载。在断点和恢复之间,数据库不得更改状态,例如不允许插入或删除数据。不得修改该号码,否则可能会发生数据丢失。partition

最后,由于 Exchange 在不同的分区上执行不同的 Cypher 查询,因此用户不得提供包含 和 的查询。skiplimitskiplimit

接下来,运行交换以导入数据。执行以下命令:

1;$SPARK_HOME/bin/spark-submit  --class com.vesoft.nebula.tools.importer.Exchange --master "local[10]" target/exchange-1.0.1.jar -c /path/to/conf/neo4j_application.conf


在上述配置下,导入 100 万个顶点需要 13 秒,导入 1000 万条边需要 213 秒。因此,总导入需要 226 秒。

附录:Neo4j 3.5社区与星云图1.0.1的比较

Neo4j和星云图在系统架构、数据模型和访问方式上有所不同。因此,我们在下表中列出了一些常见的差异供您参考:

项目Neo4j 3.5 社区星云图 1.0.1交流小贴士
系统架构分散式仅限企业版星云图 1.0.1/
分片/分区是的/
开源许可证阿普尔阿帕奇 2.0/
写在爪哇岛C++/
高可用性是的/
数据建模属性图是的是的
图式架构可选或无架构
强架构
1. 必须先创建架构。
2. Neo4j的模式必须与星云图的模式一致。
顶点/边类型标签不是必须的。标签不确定属性架构。
标签/边类型必须至少有一个标签。标记必须与架构相对应。
/
顶点 ID/唯一主键主键不是顶点的必备条件。因此,可能会有重复的记录。主键的唯一性由内置的 id() 或约束来保证。
顶点 ID(或 VID)必须是唯一的。您可以使用其他应用程序生成 VID。
不允许没有主键的重复记录。仅保存最后的写入重复记录。
物业指数是的是的无法导入索引。您需要重新生成它们。
约束是的不能导入约束。
交易是的/
示例查询列出所有标签/标签MATCH (n) 返回不同的标签(n);调用 db.labels();
显示标签

插入具有指定类型的顶点创建 (:P erson {年龄: 16})
插入顶点 (prop_name_list) 值 :(prop_value_list)<tag_name><vid>

更新顶点的属性设置 n.name = V
更新顶点集<vid><update_columns>

查询指定顶点的属性匹配 (n)其中 ID(n) = vidRETURN 属性(n)
获取道具<tag_name> <vid>

查询特定顶点的指定边类型匹配 (n)-[r:edge_type]->() 其中 ID(n) = vid
从过去开始<vid><edge_type>

查找两个顶点之间的路径匹配 p =(a)-[]->(b)其中 ID(a) = a_vid 且 ID(b) = b_vidRETURN p
查找从到结束的所有路径 *<a_vid><b_vid>


原文链接:https://dzone.com/articles/how-to-migrate-data-from-neo4j-to-nebula-graph

原文标题:How to Migrate Data From Neo4j to Nebula Graph

原文作者:by Jamie Liu

最后修改时间:2023-01-05 13:11:00
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论