大规模数据如何实现数据的高效追溯 —华为云图数据库服务应用
“一分钟,我要这个人的全部信息”,霸道总裁拍了拍你,并提出这个要求。秘书开始发力,找到了:姓名、年龄、联系方式、爱好,这些信息。不太够?那就再加上亲朋好友信息,近期活动信息,更完整展现这个人。虽然是个段子,但也给与我们一些启示:对象本身的信息可能不够“全”,周边关联的数据也是对象信息的重要组成,这些关联数据对在进行数据分析和挖掘时十分有用。
现实生活中关联关系十分普遍,比如人的社交、商品生产和消费行为之间都是关联关系。数据分析时,为了更好的利用关联关系,常使用图作为数据结构,使用图结构保存数据的数据库被称为图数据库。传统的关系型数据库,以表格视角对数据进行呈现,可以方便的对数据进行查询管理,而图数据库更关注节点和周边节点的联系,是一种网状结构,适用于追溯分析、社交网络分析、异构信息挖掘等等应用。华为云提供的图数据库服务就是GES(Graph Engine Service)[1]。
基于图数据库可以做很多有趣的应用,数据追溯就是一个很常见的应用。数据追溯,就是把各环节产生的数据进行关联与溯源。疫情中,查看商品的流通过程,检查商品是否有可能有接触传染源。测试活动中,通过构建测试过程网络,分析测试活动的完备性,用于进行质量评估。这些都是追溯的典型使用场景。若以传统关系型数据库构建数据追溯,需要独立构造和维护多个关系表,并实现多对多的关系网络,不易于理解复杂的业务逻辑,与此同时,也会伴随着追溯查询实现复杂和查询缓慢的问题。
图1 关系型数据库和图数据库对比
用一个例子简单说明图数据库在数据分析领域的优势。图1是一个简单的选课系统,记录了学生选课以及相应的课程信息。如右图所示,我们根据图数据库的表达方式把这些信息转化为一张图。可以看出,图可以更加直观地表达选课和班级等关系,清楚地呈现实体之间的关系,更方便进行关联分析。比如,根据图我们可以很容易找到和小布一起上数学课的同学,也可以快速找到选课兴趣相同的同学。通过图数据库可以很方便查询到周边节点信息,非常适用于追溯实现。那如何基于图数据库如何实现追溯服务?接下来我们将以华为云GES为例,分析基于GES图数据库追溯服务的实现和优化。
-
什么是图
在图数据库中,图由以下部分组成:
- 点:图中的实体对象,在图中表现为一个节点。例如,社会的人,流通的商品等都可以抽象为图中的一个节点。
- 边:图中节点与节点之间的关系。如人与人的社会关系,商品的购买行为等。
- 属性:用于描述图中节点或者边的属性,比如编号、名称等。聚类和分类分析中,权重是常常作为关系属性,也就是边的属性。
图2 有向图与无向图
根据边是否有方向,可以把图分为有向图和无向图。对于有向图来说,边的起点和终点是确定的。图2中,城市是一个节点,城市间的距离和城市之间交通方式为边。城市交通就是一个有向图,不同方向交通方式用不同的边表示,而城市间距离是无向图,因为距离和方向无关。GES使用时,需要将点和边处理成不同的对象,点边都需要定义需要的属性。点主要就是包含实体的信息,而边需要指定起点与终点。
-
定义GES图
GES建立图的步骤可以参考官方文档[2]。主要就是对节点和边进行定义,将数据处理为点和边文件,最后导入GES中,可通过界面或API导入。处理无向图时,即不区分边的起点和终点,通常也会设定一个默认方向,即指定边的起点和终点,这是为了处理和导入数据方便,在实际查询中可以忽略这种方向设定。
在GES构建图的过程中,定义点和边以及相关属性的文件被称为元数据。点和边的类型被称为label,每个label可具有多个属性,如上文提到的名称、权重等,都可以作为点或边的属性。在GES中,label一旦定义并创建成功将不被允许修改,如果必须要修改label定义,就需要格式化图并重新创建导入元数据文件到图中。
节点通常是由现实中的实体抽象而来,GES节点属性常用的数据结构包含了float、int、double、long、char、char array、date、bool、enum和string等。通常来说节点中,字符串类型的属性较多,非字符串属性可以根据数据类型进行选择。字符串类型有两个选择:string和char array。char array有数据长度限制,通常为256,而string类型没有长度限制。但是在GES中使用char array更有优势,这是因为char array数据存放在内存中,string类型数据存放在硬盘中,因此char array查询效率更高,这也是GES元数据定义需要注意的地方。在我们项目的场景中,节点的名称和编号都是常用的查询条件,综合考虑属性特征,如节点名称较长而节点编号较短,最终名称使用了string类型,而编号选择了char array类型。
-
GES查询优化
定义好节点信息后,可以在图中进行查询。GES使用的是Gremlin[3]进行查询。Gremlin是一个开源的流式查询语言,查询实现灵活,不同图数据库对查询语句的分解以及优化处理都不相同,因此,不同的写法可能查询效率可能不同。接下来我们就一种追溯查询场景进行分析。
图3 多分支查询场景分析
如图3所示,字母代表label,也就是一种节点类型。可以看到该场景具有较多查询分支,按照图中的节点要求,Gremlin查询语句直接实现如下:
g.V(id).hasLabel('A').ouE().otherV().hasLabel('B').ouE().otherV().hasLabel('C').as('c').outE().otherV().hasLabel('F').outE().otherV().hasLabel('H').select('c').outE().otherV().hasLabel('D').as('d').outE().otherV().hasLabel('G').select('d').outE().otherV().hasLabel('H')
基于当前Gremlin,GES Gremlin server会将查询分解为多个查询原子操作,并由GES engine·执行。对于这种多跳的复杂查询,会解析为较多的原子操作并频繁交互,这会导致的查询效率低下。对于这种场景,考虑使用optional语句进行查询,效率会得到提升。查询语句如下:
g.V(id).hasLabel('A').ouE().otherV().hasLabel('B').ouE().otherV().hasLabel('C').as('c').optional(outE().otherV().hasLabel('F').outE().otherV().hasLabel('H')).optional(select('c').outE().otherV().hasLabel('D').as('d').optional(outE().otherV().hasLabel('G')).optional(select('d').outE().otherV().hasLabel('H')))
optional在一定程度上可以降低分支的查询范围,从而提升查询效率。在项目实际使用中,使用optional可以提升查询性能1倍左右。但是optional不是所有场景都适用,Gremlin实现需要根据查询场景、数据规模和数据特点进行优化处理,例如图中节点的稀疏程度和分支的数量都是可以考虑优化的点。
在对GES查询优化时,即使对Gremlin语句进行了优化,也有可能达不到期望的查询性能。这是因为使用Gremlin时,处理查询过程中Gremlin server解析后的原子操作可能会和GES engine频繁交互,反而会降低查询性能,而且针对Gremlin查询优化处理范围也有限。虽然Gremlin是图数据库通用的查询脚本定义方式,但是各个厂家对于Gremlin脚本优化处理不同,因此更推荐使用GES原生API。原生API针对固定场景做了更多的优化,并且减少了Gremlin解析处理过程,因此性能更优,但同时也引入了通用性和效率之间的平衡问题,毕竟API没有通用的定义实现。
下面我们将介绍几种常见的追溯查询场景。这些场景都可以通过Gremlin查询实现,但是如果通过使用GES系统API,可以获取更好的查询性能。
-
场景(1) 追溯某个节点前(后)n层节点
该查询较为常见,主要用于查询某个节点的父子节点,对于图1 的场景可以找到班级的所有同学,该场景Gremlin实现如下:
g.V(id).repeat(out()).times(n).emit().path()
这种场景下,推荐使用GES算法文档中的k-hop算法解决该问题,需要注意,这个算法接口只会返回满足查询条件的子图中的所有点,但没有节点详情和边信息,如果需要节点详情可以采用batch-query批量进行节点详情查询。如果需要边信息,推荐场景(2) 使用的API。
-
场景(2) 按条件追溯某个节点之前(后)n层节点,节点筛选条件相同
g.V(id).repeat(outE().otherV().hasLabel('A')).times(n).emit().path()
这种场景下,推荐使用repeat-query方法。该方法可以快速实现某个起点前后n跳查询,并且可以限定节点查询条件,并且所有点的查询过滤条件相同。在查询中,如果不同的点需要使用不同的查询条件进行过滤,可以先不指定点查询条件,待返回查询结果后再进行过滤。不指定点的查询场景可以退化为场景(1),并且该API可以同时返回节点和边的详情。
-
场景(3) 按条件追溯某个节点之前(后)n层节点,不同节点筛选条件不同
图3的例子就是一个这样的场景,每层的查询label不同。这种情况下,推荐使用filtered-query进行查询,该方法需要详细指定每个节点的过滤属性,相当于将每个查询条件都在参数中一一指定,实现完全满足条件的查询。项目中,相对于Gremlin 查询,filtered-query的查询性能可以提升10倍左右。
上述三个场景中repeat-query和k-hop具有更好的泛化能力,可以随意指定查询跳数n,需要设定的参数简单。而filtered-query需要详细指定查询中每层节点的属性,参数较为复杂,具体使用中可以根据业务需求进行选择。
GES还提供了很多算法,如Node2vec, subgraph2vec,GCN算法,本文只介绍了基于GES进行节点快速查询并提供追溯服务,后续也会考虑如何基于建立好的图,进行一些数据节点融合,也可以进行相似度分析、质量评估和流程推荐等,更好地挖掘数据的价值。
【参考资料】
- 点赞
- 收藏
- 关注作者
评论(0)