NEO4J亿级数据全文索引构建优化

2024-02-25 06:38

本文主要是介绍NEO4J亿级数据全文索引构建优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

NEO4J亿级数据全文索引构建优化

  • 一、数据量规模(亿级)
  • 二、构建索引的方式
  • 三、构建索引发生的异常
  • 四、全文索引代码优化
    • 1、Java.lang.OutOfMemoryError
    • 2、访问数据库时
    • 3、优化方案
    • 4、优化代码
    • 5、执行效率测试

如果使用基于NEO4J的全文检索作为图谱的主要入口,那么做好图谱搜索引擎的优化是非常关键的。

一、数据量规模(亿级)

count(relationships):500584016

count(nodes):765485810

二、构建索引的方式

使用脚本后服务器台执行构建全文索引的操作。
使用后台脚本执行构建索引程序:

index.sh
#!/usr/bin/env bash
nohup /neo4j-community-3.4.9/bin/neo4j-shell -file build.cql >>indexGraph.log 2>&1 &
build.cql
CALL zdr.index.addChineseFulltextIndex('IKAnalyzer', ['description','fullname','name','lnkurl'], 'LinkedinID') YIELD message RETURN message;

三、构建索引发生的异常

ERROR (-v for expanded information):TransactionFailureException: The database has encountered a critical error, and needs to be restarted. Please see database logs for more details.-host      Domain name or IP of host to connect to (default: localhost)-port      Port of host to connect to (default: 1337)-name      RMI name, i.e. rmi://<host>:<port>/<name> (default: shell)-pid       Process ID to connect to-c         Command line to execute. After executing it the shell exits-file      File containing commands to execute, or '-' to read from stdin. After executing it the shell exits-readonly  Connect in readonly mode (only for connecting with -path)-path      Points to a neo4j db path so that a local server can be started there-config    Points to a config file when starting a local serverExample arguments for remote:-port 1337-host 192.168.1.234 -port 1337 -name shell-host localhost -readonly...or no arguments for default values
Example arguments for local:-path /path/to/db-path /path/to/db -config /path/to/neo4j.config-path /path/to/db -readonly
Caused by: java.lang.OutOfMemoryError: Java heap space | GB+Tree[file:/u02/isi/zdr/graph/neo4j-community-3.4.9/data/databases/graph.db/schema/index/lucene_native-2.0/134/string-1.0/index-134, layout:StringLayout[version:0.1, identifier:24016946018123776], generation:16587/16588]at org.neo4j.io.pagecache.impl.muninn.CursorFactory.takeWriteCursor(CursorFactory.java:62)at org.neo4j.io.pagecache.impl.muninn.MuninnPagedFile.io(MuninnPagedFile.java:186)at org.neo4j.index.internal.gbptree.FreeListIdProvider.releaseId(FreeListIdProvider.java:217)at org.neo4j.index.internal.gbptree.InternalTreeLogic.createSuccessorIfNeeded(InternalTreeLogic.java:1289)at org.neo4j.index.internal.gbptree.InternalTreeLogic.insertInLeaf(InternalTreeLogic.java:513)at org.neo4j.index.internal.gbptree.InternalTreeLogic.insert(InternalTreeLogic.java:356)at org.neo4j.index.internal.gbptree.GBPTree$SingleWriter.merge(GBPTree.java:1234)at org.neo4j.kernel.impl.index.schema.NativeSchemaIndexUpdater.processAdd(NativeSchemaIndexUpdater.java:132)at org.neo4j.kernel.impl.index.schema.NativeSchemaIndexUpdater.processUpdate(NativeSchemaIndexUpdater.java:86)at org.neo4j.kernel.impl.index.schema.NativeSchemaIndexUpdater.process(NativeSchemaIndexUpdater.java:61)at org.neo4j.kernel.impl.index.schema.fusion.FusionIndexUpdater.process(FusionIndexUpdater.java:41)at org.neo4j.kernel.impl.api.index.updater.DelegatingIndexUpdater.process(DelegatingIndexUpdater.java:40)at org.neo4j.kernel.impl.api.index.IndexingService.processUpdate(IndexingService.java:516)at org.neo4j.kernel.impl.api.index.IndexingService.apply(IndexingService.java:479)at org.neo4j.kernel.impl.api.index.IndexingService.apply(IndexingService.java:463)at org.neo4j.kernel.impl.transaction.command.IndexUpdatesWork.apply(IndexUpdatesWork.java:63)at org.neo4j.kernel.impl.transaction.command.IndexUpdatesWork.apply(IndexUpdatesWork.java:42)at org.neo4j.concurrent.WorkSync.doSynchronizedWork(WorkSync.java:231)at org.neo4j.concurrent.WorkSync.tryDoWork(WorkSync.java:157)at org.neo4j.concurrent.WorkSync.apply(WorkSync.java:91)

