Nebula Java API 批量插入的性能问题

近期调研NebulaGraph,准备运用到生产环境,但无奈使用过程遇到一些问题,特寻求帮助,感谢。

问题:使用JavaApi, 批量insert插入点效率很低(1000个点每秒),机器资源很大空闲 (cpu=20%, io=2%)

我需要能够支撑1000亿的每日构建量,可目前还无法实现

具体是使用的 GraphClientImpl 和 AsyncGraphClientImpl 异步和非异步的实现,执行类似下面语句。

INSERT VERTEX user(user_id) VALUES 1000000000000000:("1000000000000000"), 1000000000000001:("1000000000000001"), 1000000000000002:("1000000000000002")

我没有使用uuid,是直接整形做为id,但性能还是不理想。 比如使用 GraphClientImpl,单线程和多线程测试了单批50个、200、1000的插入, 响应的耗时都会从逐渐增大到1s ~ 2s ,所以实际下来插入性能瓶颈仅在1000个元素/s左右,但插入时系统cpu和io和网络仍有很大的空闲,没有被彻底利用。

怀疑是什么配置不对导致了这个瓶颈,没有彻底利用系统资源? 是否有更好的java api可提供更高的插入性能?

我的集群配置如下
nebula 版本:v1.1.0

节点数量:3个
- 节点角色相同: metad + graphd + storaged
- 配置相同:4核 + 16G + 400GB NVMe SSD

创建的space: CREATE SPACE IF NOT EXISTS my_space (partition_num=300, replica_factor=1);

Storaged 配置信息:

############## rocksdb Options ############## 
--rocksdb_db_options={"max_subcompactions":"4","max_background_jobs":"4"} 
--rocksdb_column_family_options={"disable_auto_compactions":"false","write_buffer_size":"536870912","max_write_buffer_number":"10","max_bytes_for_level_base":"268435456"} 
--rocksdb_block_based_table_options={"block_size":"8192"}

如果vid能保持唯一性的话,尝试一下java client并发导入?

可以试下 spark导入工具exchange
https://github.com/vesoft-inc/nebula-docs-cn/blob/master/nebula-exchange/ex-ug-toc.md ,性能在40万/s

谢回, 我尝试了使用GraphClientImpl 和 AsyncGraphClientImpl ,分别使用并发执行 insert vertex语句,可仍然没有一个理想的性能,随着我插入数量的变多,nebula graphd 的api响应时间会明显变大,响应时间从几十毫秒 慢慢 增加到几秒。

我的代码是参考:

  1. com.vesoft.nebula.examples.async.AsyncGraphClientExample
  2. com.vesoft.nebula.examples.GraphClientExample

是否有什么配置可以更好的利用机器资源配置,我的NVMe,io利用率只有2%

请问这个exchange工具现在可以支持从Kafka读取数据后直接导入Nebula吗? 我看文档是TODO

exchange是支持从kafka导入Nebula Graph 的,文档todo是指该功能对应的文档手册还没有。
除了exchange,还可以使用flink读取kafka再写入nebula graph。

明白了。 我现在正在尝试flink导入数据,但java api插入时遇到了性能瓶颈,不确定是client的问题,还是nebula节点的配置问题, 我需要能够支撑1000亿的每日构建量 ,可目前还无法实现

当单条数据量不大时,建议把每次提交时插入的数据批次设大点。 我看你的示例中一次提交只插入了三条数据,可以设1000试下。

  1. 有没有建过索引——这个对性能应该有10倍影响。
  2. batch加大到100
  3. nebula> UPDATE CONFIGS storage:rocksdb_column_family_options = {disable_auto_compactions = true};
  4. –data_path=data/storage 是不是写在你的nvme盘
  5. 是否改过日志级别
  6. 是点慢,还是写边慢。一个批次的写点batch通常会散列多个partition,一个批次的写边batch通常会落在同一个partition
2 个赞

谢谢回复

  1. 新创建的空间,没有建索引
  2. data_path可以确定是写在nvme盘
  3. 没有改过日志级别
  4. 写点慢, insert vertex每秒写入的点个数仅1000/s~2000/s,使用Java的GraphAPI

不清楚瓶颈卡在哪,机器的io/cpu/network资源都有大量剩余,未被充分利用

单线程和多线程测试了单批50个、200、1000的插入, 响应的耗时都会从逐渐增大到1s ~ 2s
replica_factor=1
示例的属性也很小

– 时延要几秒?难道跨机房了?

你在 java client 机器上用 go-importer 导入试试呢?排除下环境问题,建立个基准。

http://nebula-graph-download.oss-cn-huhehaote.aliyuncs.com/own-think/kg_data.tar.gz?OSSAccessKeyId=LTAI4GL8kA8qApseSVGQRGxW&Expires=1606966927&Signature=e%2BBuVEZMv99XHWqdksXRtY3OP8g%3D

那我尝试下go importer ,这个链接中的文件无法下载

我尝试了是可以的。

@min.wu 我尝试了在java client上使用go-importer导入kg_data,速度可以达到 51万/s ,导入共耗时358秒,这似乎可以反映我的nebula搭建是正常的了。

Java写入耗时高的问题还是存在,我注意到github有两个版本的java client ,现在更推荐使用哪一个? (1. GitHub - vesoft-inc/nebula-clients: API of Nebula Graph in different programming languages. 2. https://github.com/vesoft-inc/nebula-java)

另外,关于Metrics我有些疑问,我导入速度为51万row每秒,在导入时查询storage_add_edge_qps.count.5指标,约等于2100~2500,这个指标的定义是按插入批次计算还是按实际边的个数计算的? 举个例子比如我batch=1000,插入2次,那么这个指标是2000还是2 。

这是我导入时的截图


1 是Nebula1.x版本的客户端
2 是Nebula2.0.0版本的客户端,目前还未正式使用