SPL (SLS Processing Language) — 日志服务管道式数据处理语言。语句以 | 分割:查询语句 | 分析语句。
1. 基础语法
SPL 语句结构
<data-source> | <spl-expr> | <spl-expr> ;
* = LogStore 全部数据
| = 管道符,前级输出为后级输入
; = 语句结束符(末尾可省略)
语法符号
| 符号 |
说明 |
* |
LogStore 数据占位符 |
. |
SPL 关键字前缀(如 .let) |
\| |
管道符 |
'...' |
字符串常量 |
"..." |
字段名 / 字段名模式 |
-- / /*...*/ |
单行 / 多行注释 |
$ |
命名数据集引用($name) |
数据类型
| 类型 |
说明 |
| VARCHAR |
可变字符(除时间字段外,SPL 输入字段初始类型均为 VARCHAR) |
| BOOLEAN / TINYINT / SMALLINT / INTEGER / BIGINT / HUGEINT |
整数系列 |
| REAL / DOUBLE |
浮点数 |
| TIMESTAMP |
纳秒精度 UNIX 时间戳 |
| DATE |
YYYY-MM-DD |
| ARRAY |
数组,下标从 1 开始,a[1] |
| MAP |
字典,a['foo'] |
| JSON |
JSON 类型 |
2. SPL 指令速查
指令表达式语法:cmd -option=<value> -flag <expression> as <output>, ...
2.1 控制指令
.let — 定义命名数据集
.let <name> = <spl-expr>
.let err = * | where status >= 500 | extend msg='ERR';
$err; -- 输出命名数据集
2.2 字段操作
project — 保留/重命名字段
| project -wildcard <pattern>, <new>=<old>, ...
* | project level, err_msg
* | project log_level=level
* | project -wildcard "__tag__:*"
默认保留 __time__、__time_ns_part__,不可重命名或覆盖。
project-away — 移除字段
| project-away -wildcard <pattern>, ...
* | project-away -wildcard "__tag__:*"
project-rename — 重命名字段
| project-rename <new>=<old>, ...
* | project-rename log_level=level
2.3 SQL 计算指令
extend — 通过 SQL 表达式产生新字段(重名直接覆盖)
| extend <output>=<sql-expr>, ...
* | extend Duration = EndTime - StartTime
* | extend a = json_extract(content, '$.body.a')
* | extend status = cast(status as BIGINT)
* | extend k1='v1', k2='v2', k3='v3' -- 合并多个 extend
where — 根据 SQL 表达式过滤数据
| where <sql-expr>
* | where userId = '123'
* | where cast(status as BIGINT) >= 500
* | where regexp_like(server_protocol, '\d+')
* | where a = 'x' and b = 'y' -- 合并多个 where
2.4 聚合指令
stats — 聚合统计
stats <alias>=<aggFunc> by <group>, ...
| 聚合函数 |
| count, count_if, min, max, sum, avg, skewness, kurtosis, approx_percentile, approx_distinct, bool_and, bool_or, every, arbitrary, array_agg |
* | stats pv = count(*) by ip
* | stats pv = count(*) -- 无分组全局统计
* | extend lat = cast(latencyMs as bigint) | stats minLat=min(lat), maxLat=max(lat) by ip
默认返回前 100 条,配合 limit 获取更多。
sort — 排序
sort <field> [asc|desc], ...
* | sort latencyMs desc
limit — 限制行数
limit (<offset>,) <size>
* | sort latencyMs | limit 1
* | limit 5, 10 -- 跳过5条取10条
不配合 sort 时,limit 输出顺序随机。
3. SQL 分析语法
查询语句 | 分析语句
- 查询语句可单独使用;分析语句必须与查询语句一起使用
- 分析语句无需 FROM/WHERE(默认分析当前 LogStore),不区分大小写,末尾不加分号
- 分析语句不支持 offset
* | SELECT status, count(*) AS PV GROUP BY status
4. 查询语句语法
4.1 全文查询
keywords1 [ and | or | not ] keywords2 ...
- 多个关键词之间默认
and 关系
- 通配符
*(0+字符)、?(1字符),不能用在词开头
GET
GET or POST
Jo? -- Joe, Jon 等
cn* -- 以 cn 开头的词
4.2 字段查询
field [ : | > | >= | < | <= | = | in ] value [ and | or | not ... ]
运算符速查
| 运算符 |
说明 |
示例 |
: |
Key:Value |
status:200 |
and / or / not |
逻辑运算 |
status:200 and method:GET |
( ) |
优先级 |
(GET or POST) and status:200 |
"" |
包裹特殊字符/关键词 |
"file info":apsara, "and" |
* / ? |
通配符 |
host:www*com, host:aliyund?c |
> >= < <= |
比较(long/double) |
request_time>100 |
= |
等于(long/double) |
request_time=100 |
in [a b] / in (a b) |
闭区间/开区间 |
status in [200 299] |
__source__ |
日志源 |
__source__:192.0.2.* |
__tag__ |
元数据 |
__tag__:__receive_time__:1609... |
__topic__ |
日志主题 |
__topic__:nginx_access_log |
运算符优先级(高→低)
:, "", (), and/not, or
字段类型与可用运算符
| 类型 |
可用运算符 |
| text |
and, or, not, (), :, "", *, ? |
| long/double |
and, or, not, (), >, >=, <, <=, =, in |
| JSON |
按内部字段类型 |
特殊查询
| 需求 |
语句 |
| 字段值不为空 |
not remote_user:"" |
| 字段值为空 |
remote_user:"" |
| 字段不存在 |
not remote_user:* |
| 字段存在 |
remote_user:* |
| 原始日志全文搜索 |
* \| where __line__ like '%error%' |
| 字段名含空格 |
"request method":PUT |
| 保留字当关键词 |
"and" |
| 短语精确匹配 |
#"redo_index/1" |
5. SQL 子句
| 子句 |
说明 |
| SELECT |
选择列,支持 AS 别名 |
| FROM log |
指定 LogStore(嵌套子查询中必须显式写) |
| WHERE |
过滤条件 |
| GROUP BY |
分组聚合,支持 ROLLUP、CUBE、GROUPING SETS |
| HAVING |
过滤分组/聚合结果 |
| ORDER BY |
排序,ASC/DESC |
| LIMIT |
限制行数(默认 100) |
| JOIN |
连接多表(跨 Logstore / MySQL / OSS) |
| UNION |
合并多个 SELECT 结果 |
| INTERSECT |
返回交集 |
| EXCEPT |
返回差集 |
| EXISTS |
判断子查询是否有结果 |
| UNNEST |
展开数组/map 字段 |
| WITH |
子查询保存为临时表 |
| VALUES |
构造临时数据 |
| INSERT INTO |
写入计算结果到其他 Logstore |
6. SQL 保留字段
AND, AS, BETWEEN, BY, CASE, CAST, CROSS, CUBE,
CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP,
DISTINCT, ELSE, END, ESCAPE, EXCEPT, EXISTS,
FROM, GROUP, GROUPING, HAVING, IN, INNER,
INSERT, INTERSECT, INTO, IS, JOIN, LEFT, LIKE,
LIMIT, LOCALTIME, LOCALTIMESTAMP, NATURAL, NOT,
NULL, ON, OR, ORDER, OUTER, RIGHT, ROLLUP,
SELECT, THEN, TRUE, UNION, UNNEST, VALUES,
WHEN, WHERE, WITH
7. 嵌套子查询
子查询用 () 包裹,内部须写 FROM log。
-- 基础
* | SELECT key FROM (sub_query)
-- 求最小 PV
* | SELECT min(PV) FROM (
SELECT count(1) as PV FROM log GROUP BY request_method
)
-- 同比
* | SELECT diff[1] AS today, diff[2] AS yesterday, diff[3] AS ratio
FROM (
SELECT compare(PV, 86400) AS diff FROM (
SELECT count(*) AS PV FROM log
)
)
-- 占比(窗口函数)
* | SELECT uri, c, round(c * 100.0 / sum(c) over(), 2) AS "占比%"
FROM (SELECT request_uri AS uri, count(*) AS c FROM log GROUP BY uri)
8. 函数分类速查
| 分类 |
常用函数 |
| 聚合 |
count, count_if, min, max, sum, avg, array_agg |
| 字符串 |
concat, length, position, replace, split, split_part, chr |
| 日期时间 |
current_date, date_parse, date_format, date_trunc, date_add, to_unixtime, day |
| JSON |
json_extract, json_extract_scalar, json_array_get, json_array_length, json_parse |
| 正则 |
regexp_extract, regexp_extract_all, regexp_like, regexp_replace, regexp_split |
| 类型转换 |
cast, try_cast, typeof |
| 条件表达式 |
CASE WHEN ... THEN ... ELSE ... END, IF, COALESCE, NULLIF, TRY |
| 数组 |
array_distinct, array_join, reverse, filter, reduce, transform, [] |
| Map |
cardinality, element_at, histogram, map |
| 数学 |
abs, ceil, round, log, mod, random |
| 统计 |
corr, covar_pop, regr_intercept, beta_cdf |
| 窗口 |
dense_rank, lag + 聚合函数 |
| 同比环比 |
compare, ts_compare |
| 预测 |
ts_predicate_simple |
| 比较 |
>, >=, <, <=, =, !=, BETWEEN, IS NULL, IS NOT NULL, LIKE, IN, ALL, ANY |
| 逻辑 |
AND, OR, NOT |
| IP |
ip_to_province, ip_to_city, ip_prefix, ipv6_to_city |
| URL |
url_encode, url_decode, url_extract_path, url_extract_query |
| 估算 |
approx_distinct, approx_percentile, numeric_histogram |
| 二进制 |
from_base64, from_hex, to_hex, sha256 |
| 位运算 |
bitwise_and, bitwise_or, bitwise_not, bit_count |
| 地理 |
geohash, ST_AsText, ST_Contains, ST_Buffer |
| HyperLogLog |
approx_set, cardinality, merge |
| 窗口漏斗 |
window_funnel |
| 单位换算 |
convert_data_size, format_duration |
9. 常用场景速查
9.1 SPL vs SQL
| 场景 |
SQL |
SPL |
| 过滤 |
WHERE Type='write' |
\| where Type='write' |
| 选字段+重命名 |
SELECT a AS x, b |
\| project x=a, b |
| 排除字段 |
— |
\| project-away -wildcard "tag:*" |
| 计算新字段 |
SELECT cast(s AS BIGINT) |
\| extend s = cast(s as BIGINT) |
| 聚合 |
SELECT count(*) PV GROUP BY ip |
\| stats pv=count(*) by ip |
9.2 关键注意事项