@TOC[1] Here's the table of contents:
•一、超级节点 •1.1 超级节点概念 •1.2 从图数据网络中寻找超级节点•二、与超级节点相关的关键问题案例•三、模拟超级节点 •3.1 服务器资源 •3.2 构建模拟数据的图数据模型 •3.3 模拟超级节点的数据规模•四、超级节点建模优化 •4.1 关系结构优化方案 •4.2 标签细分遍历图可减少节点规模•五、增删改操作优化 •5.1 服务器优化 •5.2 图库配置优化 •5.3 JVM调优 •5.4 批量操作 •5.5 服务器端操作文件•六、检索效率提升 •6.1 查询优化 •6.2 预热数据 •6.3 图数据库索引 •6.4 图数据库全文检索lucene接口 •6.5 图数据库全文检索集成Elasticsearch •6.5.1 数据同步-关联存储 •6.5.2 数据同步-监控程序同步 •6.5.3 Elasticsearch调优•七、自规避路径查询 •7.1 查询场景案例 •7.2 自规避查询实现
一种针对图数据超级节点的数据建模优化解决方案
图数据中超级节点的存在会极大地影响某些查询的性能。
最佳操作是通过数据建模分散超级节点规模
,以提高路径遍历效率;也可以通过一些缓存机制进行优化
,但是通过缓存优化在实战中是非常鸡肋的。 例如,在对复杂网络执行“二跳邻居”算法时,该算法的实现使用两次遍历,首先进行初始化的时候将自己的生命值设置为2,第一次遍历向邻居节点传播自身携带的ID和生命值1的消息,第二次遍历的时候收到消息的邻居再转发一次,生命值为0,最终对带有消息为0ID的节点进行统计。但是,若复杂网络中包含超级节点,则这些节点会在第一轮传播后收到过多消息而使关系图瘫痪
而无法进行下一步运算。 本篇文章中提出了一种超点
数据建模优化的实战案例,仅供参考:)
一、超级节点
1.1 超级节点概念
百度百科:关于超级节点[2] 百度百科:关于无标度网络[3] 数据部门需要利用海量数据生成复杂关系网络,并对复杂网络进行分析。然而,复杂网络中包含无标度网络,无标度网络具有严重的异制性,少数节点往往拥有大量的连接,而大部分节点确拥有少量的连接。但是,在对无标度网络进行研究时,更关注的是拥有少量连接的节点,对于拥有大量连接的超级节点不仅影响性能,对结果也是一种干扰。
1.2 从图数据网络中寻找超级节点
代码语言:javascript复制构建海量数据的关系图,该关系图包含节点和通过两个节点连接构成的边。计算每个节点的出现概率,剔除出现概率小于预设
阈(yù)值
的节点,就可以得到超级节点列表。另外也可以通过人工经验判断哪些节点的度属于超级节点,但是这种方式过分依赖专家经验,识别效率比较低。使用存储过程CALL apoc.meta.stats()
对图中标签和关系数据规模做一个粗略统计分析,然后可以重点分析某类数据下的节点数据。计算节点度分布时生成结果数据量较大的情况下,可以使用导出CALL apoc.export.json.query
将出入度分析的结果生成到图数据库后台import
目录下,并使用后台任务CALL apoc.periodic.submit
的方式提交该查询。计算节点度分布可以使用如下查询:
二、与超级节点相关的关键问题案例
超级节点:
实中网络结构的度分布往往呈现幂律性,意即存在这么一类节点,其拥有的边数对整个网络的边数占比显著非0,我们称这类节点为超级节点。实际业务场景下的超级节点问题案例:
中证中小投资者服务中心对全体A股上市公司进行各1手的公益性持有,在A股股东关系中就是一个超级节点。超级节点的存在会极大影响入库、检索和分析的效率。请针对以下场景进行调研分析:
(在第三节
会围绕这三个关键问题
提出对应解决方案): 1、图数据库对跟超级节点有关的增删改操作效率很差,如何改善这个状况? 2、图数据库查询过程中遇到超级节点会使查询结果爆炸,如何提高检索效率? 3、如何实现含超级节点的自规避路径查询?自规避路径是指查询结果链路上不存在重复节点。与该案例相关的文章与PPT:
针对图谱超级节点的一种优化解决方案[4] 针对图谱超级节点的一种优化解决方案PPT下载[5]
三、模拟超级节点
3.1 服务器资源
服务器型号:阿里云服务器 内存:32G-图数据库可使用内存12G 磁盘:200G CPU:8核 带宽:1M
3.2 构建模拟数据的图数据模型
数据模型如path所示,节点类型有事件、账号、帖子;关系类型有参与事件、发帖、点赞、关注等。
path1=(事件)<-[:参与事件]-(:账号)
path2=(账号)-[:发帖]->(:帖子)
path3=(账号)-[:关注]->(:账号)path4=(账号)-[:点赞]->(:帖子)
3.3 模拟超级节点的数据规模
程序模拟生成一批节点csv文件和关系csv文件,之后导入图数据库。这里将事件构建为一个超级节点,参与事件的账号449万,二层路径网络规模367万。
四、超级节点建模优化
很常见的图建模问题:实体可以建模成节点还是标签?例如,“中国”作为国家可以定义成节点,于是很容易成为超级节点;如果定义为标签,效果一样但是查询数据和DBA运维操作就会简化很多。从刚开始设计图数据模型的时候就需要考虑对于查询的便捷性。
4.1 关系结构优化方案
•对于社交网络中的超级节点,一种建模方法是将其与其他节点的关系按照时间段或者任何其他类别分组。
例如对于:
(:个人) -[:点赞]-> (:明星)
, 可以变成:(:个人) - [:操作日期]->(:日期{date:'20200101'})-[:点赞_20200101]->(:明星)
这样提高查询的并发性
、减少
对超级节点关系的遍历深度
。
•对于社交网络的双向关注关系也可以优化为好友关系,可以使图结构更加精简提升效率。
4.2 标签细分遍历图可减少节点规模
对标签进行分组分类的方式设计,可以降低数据遍历时命中数据的规模。对于
3.2
中构建的图模型:path1=(事件)<-[:参与事件]-(:账号) path2=(账号)-[:发帖]->(:帖子) path3=(账号)-[:关注]->(:账号) path4=(账号)-[:点赞]->(:帖子)
可以做以下优化:
•标签结构设计
将账号类节点细分,帖子节点细分,ETL处理时使用标签树统一管理。示例标签树只分一级,如下:账号分为:TwitterID、FacebookID、InstagramID... 帖子分为:Twitter发帖、Facebook发帖、Instagram发帖...
•账号类型细分之后,参与事件的各个类型
账号的数据量:
•账号、帖子标签细分之后的层级关系示例:
标签分组分类示意图:
•在遍历图时,可以指定细分标签进行遍历。相关节点被过滤出来之后,当前需要分析的子图规模大幅下降,从而帮助提高效率。
五、增删改操作优化
通过对CYPHER查询语句本身的优化,可以极大的提升效率。主要借助EXPALIN和PROFILE,对于查询计划和耗时等进行深度分析,进一步优化CYPHER本身。
5.1 服务器优化
服务器优化主要是硬件的升级,包括使用ssd固态硬盘、使用更快的cpu、加大内存容量、增加网络带宽、以及一些系统级配置优化,例如打开文件数的上限配置、调整swap分区等等。
5.2 图库配置优化
操作系统内存
:运行服务保留1G内存即可;页面缓存
:尽量大将数据库放置到内存;堆内存
:可用堆内存的大小是图数据库性能的一个重要方面,堆内存设置一般在8G~16G之间,初始化堆内存大小和最大堆内存大小设置为同样大小,但是不要超过32g(会导致性能下降--涉及内存对象指针压缩技术);其它重要优化项
:逻辑事物日志备份策略、事务单次提交限制、事务执行时间、索引更新策略等等。
5.3 JVM调优
主要针对垃圾收集器的收集性能优化,令运行在虚拟机上的应用能够使用更少的内存以及延迟获取更大的吞吐量。
5.4 批量操作
如果对大量数据进行初始化加载,那么就用Neo4j-import;增量数据的同步加载又不想暂停数据库服务,那就要用load csv或者apoc。在数据提交时,节点和关系分开提交也会大幅提升效率。另外需要构造尽可能小的请求,并且语句格式固定(这样可以利用缓存),然后通过参数方式使用。
5.5 服务器端操作文件
比通过网络批量提交增删改CYPHER更加高效的操作方式:Neo4j提供了一种嵌入式数据库操作,就是直接操作数据库文件。这种方式处理效率非常高,TPS在1W以上。但是如果用这种方法的话,就不能分布式进行处理了。使用插件来操作数据库。插件方式是指编写插件代码,然后部署到服务器上。然后以嵌入式的方式在服务端直接处理数据库,并且可以分布式提交数据变更请求。
六、检索效率提升
6.1 查询优化
Neo4j在生成查询执行计划时会优先选择“成本更小”的节点出发,因此超级节点通常不会作为查询的起点。也可以使用USING INDEX :Node(prop)来强制Cypher查询从某个节点出发进行遍历。如果超级节点是路径的中间节点,可以将查询路径分段,例如:MATCH (a)-[r]->(b) WITH DISTINCT(b) MATCH ...,这里b表示超级节点。
6.2 预热数据
1、存储过程YIELD的结果用with缓存一下,性能会提高一些 2、CALL apoc.warmup.run() 3、MATCH (n) OPTIONAL MATCH (n)-[r]->() RETURN count(n.prop) count(r.prop)
6.3 图数据库索引
手工索引 模式索引,支持节点和关系。利用好这两个索引对于写入还有检索的性能影响至关重要。
6.4 图数据库全文检索lucene接口
借助此接口可以在图库之上研发类似万方搜索的高级检索功能,但是目前不支持数值类型而且中文分词不友好需要借助底层API自研。
6.5 图数据库全文检索集成Elasticsearch
集成Elasticsearch,使用图数据库插件捕获事务进行同步增删改操作。
neo4j适合做
图存储和基于模式匹配的子图查询
,elasticsearch适合复杂属性综合检索
,两者结合相得益彰。在无处不在的互联网搜索引擎的推动下,全文搜索占据了主导地位。图形数据库在高度连接的领域上支持事务性和分析性。将两者结合在一起可以增强
基于图的搜索结果,比如推荐特性或概念搜索
,还可以将高级搜索结果作为图遍历的入口点。
6.5.1 数据同步-关联存储
(需要设计额外的关联属性)在图数据存储到neo4j时,同时将关联详情属性信息存储到es,图库数据和索引数据通过设计关联主键关联。
6.5.2 数据同步-监控程序同步
(不需要设计额外的关联属性,使用图库自动生成的ID)设计图库监控程序,分别监控节点以及节点属性信息,关系以及关系属性信息。监测到新入数据之后,在数据来源处获取数据详细信息整合存储到es。
6.5.3 Elasticsearch调优
节点独占服务器(每台服务器只布署一个节点),多余内存留给操作系统缓存(lucene使用缓存对于检索速度有至关重要的影响); 每个分片的数据量控制不要超过30GB,单个集群规模不要超过300 节点,根据业务需求合理规划集群; 其它重要优化:慢速日志监控、索引刷新策略、内存锁定策略、索引级触动冲刷的规模、索引级用于合并的最大线程数、强制限定一个节点上某个index的shard数量、tranlog持久化策略调整、禁止动态分配分片、自适应副本选择、动态创建mapping的设置、sync间隔时间设定、节点缓存、分片查询缓存、Fielddata缓存的使用等等。
七、自规避路径查询
7.1 查询场景案例
代码语言:javascript复制A到C的路径不能出现C-A-B-A,即某个点只能路过一次。下面这个查询实现了从473节点出发查询三层路径默认返回匹配到的第一条路径。通过查询结果可以看到在三层路径内重复遍历了473这个节点,而473这个节点与627恰好存在一条环路。
7.2 自规避查询实现
代码语言:javascript复制为了解决上述
7.1
重复遍历节点的问题,使用下面的存储过程精细控制图遍历过程。与上一次
7.1
查询一样,下面这个查询实现了从473节点出发查询三层路径默认返回匹配到的第一条路径,并且没有重复遍历节点。返回的结果可以看到,473、7976、13534、8516四个节点组成了一条三层的路径。
图相关的建模、存储、搜索、分析优化非常复杂,以上只是沧海一粟,更多优化需要不断地在企业级生产环境中实践操作!:)
References
[1]
TOC: 一种针对图数据超级节点的数据建模优化解决方案
[2]
百度百科:关于超级节点: https://baike.baidu.com/item/超级节点
[3]
百度百科:关于无标度网络: https://baike.baidu.com/item/无标度网络
[4]
针对图谱超级节点的一种优化解决方案: https://blog.csdn.net/superman_xxx/article/details/104906383
[5]
针对图谱超级节点的一种优化解决方案PPT下载: https://download.csdn.net/download/superman_xxx/12427668