JAVA代码实现索引

    /*** @param* @return* @Description: TODO(构建索引并返回MESSAGE - 不支持自动更新)*/private String chineseFulltextIndex(String indexName, String labelName, List<String> propKeys) {Label label = Label.label(labelName);// 按照标签找到该标签下的所有节点ResourceIterator<Node> nodes = db.findNodes(label);System.out.println("nodes:" + nodes.toString());int nodesSize = 0;int propertiesSize = 0;// 循环存在问题 更新到3000万之后程序开始卡顿while (nodes.hasNext()) {nodesSize++;Node node = nodes.next();System.out.println("current nodes:" + node.toString());// 每个节点上需要添加索引的属性Set<Map.Entry<String, Object>> properties = node.getProperties(propKeys.toArray(new String[0])).entrySet();System.out.println("current node properties" + properties);// 查询该节点是否已有索引,有的话删除if (db.index().existsForNodes(indexName)) {Index<Node> oldIndex = db.index().forNodes(indexName);System.out.println("current node index" + oldIndex);oldIndex.remove(node);}// 为该节点的每个需要添加索引的属性添加全文索引Index<Node> nodeIndex = db.index().forNodes(indexName, FULL_INDEX_CONFIG);for (Map.Entry<String, Object> property : properties) {propertiesSize++;nodeIndex.add(node, property.getKey(), property.getValue());}// 计算耗时}String message = "IndexName:" + indexName + ",LabelName:" + labelName + ",NodesSize:" + nodesSize + ",PropertiesSize:" + propertiesSize;return message;}

四、全文索引代码优化

1、Java.lang.OutOfMemoryError

Java.lang.OutOfMemory是java.lang.VirtualMachineError的一个子类,当Java虚拟机中断,或是超出可用资源时抛出。

2、访问数据库时

访问数据库时程序会获取锁和内存,在事务没有被完成之前锁和内存是不会释放的。因此现在很容易理解上述BUG的出现的原因。(三)实现的索引程序中,是获取节点之后在WHILE循环中执行构建索引,直到索引构建完毕事务才会自动被关闭,自动执行内存回收等操作。当获取的数据量巨大的时候,必然会出现内存溢出。

3、优化方案

使用批量事务提交的机制。

4、优化代码

 /*** @param* @return* @Description: TODO(构建索引并返回MESSAGE - 不支持自动更新)*/private String chineseFulltextIndex(String indexName, String labelName, List<String> propKeys) {Label label = Label.label(labelName);int nodesSize = 0;int propertiesSize = 0;// 按照标签找到该标签下的所有节点ResourceIterator<Node> nodes = db.findNodes(label);Transaction tx = db.beginTx();try {int batch = 0;long startTime = System.nanoTime();while (nodes.hasNext()) {nodesSize++;Node node = nodes.next();boolean indexed = false;// 每个节点上需要添加索引的属性Set<Map.Entry<String, Object>> properties = node.getProperties(propKeys.toArray(new String[0])).entrySet();// 查询该节点是否已有索引,有的话删除if (db.index().existsForNodes(indexName)) {Index<Node> oldIndex = db.index().forNodes(indexName);oldIndex.remove(node);}// 为该节点的每个需要添加索引的属性添加全文索引Index<Node> nodeIndex = db.index().forNodes(indexName, FULL_INDEX_CONFIG);for (Map.Entry<String, Object> property : properties) {indexed = true;propertiesSize++;nodeIndex.add(node, property.getKey(), property.getValue());}// 批量提交事务if (indexed) {if (++batch == 50_000) {batch = 0;tx.success();tx.close();tx = db.beginTx();// 计算耗时startTime = indexConsumeTime(startTime, nodesSize, propertiesSize);}}}tx.success();// 计算耗时indexConsumeTime(startTime, nodesSize, propertiesSize);} finally {tx.close();}String message = "IndexName:" + indexName + ",LabelName:" + labelName + ",NodesSize:" + nodesSize + ",PropertiesSize:" + propertiesSize;return message;}

5、执行效率测试

50_000为批次进行提交,依次累加nodeSize和propertieSize,consume还是每批提交的耗时。
可以看到在刚开始提交的时候耗时较多,之后基本上稳定在每批提交耗时:2s~5s/5万条。10亿nodes,耗时估算11h~23h之间。

Build index-nodeSize:50000,propertieSize:148777,consume:21434ms
Build index-nodeSize:100000,propertieSize:297883,consume:18493ms
Build index-nodeSize:150000,propertieSize:446936,consume:17140ms
Build index-nodeSize:200000,propertieSize:595981,consume:17323ms
Build index-nodeSize:250000,propertieSize:745039,consume:19680ms
Build index-nodeSize:300000,propertieSize:894026,consume:18451ms
Build index-nodeSize:350000,propertieSize:1042994,consume:20266ms
Build index-nodeSize:400000,propertieSize:1160186,consume:12787ms
Build index-nodeSize:450000,propertieSize:1210186,consume:1946ms
Build index-nodeSize:500000,propertieSize:1260186,consume:3174ms
Build index-nodeSize:550000,propertieSize:1310186,consume:3090ms
Build index-nodeSize:600000,propertieSize:1360186,consume:3063ms
Build index-nodeSize:650000,propertieSize:1410186,consume:1868ms
Build index-nodeSize:700000,propertieSize:1460186,consume:2036ms
Build index-nodeSize:750000,propertieSize:1510186,consume:3784ms
Build index-nodeSize:800000,propertieSize:1560186,consume:3037ms
Build index-nodeSize:850000,propertieSize:1610186,consume:2627ms
Build index-nodeSize:900000,propertieSize:1660186,consume:1900ms
Build index-nodeSize:950000,propertieSize:1710186,consume:2944ms
Build index-nodeSize:1000000,propertieSize:1760186,consume:3369ms
Build index-nodeSize:1050000,propertieSize:1810186,consume:3289ms
Build index-nodeSize:1100000,propertieSize:1860186,consume:2763ms
Build index-nodeSize:1150000,propertieSize:1910186,consume:3237ms
Build index-nodeSize:1200000,propertieSize:1960186,consume:3408ms
Build index-nodeSize:1250000,propertieSize:2010186,consume:3644ms
Build index-nodeSize:1300000,propertieSize:2060186,consume:3661ms
Build index-nodeSize:1350000,propertieSize:2110186,consume:2964ms
Build index-nodeSize:1400000,propertieSize:2160186,consume:3219ms
Build index-nodeSize:1450000,propertieSize:2210186,consume:3356ms
Build index-nodeSize:1500000,propertieSize:2260186,consume:4115ms
Build index-nodeSize:1550000,propertieSize:2310186,consume:3188ms
Build index-nodeSize:1600000,propertieSize:2360186,consume:3364ms
Build index-nodeSize:1650000,propertieSize:2410186,consume:3799ms
Build index-nodeSize:1700000,propertieSize:2460186,consume:4301ms
Build index-nodeSize:1750000,propertieSize:2510186,consume:3772ms
Build index-nodeSize:1800000,propertieSize:2560186,consume:3692ms
Build index-nodeSize:1850000,propertieSize:2610186,consume:3428ms
Build index-nodeSize:1900000,propertieSize:2660186,consume:2930ms

备注:在本次测试的数据集上执行索引构建2小时之后,此时已经被索引了1495万个NODES,速度下降明显,需要进一步优化。

Build index-nodeSize:13850000,propertieSize:14610186,consume:97290ms
Build index-nodeSize:13900000,propertieSize:14660186,consume:7441ms
Build index-nodeSize:13950000,propertieSize:14710186,consume:3730ms
Build index-nodeSize:14000000,propertieSize:14760186,consume:3512ms
Build index-nodeSize:14050000,propertieSize:14810186,consume:4545ms
Build index-nodeSize:14100000,propertieSize:14860186,consume:12100ms
Build index-nodeSize:14150000,propertieSize:14910186,consume:83071ms
Build index-nodeSize:14200000,propertieSize:14960186,consume:7417ms
Build index-nodeSize:14250000,propertieSize:15010186,consume:3579ms
Build index-nodeSize:14300000,propertieSize:15060186,consume:64841ms
Build index-nodeSize:14350000,propertieSize:15110186,consume:7553ms
Build index-nodeSize:14400000,propertieSize:15160186,consume:63141ms
Build index-nodeSize:14450000,propertieSize:15210186,consume:64316ms
Build index-nodeSize:14500000,propertieSize:15260186,consume:187510ms
Build index-nodeSize:14550000,propertieSize:15310186,consume:247571ms
Build index-nodeSize:14600000,propertieSize:15360186,consume:224611ms
Build index-nodeSize:14650000,propertieSize:15410186,consume:244539ms
Build index-nodeSize:14700000,propertieSize:15460186,consume:354684ms
Build index-nodeSize:14750000,propertieSize:15510186,consume:236970ms
Build index-nodeSize:14800000,propertieSize:15560186,consume:308532ms
Build index-nodeSize:14850000,propertieSize:15610186,consume:429815ms
Build index-nodeSize:14900000,propertieSize:15660186,consume:409451ms
Build index-nodeSize:14950000,propertieSize:15710186,consume:456980ms

构建程序在运行4个小时之后,被索引了1530万NODES,索引构建速度几乎慢到不可接受,持续优化中…

Build index-nodeSize:14750000,propertieSize:15510186,consume:236970ms
Build index-nodeSize:14800000,propertieSize:15560186,consume:308532ms
Build index-nodeSize:14850000,propertieSize:15610186,consume:429815ms
Build index-nodeSize:14900000,propertieSize:15660186,consume:409451ms
Build index-nodeSize:14950000,propertieSize:15710186,consume:456980ms
Build index-nodeSize:15000000,propertieSize:15760186,consume:447474ms
Build index-nodeSize:15050000,propertieSize:15810186,consume:580270ms
Build index-nodeSize:15100000,propertieSize:15860186,consume:840488ms
Build index-nodeSize:15150000,propertieSize:15910186,consume:573554ms
Build index-nodeSize:15200000,propertieSize:15960186,consume:748670ms
Build index-nodeSize:15250000,propertieSize:16010186,consume:1305363ms
Build index-nodeSize:15300000,propertieSize:16060186,consume:2495139ms

上述测试案例的源码位置

这篇关于NEO4J亿级数据全文索引构建优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/744666

相关文章

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

mysql索引三(全文索引)

前面分别介绍了mysql索引一(普通索引)、mysql索引二(唯一索引)。 本文学习mysql全文索引。 全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。 在MySql中,创建全文索引相对比较简单。例如:我们有一个文章表(article),其中有主键ID(

【服务器运维】MySQL数据存储至数据盘

查看磁盘及分区 [root@MySQL tmp]# fdisk -lDisk /dev/sda: 21.5 GB, 21474836480 bytes255 heads, 63 sectors/track, 2610 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical)

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

SQL Server中,查询数据库中有多少个表,以及数据库其余类型数据统计查询

sqlserver查询数据库中有多少个表 sql server 数表:select count(1) from sysobjects where xtype='U'数视图:select count(1) from sysobjects where xtype='V'数存储过程select count(1) from sysobjects where xtype='P' SE

数据时代的数字企业

1.写在前面 讨论数据治理在数字企业中的影响和必要性,并介绍数据治理的核心内容和实践方法。作者强调了数据质量、数据安全、数据隐私和数据合规等方面是数据治理的核心内容,并介绍了具体的实践措施和案例分析。企业需要重视这些方面以实现数字化转型和业务增长。 数字化转型行业小伙伴可以加入我的星球,初衷成为各位数字化转型参考库,星球内容每周更新 个人工作经验资料全部放在这里,包含数据治理、数据要

如何在Java中处理JSON数据?

如何在Java中处理JSON数据? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨在Java中如何处理JSON数据。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,在现代应用程序中被广泛使用。Java通过多种库和API提供了处理JSON的能力,我们将深入了解其用法和最佳

两个基因相关性CPTAC蛋白组数据

目录 蛋白数据下载 ①蛋白数据下载 1,TCGA-选择泛癌数据  2,TCGA-TCPA 3,CPTAC(非TCGA) ②蛋白相关性分析 1,数据整理 2,蛋白相关性分析 PCAS在线分析 蛋白数据下载 CPTAC蛋白组学数据库介绍及数据下载分析 – 王进的个人网站 (jingege.wang) ①蛋白数据下载 可以下载泛癌蛋白数据:UCSC Xena (xena

服务器雪崩的应对策略之----SQL优化

SQL语句的优化是数据库性能优化的重要方面,特别是在处理大规模数据或高频访问时。作为一个C++程序员,理解SQL优化不仅有助于编写高效的数据库操作代码,还能增强对系统性能瓶颈的整体把握。以下是详细的SQL语句优化技巧和策略: SQL优化 1. 选择合适的数据类型2. 使用索引3. 优化查询4. 范式化和反范式化5. 查询重写6. 使用缓存7. 优化数据库设计8. 分析和监控9. 调整配置1、