openGemini是一款面向物联网、车联网、工业互联网、运维监控等领域的开源分布式时序数据库。作为一款专门为时序场景设计并实现的数据库系统,openGemini具有卓越的读写性能和高效的数据分析能力。本文主要介绍openGemini查询执行的流程以及关键源码解析,以方便用户理解openGemini如何高效执行查询的过程。
查询整体流程
查询的整体流程如图所示,ts-sql负责与client交互,接收查询sql并且返回查询结果。具体来说,ts-sql在查询时从ts-meta中获取目标表元数据信息,生成查询计划,再转发到ts-store执行,ts-store负责从磁盘捞取数据并且进行计算,进一步将结果返回给ts-sql。
本文以聚合查询为例,详细剖析查询流程。
Select SUM(field)
FROM mst
WHERE tag=1 AND time > now()-1h
GROUP BY tag2
ts-sql在查询流程中的数据处理过程
ts-sql节点在查询流程中主要参与的有两个模块,分别为Compiler以及Pipeline Executor,前者负责解析输入的sql语句并生成对应的语法解析树;后者负责根据语法树生成相对应Logic Plan,再转化成DAG图并发执行并获取计算的结果。
-
Compiler
Compiler和传统的数据库Compiler功能相似,由词法解析的scanner, 语法和语义解析的Parser构成,Parser使用的是基于LR语法的Yacc语法解析器,在生成对应sql的语法树之后,Compiler会有一个查询重写过程,通过与ts-meta交互获取查询列的数据类型并计算对应查询列的数据类型。
-
PipelineExecutor
PipelineExecutor的查询流程主要分为以下步骤:
-
PipelineExecutor根据语法解析结果生成对应的Logic Plan,该Logical Plan主要包含查询计划和数据表的Schema信息;
-
Logic Plan优化,完成算子下推,Logic Plan优化前后对比如下图所示。
-
根据优化之后的Logical Plan生成用于查询的DAG图
整个查询计划可以由一张DAG图表示,每个边通过channel进行通信,每个节点代表一个用于查询计算的物理算子。PipelineExecutor执行DAG时,按照DAG图自底向上执行,RPC Reader负责接收从ts-store发送的数据,通过反序列化,将数据存放到chunk,交由上层Transform计算,以此类推。
-
执行查询计划
每一个DAG节点都是由一个独立的线程负责运行,以保证查询计算的高并发和高效率。
-
返回查询结果
相关数据结构
在执行查询计划时,物理算子之间用于通信的数据结构称之为chunk:
Column结构如下:
Chunk数据结构可一次性存放多列数据,查询计算均为多值计算模型,不同类型的数据放在相应的数组中,同时计算多列数据,极大的提高了查询效率。
ts-store在查询流程中的数据处理过程
ts-store在接收到ts-sql发送的逻辑计划之后,也会根据对应的逻辑计划创建相应的DAG子图,查询和执行流程与ts-sql端的一致,唯一的区别是DAG子图的叶子节点为ChunkReader的结构,ChunkReader的数量根据当前机器cpu的核数来决定,最大程度保证查询的并发。
首先根据索引以及过滤条件过滤出时间线,接着均匀排布在多个ChunkReader中,再根据Tag Set排序之后按照顺序依次执行,通过索引扫描捞取数据进行计算。
-
ChunkReader
ChunkReader内部也是一个DAG子图,但是用于执行的物理算子不再是Transform,而是另一种迭代器结构Cursor,查询在ChunkReader内部也不再是并发而是串行执行,以免查询的并发线程过高。
每一个groupCursor都是以时间线为粒度的执行器,按照Tag Set顺序依次执行。TagsetCursor对应的是transform中的merge transform。
-
TsmMergeCurosr
TsmMergeCurosr数据来源有两种,分别是满足条件的所有数据,以及一些常用聚合查询的预聚合数据以提高查询速度。
常用Transform及其功能说明
名称 | 作用 |
---|---|
aggregate transform | 数据聚合 |
merge transform | 数据排序 |
RpcReader transform | 通过rpc接收chunk |
RpcSender transform | 通过rpc发送chunk |
align transform | 数据对齐 |
fill transform | 填充空值数据:线性填充,平均填充,空值填充 |
filter transform | 使用子查询时外用于外查询的过滤 |
orderby transform | 使用子查询时重构外查询group by dimension |
subquery transform | 子查询列转换 |
limit transform | 截断数据 |
groupby transform | 重构子查询查询列 |
materialize transform | 物化 |
httpsender transform | 数据结果返回 |
结束
本文以宏观地视角对openGemini查询流程做了一个整体概述并详细介绍了每个模板的具体实现流程,希望对大家阅读源码有所帮助。更多精彩内容,还可以关注openGemini微信公众号~!
penGemini 官网:http://www.openGemini.org
openGemini 开源地址:https://github.com/openGemini
openGemini 公众号:
欢迎关注~ 诚邀你加入 openGemini 社区,共建、共治、共享未来!