![154d88efa79bc6441a372ff9c769646b.png](https://i-blog.csdnimg.cn/blog_migrate/efe3573f419d7684598ce9544097c663.png)
RedisGraph
- a graph database module for Redis
Graph
![93e9817ed6599d142ce20ad7bab858c0.png](https://i-blog.csdnimg.cn/blog_migrate/5ad8227d8b4fa74b29b05ca864a7be76.jpeg)
- 内存图
- 矩阵均为nxn的方阵,n为顶点数
- lebel矩阵为0-1对角方阵
- 邻接矩阵adjacecy_matrix为0-1方阵,顶点间只要有边连接即为1
- 关系矩阵relations_matrix为0-1方阵,顶点间存在relation边则为1
- 关系映射relationMap_matrix保存顶点间边id到Edge的映射
- 顶点表nodes与边表edges
计算模型
![10582ca9e2bec1fe54ad2176f1f7fc1e.png](https://i-blog.csdnimg.cn/blog_migrate/979bb4608d91d488b9687993d8b30d97.png)
执行计划树
![1babed7ebf849c9fdf20979be8fa9e16.png](https://i-blog.csdnimg.cn/blog_migrate/46f1aff275d5b3af363a2a6b50febd27.png)
- 先自顶向下遍历AST构建出ExecutionPlan内Traverser树
- 执行ExecutionPlan时,自底向上迭代执行各Traverser
- 每个Traverser都继承OpBaseTraverser迭代器,拥有Free()、Init()、Consume()、Reset()接口
- 父Traverser递归调用子Traverser的Consume()方法,从底部流式拉取满足匹配条件的记录Record
ExecutionPlan
![eb9188b2ba9aa731bee5ca3c89b0e467.png](https://i-blog.csdnimg.cn/blog_migrate/5ccd316dde9ee95c97cc76dfed7939a8.jpeg)
- 解析query,构建语法树AST
- 将AST通过WITH、RETURN与其他语段切分为sub-AST,对每个sub-AST构建子可执行计划sub-ExecutionPlan
- 通过AST构建QueryGraph
- 通过AST构建带ArithmeticExpression的FilterTree
- 对QueryGraph,构建NodeScanTraverser,对每条查询路径QueryPath分析出AlgebraicExpression表,再根据AlgebraicExpression表组合成ConditionalTraverser链
- 通过AST构建带ArithmeticExpression的ProjectTraverser,并作为Traverser树树根
- 递归遍历FilterTree构建FilterTraverser,将其插入到Traverser树内最早解析出FilterTree内所有别名的Traverser的上游
- Traverser树构成ExecutionPlan
- 将sub-ExecutionPlan合并成pipeline来组成ExecutionPlan
- 优化ExecutionPlan
- 自底向上迭代执行ExecutionPlan中各Traverser,批量pull出Record
- Record记录查询路径信息。提取Record内值组成结果ResultSet
QueryGraph
![ca7dfbabeb71dab05e46a2fdd5a76e6b.png](https://i-blog.csdnimg.cn/blog_migrate/f13963838c0fb2e0f5c01157c4385894.jpeg)
- 根据AST match segments构建为QueryGraph
- QueryGraph为有向有环图(双向可设置both标志),两点间可能有多条边
- 将QueryGraph分裂为多条Path组合。使用dfs方法每次从QueryGraph中抽取一条最长查询路径LongestPath,通过LongestPath构建AlgebraicExpression表
- AlgebraicExpression即把路径遍历变为矩阵运算
- 对多引用顶点(相同别名,多次引用)进行分裂,断成多条Path,因为要保证在查询路径中顶点的多次存在性。分裂条件为:对树根顶点与环相交顶点进行分裂;对return语句中引用的需要返回的中间变量顶点进行Path分裂
![620c94d33537a51028e2aa4e09092065.png](https://i-blog.csdnimg.cn/blog_migrate/8da1059ffc91c3cfe832b462a064cc56.png)
树型与环型图
![d26d638a754df8a07235ce201e91dcda.png](https://i-blog.csdnimg.cn/blog_migrate/f69b7298b63a1a1d27df8b88e7a2e488.png)
环型图分类Path
ArithmeticExpression
![f66a0ddfc0516055438433481a42f5c3.png](https://i-blog.csdnimg.cn/blog_migrate/8f0ca91c5013c8ef555b5a1727b79af1.jpeg)
AST树
![c1b5f78b7ecaf8605260de64812848fa.png](https://i-blog.csdnimg.cn/blog_migrate/9fd36ebaccdc293894fe998833784952.jpeg)
对AST中运算操作构建ArithmeticExpression运算表达式树
FilterTree
![9f782aaebd96325954dc038ef06803e3.png](https://i-blog.csdnimg.cn/blog_migrate/ee03de599ce219cd27ab38efe77e5477.jpeg)
AST树
![7e2ec025c9b2af1a50240ebbef3e8683.png](https://i-blog.csdnimg.cn/blog_migrate/51e0dfc356f06e6f0c06d3603e6e77fb.jpeg)
- 对AST中判断操作与与或操作构建FilterTree
- FliterTree叶子节点为ArithmeticExpressionTree
AlgebraicExpression
![0c37a9277bd3135a52ca58cf58518c92.png](https://i-blog.csdnimg.cn/blog_migrate/34cb5fdb491285a08d15b2ffff39b119.jpeg)
- 每条Path即(srcNode->Edge1...EdgeN->dstNode)遍历可转换矩阵运算
- 矩阵运算的输入为QueryGraph中顶点代表的srcNode集合(p),QueryGraph中边是中间变量(ef,ev,ew),输出为QueryGraph中顶点代表的dstNode集合(e)
- 对多引用顶点进行分裂,成为多个子代数表达式的矩阵运算。比如{(p1)-[]->(p2)-[]->(p3)-[]->(p2)-[]->(p4)},2个p2完全一样,p2即环顶点,需要分裂顶点以断成多条路径,遍历下一条路径时要检查源顶点在上一条路径中是否存在(首尾相接,需要一致)
- 矩阵乘法需要符合顺序,逆序的边需要矩阵转置
- Path中顶点转为LabelMatrix
- Path中边转为AdjMatrix或RelationMatrix
- 矩阵乘法相当于批量执行遍历操作(bfs)
ConditionalTraverser
![66d4d0a247812e55a99f8ce9ad85718e.png](https://i-blog.csdnimg.cn/blog_migrate/3a651effe6a4ef31da741b3089ad5fa1.jpeg)
- 整体为遍历操作得到路径集合,单条路径操作类似于dfs,多个中间解集合表示路径已根据多引用顶点断开成多个子查询路径
- 每个子查询路径间运算可用矩阵运算(相当于bfs操作)。比如解集合(g1->g2)的结果路径集合p1,p2,p3可由矩阵运算得到
- 集合间传递中间变量为record。record存储路径序列,相同顶点去重,边可选,格式为Path(srcNode1, Edge1, destNode1, Edge2...destNodeN-1, EdgeN, destNodeN)
参考
- RedisGraph,https://oss.redislabs.com/redisgraph/
- RedisConf17 - Redis Graph。https://www.slideshare.net/RedisLabs/redisconf17-redis-graph
- RedisConf18 - Lower Latency Graph Queries in Cypher with Redis Graph。https://www.slideshare.net/RedisLabs/redisconf18-lower-latency-graph-queries-in-cypher-with-redis-graph