GDB索引:更快的速度探索互联数据的奥秘

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 Tair(兼容Redis),内存型 2GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 阿里云图数据库GDB对于用户点边的每一个属性都会自动创建索引信息,减少用户额外的索引操作。同时,用户也可以根据访问场景通过GDB支持的标准图查询语言Gremlin动态地创建复合索引、唯一索引和点中心索引等其它类型的索引来加速特定的查询。

对于数据库的使用者而言,索引是一个非常熟悉的概念。Wikipedia中对数据库索引的定义:

A database index is a data structure that improves the speed of data retrieval operations on a database table at the cost of additional writes and storage space to maintain the index data structure.

用户创建索引的期望是能够避免全量扫描,通过索引来减少IO和CPU开销从而加速查询,是典型的空间换时间的优化方式。大部分数据库会默认创建主键/RowKey索引,二级索引等其它类型索引需要用户根据实际查询情况自定义地创建。
阿里云图数据库GDB对于用户点边的每一个属性都会自动创建索引信息,减少用户额外的索引操作。同时,用户也可以根据访问场景通过GDB支持的标准图查询语言Gremlin动态地创建复合索引、唯一索引和点中心索引等其它类型的索引来加速特定的查询。

自动索引

LDBC SNB是面向图数据管理系统的Benchmark,越来越受到图数据库厂商的重视,下面以LDBC SNB的数据模型为例来说明图数据库GDB的自动索引是如何工作的。

schema.png

从模型中可以看出,对于Person这种Label的节点,可能会有firstName、lastName、creationDate等多种属性。当用户使用Gremlin DSL插入某个节点的数据时:

g.addV('Person').property('firstName', 'Foo').property('lastName', 'Bar').property('creationDate', 20200225)

图数据库GDB会自动为每一个属性fistName、lastName、creationDate创建索引数据。这样查询firstName为Foo的人时,查询语句会自动利用对应的索引来获取结果,避免遍历操作:

g.V().hasLabel('Person').has('firstName', 'Foo')
# 下面的这些查询也会利用自动索引
g.V().hasLabel('Person').has('firstName', TextP.startingWith('Fo'))
g.V().hasLabel('Person').has('creationDate', gte(20200101))

如果需要根据fistName、lastName来进行查找:

g.V().hasLabel('Person').has('firstName', 'Foo').has('lastName', 'Bar')

图数据库GDB会根据内部统计信息来决定使用firstName索引还是lastName索引。但是,如果图数据库中firstName为Foo以及lastName为Bar的节点数据都非常多时,通过自动索引扫描出来的数据也会非常多,这个时候就需要手动创建复合索引了。

复合索引

上面一节提到了同时对firstName和lastName进行过滤的查询需要创建复合索引,在阿里云图数据库GDB中,我们可以方便地使用Gremlin DSL来进行添加索引的操作:

gremlin> g.withSideEffect("GDB#createVertexLabelIndex", "{label: 'Person', properties: ['firstName', 'lastName'], unique: false}").inject(1)
==>GraphDbIndex
Index created, id: 1

创建之后可以通过Gremlin DSL查询对应的索引的状态:

gremlin> g.withSideEffect("GDB#queryIndex", "all").inject(1)
==>GraphDbIndex
Id: 1, Desc: {  type: 0,  label: Person,  property_list: [ firstName, lastName ], unique: false }, Status: Installed

当索引状态从Populating变为Installed之后,对应的索引就能够被查询语句利用到了。

点中心索引

点中心索引是针对“一跳场景”过滤非常实用的一种索引类型。下图是社交网络场景的例子,Vertex是注册用户,Edge是关注关系,Edge上有一个属性since代表关注时间。

%E7%82%B9%E4%B8%AD%E5%BF%83%E7%B4%A2%E5%BC%95.png

假设一个大V有100w+的粉丝,现在需要找出大V的粉丝中“关注时间在10年以上的”,在没有索引可以利用的时候,我们需要遍历100w+的粉丝进行过滤。这时候就会有一个问题:能否针对这个大V的100w+粉丝进行排序,按照since来进行排序 ,这样这不需要进行全量的扫描了。这个问题的答案就是阿里云图数据库GDB的点中心索引。

下面还是使用LDBC SNB的数据为例来说明点中心索引如何创建和使用,LDBC SNB的数据模型中Person节点会创建到其它Person节点数的边,类型为knows,边上有属性creationDate代表开始时间。现在需要查询某一个Person节点最近认识的10个人,返回他们之间的边和对应的creationDate,对应的查询语句如下:

g.V('p4398046512014').bothE('knows').
order().by('creationDate', desc).
project('relation', 'date').
by(identity()).
by(values('creationDate')).
limit(10)

基于这里的数据看下上面这条Gremlin DSL运行的时间:

