index not found
?找不到索引?为什么我要创建 Nebula Graph 索引?什么时候要用到 Nebula Graph 原生索引?针对社区常见问题,本文旨在一文带大家搞清索引使用问题。
Nebula Graph 的索引其实和传统的关系型数据库中的索引很像,但是又有一些容易让人疑惑的区别。刚开始了解 Nebula 的同学会疑惑:
在这篇文章里,我们就把这些问题一一解决,方便大家更好地使用 Nebula Graph。
简单来说,Nebula Graph 索引是用来且只用来针对纯属性条件出发查询场景的功能,它具有以下特性:
我们知道在传统关系型数据库中,索引是对表数据的一个或多个针对特定列重排序的副本,它用来加速特定列过滤条件的读查询并带来了额外的数据写入。简单来说,索引能起到加速的作用,但查询使用索引并非是必要的。
在 Nebula Graph 图数据库里,索引则是对点、边特定属性数据重排序的副本,用来提供纯属性条件出发查询。
以如下边的查询为例,该语句实现了从指定点边属性条件,而非点的 ID 出发的方式去获取图数据:
#### 必须 Nebula Graph 索引存在的查询
# query 0 纯属性条件出发查询
LOOKUP ON tag1 WHERE col1 > 1 AND col2 == "foo" \
YIELD tag1.col1 as col1, tag1.col3 as col3;
# query 1 纯属性条件出发查询
MATCH (v:player { name: 'Tim Duncan' })-->(v2:player) \
RETURN v2.player.name AS Name;
上边这两个纯属性条件出发查询就是字面意思的”根据指定的属性条件获取点或者边本身“ ,反面的例子则是给定了点的 ID。参考以下例子:
#### 不基于索引的查询
# query 2, 从给定的点做的游走查询 vertex VID: "player100"
GO FROM "player100" OVER follow REVERSELY \
YIELD src(edge) AS id | \
GO FROM $-.id OVER serve \
WHERE properties($^).age > 20 \
YIELD properties($^).name AS FriendOf, properties($$).name AS Team;
# query 3, 从给定的点做的游走查询 vertex VID: "player101" 或者 "player102"
MATCH (v:player { name: 'Tim Duncan' })--(v2) \
WHERE id(v2) IN ["player101", "player102"] \
RETURN v2.player.name AS Name;
我们仔细看前边的 query 1
和 query 3
,尽管语句中条件都有针对 tag 为 player 的过滤条件 { name: 'Tim Duncan' }
,但一个需要依赖索引实现,一个不需要索引。具体的原因在这里 :
query 3
之中不需要索引,因为:(v:player { name: 'Tim Duncan' })
这种未给定 VID 的起点,从 v2 这样给定了 VID ["player101", "player102"]
的起点向外扩展,下一步再通过 GetNeighbors()
获得边的另一端的点,然后 GetVertices()
得到下一跳的 v
,根据 v.player.name
过滤掉不要的数据;query 1
则不同,它因为没有任何给定的起点 VID:{ name: 'Tim Duncan' }
入手,在按照 name 排序的索引数据中先找到符合的点:IndexScan() 得到 v
;v
做 GetNeighbors() 获得边的另一端 的 v2
,在通过 GetVertices() 去获得下一跳 v2
中的数据;其实,这里的关键就是在于是查询是否存在给定的顶点 ID(Vertex ID),下边两个查询的执行计划里更清晰地比较了他们的区别:
图注:query 1 的执行计划(需要索引);
图注:query 3 的执行计划(不需要索引);
因为 Nebula Graph 在存储数据的时候,它的结构是面向分布式与关联关系设计的,类似表结构数据库中无索引的全扫描条件搜索实际上更加昂贵,所以设计上被有意禁止了。
但,如果你不追求全部数据,只要采样一部分,3.0 里之后是支持不强制索引 LIMIT <n>
的情况的,如下查询(有 LIMIT
)不需要索引:
MATCH (v:player { name: 'Tim Duncan' })-->(v2:player) \
RETURN v2.player.name AS Name LIMIT 3;
在这里,我们比较一下正常的图查询 graph-queries 和纯属性条件出发查询 pure-prop-condition queries 实现方式:
query 2
和 query 3
是沿着边一路找到特定路径条件的扩展游走;query 0
和 query 1
是只通过特定属性条件(或者是无限制条件)找到满足的点、边;而在 Nebula Graph 里,graph-queries 在扩展的时候,图的原始数据已经按照 VID(点和边都是)排序过了,或者说在数据里已经索引过了,这个排序带来连续存储(物理上邻接)使得扩展游走本身就是优化过能快速返回结果。
索引是什么?
索引不是什么?
为了更好理解索引的限制、代价、能力,咱们来解释更多他的细节
这些信息可在我的个人网站的#手绘图和视频#(链接:https://www.siwei.io/sketch-notes/)里可以看到,参考下图:
因为左匹配的设计,在复杂查询场景,比如:针对纯属性条件出发查询里涉及到通配、REGEXP,Nebula Graph 提供了全文索引的功能,它是利用 Raft Listener 去异步将数据写到外部 Elasticsearch 集群之中,并在查询的时候去查 ES 去做到的,具体全文索引使用参见文档:https://docs.nebula-graph.com.cn/3.0.0/4.deployment-and-installation/6.deploy-text-based-index/2.deploy-es/。
在这个手绘图中,我们还可以看出
结论:
具体要参考 Nebula 官方的索引文档:https://docs.nebula-graph.io/3.0.0/3.ngql-guide/14.native-index-statements/ 一些要点是:
第一点,在 Tag 或者 EdgeType 上针对想要被条件反查点边的属性创建索引,使用 CREATE INDEX
语句;
第二点,创建索引之后的索引部分数据会同步写入,但是如果创建索引之前已经有的点边数据对应的索引是需要明确指定去创建的,这是一个异步的 job,需要执行语句 REBUILD INDEX
;
第三点,触发了异步的 REBUILD INDEX
之后,可用语句 SHOW INDEX STATUS
查询状态:
第四点,利用到索引的查询可以是 LOOKUP
,并且常常可以借助管道符在此之上做拓展查询,参考下面例子:
LOOKUP ON player \
WHERE player.name == "Kobe Bryant"\
YIELD id(vertex) AS VertexID, properties(vertex).name AS name |\
GO FROM $-.VertexID OVER serve \
YIELD $-.name, properties(edge).start_year, properties(edge).end_year, properties($$).name;
也可以是 MATCH
,这里边 v
是通过索引得到的,而 v2
则是在数据(非索引)部分拓展查询获得的。
MATCH (v:player{name:"Tim Duncan"})--(v2:player) \
RETURN v2.player.name AS Name;
第五点,复合索引的能力与限制。理解原生索引的匹配是左匹配能让我们知道对于超过一个属性的索引:复合索引,并且能帮助我们理解它的能力有限制,这里说几个结论:
(isRisky: bool, age: int)
,和 index_b: (age: int, isRisky: bool)
在根据 WHERE n.user.isRisky == true AND n.user.age > 18
筛选条件进行查询时,index_a 因为左匹配一个相等的短字段,显然效率更高。(isRisky: bool, age: int)
,和 index_b: (age: int, isRisky: bool)
在查询 WHERE n.user.age > 18
这个语句时,只有 index_b
复合最左匹配,能满足这个查询。LOOKUP
,详细的信息请参考文档:https://docs.nebula-graph.com.cn/3.0.1/4.deployment-and-installation/6.deploy-text-based-index/2.deploy-es/。Happy Graphing!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。