本文描述了 Snuba
查询语言 (SnQL
)。
以下是 SnQL
的查询结构:
MATCH simple | join | subquery
SELECT [expressions] | [aggregations BY expressions]
ARRAY JOIN [column]
WHERE condition [[AND | OR] condition]*
HAVING condition [[AND | OR] condition]*
ORDER BY expressions ASC|DESC [, expressions ASC|DESC]*
LIMIT expression BY n
LIMIT n
OFFSET n
GRANULARITY n
TOTALS boolean
这些查询作为字符串发送到 /:dataset/snql
端点,编码为以下格式的 JSON body
:
{
"query": "<query>",
"dataset": "<dataset>",
"consistent": bool,
"turbo": bool,
"debug": bool,
}
数据集(dataset)
通过查询使用的 url
隐含。在 JSON
主体中,除了 query
之外的所有字段都是可选的。
我们的数据模型由实体图表示。该子句标识了我们正在查询的子图(subgraphs)
的模式。目前支持三种类型的 MATCH
子句:
Simple:
MATCH (<entity> [SAMPLE n])
这相当于我们当前的所有查询。这是从单个实体(事件、事务等)查询数据。可以通过将其与实体一起添加来向查询添加可选 sample
。
例如:MATCH (events)
Subquery:
MATCH { <query> }
花括号内可以是另一个完整的 SQL
查询。子查询的 SELECT/BY
子句中的任何内容都将使用指定的别名在外部查询中公开。
例如:
MATCH {
MATCH (transactions)
SELECT avg(duration) AS avg_d BY transaction
}
SELECT max(avg_d)
Join(连接):
MATCH (<alias>: <entity> [SAMPLE n]) -[<join>]-> (<alias>: <entity> [SAMPLE n])
一个 join
代表一个多节点子图(subgraph)
,是一个包含不同节点之间的多个关系的子图。目前支持节点之间的 1..n
、n..1
和 1..1
有向关系。
对于 JOIN
,每个实体都必须有一个别名,这是一个唯一的字符串。 抽样(Sampling)
也可以应用于 join
中的任何实体。<join>
是在 Snuba
中的 Entity
中指定的字符串,是一组 join
条件的简写。可以有多个 join
子句,用逗号分隔。
例如:
MATCH
(e: events) -[grouped]-> (g: groupedmessage),
(e: events) -[assigned]-> (a: groupassignee)
SELECT count() AS tot BY e.project_id, g.id
WHERE a.user_id = "somebody"
join
类型(left/inner
)和 join key
是数据模型的一部分,而不是查询的一部分。它们被硬编码在实体代码中。这是因为没有实体可以安全地与底层数据库的分布式版本中的任何其他实体连接。
match
子句提供给 where
子句的元组(tuple)
看起来与传统 join
子句生成的元组完全一样:
[
{"e.project_id": 1, "g.id": 10}
{"e.project_id": 1, "g.id": 11}
{"e.project_id": 2, "g.id": 20}
...
]
该子句指定应在输出中返回哪些结果。如果存在聚合(aggregation
),则 BY
子句中的所有内容都被视为分组 key
。如果我们想要聚合整个结果集,则可以在没有 BY
子句的情况下进行聚合,但在这种情况下,SELECT
中只能包含聚合。即使有 BY
子句,空的 SELECT
子句也是无效的。
SELECT
子句中的表达式
可以是列
、算术
、函数
或三
者的任意组合。如果查询是 join
,则每一列都必须有一个符合条件的别名,该别名与 MATCH
子句中的实体别名之一匹配。
这是在聚合之前发生的查询的过滤器(如 SQL
中的 WHERE
)。
条件是 LHS OP RHS*
形式的中缀表达式,其中 LHS
和 RHS
是字面值
或表达式
。OP
指的是一个特定的运算符
来比较
两个值。这些运算符是 =
、!=
、<
、<=
、>
、>=
、IN
、NOT IN
、LIKE
、NOT LIKE
、IS NULL
、IS NOT NULL
之一。请注意,当使用像 IS NULL
这样的运算符时,RHS
是可选的。
可以使用布尔关键字 AND
或 OR
组合条件。它们也可以使用 ()
进行分组。
像 WHERE
子句一样工作,但它在 SELECT
子句中声明的聚合之后应用。所以我们可以在这里对聚合函数的结果应用条件。
指定对结果集进行排序的表达式。
不言自明,它们采用整数并在 Clickhouse
查询中设置相应的值。如果查询未指定 limit
或 offset
,它们将分别默认为 1000
和 0
。
一个整数,表示对基于时间的结果进行分组的粒度。
如果设置为 True
,来自 Snuba
的响应将有一个 “totals”
key,其中包含所有选定行的总值。
如果 MATCH
子句中的节点未提供采样率
,则可以在此处指定。在这种情况下,Snuba
会将 sample right
分配给查询中的节点之一。sample
可以是介于 0
和 1
之间的浮点数,表示要采样的行的百分比。
或者它可以是一个大于 1
的整数,表示要采样的行数。