gremlin> g.V('p4398046512014').bothE('knows').
......1> order().by('creationDate', desc).
......2> project('relation', 'date').
......3> by(identity()).
......4> by(values('creationDate')).
......5> limit(10).profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphDbGraphStep(vertex,[p4398046512014])                              1           1           0.263     1.61
VertexStep(BOTH,[knows],edge)                                        426         426           4.964    30.34
OrderGlobalStep([[value(creationDate), desc]])                        11          11          10.593    64.74
RangeGlobalStep(0,10)                                                 10          10           0.032     0.20
ProjectStep([relation, date],[[IdentityStep, Pr...                    10          10           0.509     3.11
  IdentityStep                                                        10          10           0.007
  PropertiesStep([creationDate],value)                                10          10           0.277
                                            >TOTAL                     -           -          16.362        -

现在对knows类型的边加上点中心索引,操作方式和上面添加复合索引的方式类似:

gremlin> g.withSideEffect("GDB#createVertexCentricIndex", "{label: 'knows', properties: ['creationDate'], direction: 'BOTH'}").inject(1)
==>GraphDbIndex
Index created, id: 2

同样的语句再来看一下运行时间:

gremlin> g.V('p4398046512014').bothE('knows').
......1> order().by('creationDate', desc).
......2> project('relation', 'date').
......3> by(identity()).
......4> by(values('creationDate')).
......5> limit(10).profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
GraphDbVertexCentricStep(edge,[java.lang.Object...                    11          11           2.854    78.41
RangeGlobalStep(0,10)                                                 10          10           0.047     1.29
ProjectStep([relation, date],[[IdentityStep, Pr...                    10          10           0.739    20.30
  IdentityStep                                                        10          10           0.030
  PropertiesStep([creationDate],value)                                10          10           0.442
                                            >TOTAL                     -           -           3.640        -

对于这个测试数据集,同样查询语句的延迟从16.3ms缩短到了3.64ms,从Profile的结果可以看到添加了点中心索引,GDB增加了定制过的GraphDbVertexCentricStep。当然,这个测试数据集中对应的点只有426条边,对于真实业务而言,添加合适的点中心索引可能会带来数十倍的性能提升。

结束语

阿里云图数据库GDB支持的自动索引,可以满足大部分业务场景的查询需求,很大程度上节省了用户接入的时间,同时用户可以根据查询情况定制更多的索引来提升特定场景的性能。图数据库的场景中还可以衍生出更多有意思的索引类型,比如子图匹配场景的索引、针对节点可达性查询的索引等,让用户以更快的速度探索互联数据的奥秘。

引用

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
Uma
|
存储 NoSQL 关系型数据库
DTCC 2019 | 前沿技术应用知多少? 阿里云图数据库GDB带你探索互联数据的奥秘
阿里图数据库GDB是一种支持属性图模型、用于处理高度连接数据查询与存储的实时、可靠、可扩展的在线数据库服务。本次演讲深入浅出的介绍了图数据库的概念和使用场景,以及如何快速构建基于高度连接的数据集的应用程序。
Uma
8244 0
|
7月前
|
NoSQL 搜索推荐 openCL
【C/C++ 调试 GDB指南 】gdb调试基本操作
【C/C++ 调试 GDB指南 】gdb调试基本操作
406 2
|
7月前
|
NoSQL Linux 开发工具
【深入解析git和gdb:版本控制与调试利器的终极指南】(下)
【深入解析git和gdb:版本控制与调试利器的终极指南】
100 0
|
12天前
|
NoSQL 编译器 C语言
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。高级技巧包括内存检查、性能分析和符号调试。通过实践案例学习如何有效定位和解决问题,同时注意保持耐心、合理利用工具、记录过程并避免过度调试,以提高编程能力和开发效率。
25 1
|
4月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
67 10
|
4月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
116 3
|
4月前
|
NoSQL
技术分享:如何使用GDB调试不带调试信息的可执行程序
【8月更文挑战第27天】在软件开发和调试过程中,我们有时会遇到需要调试没有调试信息的可执行程序的情况。这可能是由于程序在编译时没有加入调试信息,或者调试信息被剥离了。然而,即使面对这样的挑战,GDB(GNU Debugger)仍然提供了一些方法和技术来帮助我们进行调试。以下将详细介绍如何使用GDB调试不带调试信息的可执行程序。
121 0
|
6月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
49 1
|
6月前
|
NoSQL Linux C语言
Linux gdb调试的时候没有对应的c调试信息库怎么办?
Linux gdb调试的时候没有对应的c调试信息库怎么办?
36 0
|
6月前
|
NoSQL Linux C++
Linux C/C++ gdb调试正在运行的程序
Linux C/C++ gdb调试正在运行的程序