Sentry 監(jiān)控 - Snuba 數(shù)據(jù)中臺(tái)架構(gòu)(SnQL 查詢語言簡(jiǎn)介)
以下是 SnQL 的查詢結(jié)構(gòu):
- 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
這些查詢作為字符串發(fā)送到 /:dataset/snql 端點(diǎn),編碼為以下格式的 JSON body:
- {
- "query": "<query>",
- "dataset": "<dataset>",
- "consistent": bool,
- "turbo": bool,
- "debug": bool,
- }
數(shù)據(jù)集(dataset)通過查詢使用的 url 隱含。在 JSON 主體中,除了 query 之外的所有字段都是可選的。
MATCH
我們的數(shù)據(jù)模型由實(shí)體圖表示。該子句標(biāo)識(shí)了我們正在查詢的子圖(subgraphs)的模式。目前支持三種類型的 MATCH 子句:
Simple:
- MATCH (<entity> [SAMPLE n])
這相當(dāng)于我們當(dāng)前的所有查詢。這是從單個(gè)實(shí)體(事件、事務(wù)等)查詢數(shù)據(jù)??梢酝ㄟ^將其與實(shí)體一起添加來向查詢添加可選 sample。
例如:MATCH (events)
Subquery:
- MATCH { <query> }
花括號(hào)內(nèi)可以是另一個(gè)完整的 SQL 查詢。子查詢的 SELECT/BY 子句中的任何內(nèi)容都將使用指定的別名在外部查詢中公開。
例如:
- 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])
一個(gè) join 代表一個(gè)多節(jié)點(diǎn)子圖(subgraph),是一個(gè)包含不同節(jié)點(diǎn)之間的多個(gè)關(guān)系的子圖。目前支持節(jié)點(diǎn)之間的 1..n、n..1 和 1..1 有向關(guān)系。
對(duì)于 JOIN,每個(gè)實(shí)體都必須有一個(gè)別名,這是一個(gè)唯一的字符串。 抽樣(Sampling)也可以應(yīng)用于 join 中的任何實(shí)體。
例如:
- 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 是數(shù)據(jù)模型的一部分,而不是查詢的一部分。它們被硬編碼在實(shí)體代碼中。這是因?yàn)闆]有實(shí)體可以安全地與底層數(shù)據(jù)庫(kù)的分布式版本中的任何其他實(shí)體連接。
match 子句提供給 where 子句的元組(tuple)看起來與傳統(tǒng) join 子句生成的元組完全一樣:
- [
- {"e.project_id": 1, "g.id": 10}
- {"e.project_id": 1, "g.id": 11}
- {"e.project_id": 2, "g.id": 20}
- ...
- ]
SELECT .. BY
該子句指定應(yīng)在輸出中返回哪些結(jié)果。如果存在聚合(aggregation),則 BY 子句中的所有內(nèi)容都被視為分組 key。如果我們想要聚合整個(gè)結(jié)果集,則可以在沒有 BY 子句的情況下進(jìn)行聚合,但在這種情況下,SELECT 中只能包含聚合。即使有 BY 子句,空的 SELECT 子句也是無效的。
SELECT 子句中的表達(dá)式可以是列、算術(shù)、函數(shù)或三者的任意組合。如果查詢是 join,則每一列都必須有一個(gè)符合條件的別名,該別名與 MATCH 子句中的實(shí)體別名之一匹配。
WHERE
這是在聚合之前發(fā)生的查詢的過濾器(如 SQL 中的 WHERE)。
條件是 LHS OP RHS* 形式的中綴表達(dá)式,其中 LHS 和 RHS 是字面值或表達(dá)式。OP 指的是一個(gè)特定的運(yùn)算符來比較兩個(gè)值。這些運(yùn)算符是 =、!=、<、<=、>、>=、IN、NOT IN、LIKE、NOT LIKE、IS NULL、IS NOT NULL 之一。請(qǐng)注意,當(dāng)使用像 IS NULL 這樣的運(yùn)算符時(shí),RHS 是可選的。
可以使用布爾關(guān)鍵字 AND 或 OR 組合條件。它們也可以使用 () 進(jìn)行分組。
HAVING
像 WHERE 子句一樣工作,但它在 SELECT 子句中聲明的聚合之后應(yīng)用。所以我們可以在這里對(duì)聚合函數(shù)的結(jié)果應(yīng)用條件。
ORDER BY
指定對(duì)結(jié)果集進(jìn)行排序的表達(dá)式。
LIMIT BY/LIMIT/OFFSET
不言自明,它們采用整數(shù)并在 Clickhouse 查詢中設(shè)置相應(yīng)的值。如果查詢未指定 limit 或 offset,它們將分別默認(rèn)為 1000 和 0。
GRANULARITY
一個(gè)整數(shù),表示對(duì)基于時(shí)間的結(jié)果進(jìn)行分組的粒度。
TOTALS
如果設(shè)置為 True,來自 Snuba 的響應(yīng)將有一個(gè) “totals” key,其中包含所有選定行的總值。
SAMPLE
如果 MATCH 子句中的節(jié)點(diǎn)未提供采樣率,則可以在此處指定。在這種情況下,Snuba 會(huì)將 sample right 分配給查詢中的節(jié)點(diǎn)之一。sample 可以是介于 0 和 1 之間的浮點(diǎn)數(shù),表示要采樣的行的百分比。
或者它可以是一個(gè)大于 1 的整數(shù),表示要采樣的行數(shù)。