DQL 查询
简介
DQL 是专为 DataFlux 开发的语言,语法简单,方便使用,可在 DataFlux Studio 进行数据查询,也可通过 客户端命令行 进行数据查询。
在 DataFlux Studio 添加图表页面中,支持「DQL 查询」和「指标查询」两种查询方式,用户可选择「DQL 查询」自行编写查询语句进行数据查询,同时可选择不同的图表类型进行查询结果展示。
一个图表同时支持多条 DQL 查询,点击「添加查询」即可添加一个新的 DQL 查询。
DQL 定义
随着不同语法的逐步支持,该文档会做不同程度的调整和增删。
全局约束如下:
非关键字(如指标名、标签名等)大小写敏感,关键字及函数名大小写不敏感
以
#
为行注释字符,不支持行内注释支持的操作符:
+
- 加法-
- 减法*
- 乘法/
- 除法%
- 取模=
- 等于!=
- 不等于<=
- 小于等于<
- 小于>=
- 大于等于>
- 大于^
- 指数运算&&
- 逻辑与||
- 逻辑或
支持的关键字:
AND AS ASC AUTO
BY DESC FALSE FILTER
LIMIT LINK WITH LINEAR
NIL OFFSET OR PREVIOUS
SLIMIT SOFFSET TRUE WITH
标识符:标识符有几种形式,便于兼容各种变量命名形式
- 正常变量名中只能出现
[_a-zA-Z0-9]
这些字符,且首字符不能是数字。如_abc, _abc123, _123ab
- 其它形式的变量名处理方式:
this+is-a*xx/yy^zz?variable
,by
需写成`this+is-a*xx/yy^zz?variable`
,`by`
,前者变量中带运算符,后者的by
是 DQL 关键字这是一个中文或其它非英文字符变量
需写成`这是一个中文或其它非英文字符变量`
- 变量中就带了一个反引号,
this`is-a-vairalbe
需写成`identifier("this`is-a-vairalbe")`
来修饰
- 正常变量名中只能出现
字符串值可用双引号和单引号:
"this is a string"
和'this is a string'
是等价的数据类型:支持浮点(
123.4
,5.67E3
)、整形(123
,-1
)、字符串('张三'
,"hello world"
)、Boolean(true
,false
)四种类型特殊函数
re('regex')
- 表示正则表达式,如re("*abc")
。对于比较复杂的正则,可用`complex-regex`
这种形式来避免对'
和"
的转义。tz()
- 时区,有两种形式支持tz(+-12)
以 24 个时区的偏移来指定,如tz(+8),tz(8), tz('Asia/Shanghai')
是一样的,夏令时不能通过这种形式来指定。tz('Asia/Shanghai')
以国际标准形式来指定时区。对于夏令时,只能通过这种形式来指定。
identifier()
用于修饰变量名中带`
字符的变量int()
和float()
对返回的数据做类型转换,仅适用于时序数据。
查询
查询遵循如下的语法范式,注意,各个部分之间的相对顺序不能调换,如 time-expr
不能出现在 filter-clause
之前。
namespace::
data-source
target-clause
filter-clause
time-expr
by-clause
limit-clause
offset-clause
slimit-clause
soffset-clause
从语法角度而言, data-source
是必须的(类似于 SQL 中的 FROM
子句),其它部分都是可选的。但实际查询过程中,对查询的实际执行会施加一定约束(比如 time_expr
不允许时间跨度太大)
举例:
# 获取指标集 cpu 最近 5 分钟所有字段的数据
M::cpu [5m]}
# 查找匹配正则表达式 *db 的所有指标最近 5 分钟的数据
M::re('*db') [5m]
# 获取指标集 cpu 10 分钟前到 5 分钟前的所有字段数据
M::cpu [10m:5m]
# 获取指标集 cpu 10 分钟前到 5 分钟前的所有字段数据,以 1分钟的间隔来聚合
M::cpu [10m:5m:1m]
# 查询时序数据指标集 cpu 最近 5分钟的两个字段 time_active, time_guest_nice,
# 以 host 和 cpu 两个 tag 来过滤,同时以 host 和 cpu 来分组显示结果。
M:: cpu:(time_active, time_guest_nice)
{ host = "host-name", cpu = "cpu0" } [5m] BY host,cpu
# 以身高倒排,获取前十
O::human:(height, age) { age > 100, sex = "直男" } ORDER BY height LIMIT 10
M::cpu,mem:(time_active, time_guest_nice, host) { host = "host-name", cpu = "cpu0" } [5m] BY host,cpu
注意,::
和 :
两边都是可以添加空白字符的,如下语句是等价的:
M::cpu:(time_active, time_guest_nice)
{ host = "host-name", cpu = "cpu0" } [5m]
M ::cpu : (time_active, time_guest_nice)
{ host = "host-name", cpu = "cpu0" } [5m]
M :: cpu : (time_active, time_guest_nice)
{ host = "host-name", cpu = "cpu0" } [5m]
语句
namespace
语义层面,目前支持以下几种种数据源:
- M/metric - 时序指标数据
- O/object - 对象数据
- L/logging - 日志数据
- E/event - 事件数据
- T/tracing - 追踪数据
- R/rum - RUM 数据
- F/func - Func 函数计算
在语法层面,暂不对数据源做约束。数据源语法如下:
data-source ::
# 具体查询细节...
在具体的查询中,如果不指定数据源,则默认为 metric
或 M
,即时序指标是 DataFlux 的默认数据源。
data-source
指数据的来源,对不同来源的数据而言,其实际物理意义如下:
M
- 指时序数据中的指标集L
- 日志数据,以字段__source
作为逻辑意义上的分类O
- 对象数据,以字段__class
作为逻辑意义上的分类E
- 事件数据,以字段__source
作为逻辑意义上的分类T
- 追踪数据,以字段__serviceName
作为逻辑意义上的分类R
- RUM 数据,以字段type
作为逻辑意义上的分类F
- 暂无
target-clause
查询的结果列表:
M::cpu:(time_active, system_usage) {host="biz_prod"} [5m]
# 这里支持同一个指标集上不同指标(类型要基本匹配)之间进行计算
M::cpu:(time_active+1, time_active/time_guest_nice) [5m]
filter-clause
过滤子句用来对结果数据做过滤,类似 SQL 中的 where
条件:
# 查询人口对象中(__class=human)中百岁直男的身高
O::human:(height) { age > 100, sex = "直男" }
# 带正则的过滤
O::human:(height) { age > 100, sex != re("男") }
# 带计算表达式的过滤
O::human:(height) { (age + 1)/2 > 31, sex != re("男") }
# 带或运算表达式的过滤
O::human:(height) { age > 31 || sex != re("男"), weight > 70}
# 带聚合的的结果列
M::cpu:(avg(time_active) AS time_active_avg, time_guest_nice) [1d::1h]
# 带聚合填充的的结果列
M::cpu:(fill(avg(time_active) AS time_active_avg, 0.1), time_guest_nice) [1d::1h]
# 带有 in 列表的查询,其中 in 中选项关系为逻辑 or, in 列表中只能是数值或者字符串
O::human:(height) { age in [30, 40, 50], weight > 70}
关于填充:
- 数值填充:形如
cpu:(fill(f1, 123), fill(f2, "foo bar"), fill(f3, 123.456))
- 线性填充:如
cpu:(fill(f1, LINEAR))
- 前值填充:如
cpu:(fill(f1, PREVIOUS))
注意:多个过滤条件之间。默认是
AND
的关系,但如果要表达OR
的关系,就用||
操作符即可。如下两个语句的意思是相等的:
O::human:(height) { age > 31, sex != re("男") }
O::human:(height) { age > 31 && sex != re("男") }
来个复杂的过滤表达式:
M::some_metric {(a>123.45 && b!=re("abc")) || (z!="abc"), c=re("xyz")} [1d::30m]
time-expr
DataFlux 数据特点均有时间属性,故将时间的表达用单独的子句来表示:
[5m]
- 最近 5 分钟[10m:5m]
- 最近 10 分钟到最近 5 分钟[10m:5m:1m]
- 最近 10 分钟到最近 5 分钟,且结果按照 1 分钟的间隔聚合