OpenResty XRay™ YSQL 用户手册
YSQL 语言用户手册
本手册从用户角度记录 YSQL 语言。
目录
约定
为了方便起见,本文档通篇使用 ysql 一词来表示 Ops 语言。
有问题的示例代码每行开头会有一个问号 ?。例如:
? select *;
描述
YSQL 语言受 SQL 语言启发,但从未打算与 SQL 标准或某种 SQL 方言 100% 兼容。尽管如此,YSQL 代码看起来可能与 SQL 代码非常相似。
YSQL 语言作为 OpenResty XRay 平台的一部分提供。它是一种快速创建新的动态追踪分析器的方法,可以针对任何正在运行的进程,无需日志数据分析或目标应用程序的特殊数据 API 协作。
程序布局
YSQL 程序由多个用分号分隔的语句组成。目前只允许单个 select 查询语句,但将来可能会改变。下面是一个例子:
select uri, host
from ngx.reqs;
最后一个语句的尾部分号可以省略。
词法结构
整数
整数可以表示为十进制或十六进制字面量,如:
-3
519
0xdeadbeef
浮点数
浮点数可以表示如下:
3.1415926
2e8
4.2E2
字符串字面量
字符串字面量用单引号括起来,就像标准 SQL 语言一样,如:
'hello, world!'
此外,我们支持以下特殊转义序列来指定特殊字符:
\a 响铃,ascii 码 0x07
\b 退格,ascii 码 0x08
\f 换页,ascii 码 0x0c
\n 换行
\r 回车
\t 制表符
\v 垂直制表符
\\ 反斜杠 (\)
\' 单引号字符 (')
\" 双引号字符 (")
\<newline> 换行字符,就像 \n
下面是使用转义序列的示例:
'hello\nworld\t!'
正则表达式字面量
正则表达式字面量是一种表示用于模式匹配的正则表达式的方式 (与 like 二元运算符一起使用)。正则表达式字面量,比如 /[0-9]+/,可以用不同的分隔符括起来,如:
/[0-9]+/
rx/[0-9]+/
rx{[0-9]+}
rx([0-9]+)
rx[[0-9]+]
rx'[0-9]+'
rx"[0-9]+"
rx![0-9]+!
rx#[0-9]+#
您可以选择最佳分隔符来最小化正则表达式模式本身内部的必要转义。
目前只允许 Perl 兼容正则表达式和 POSIX 正则表达式语法的公共子集,但不包括反向引用语法 (如 \1、\2 等)。我们可能会在将来取消此限制。
支持使用括号进行子匹配捕获。
布尔字面量
YSQL 中的布尔字面量就是 true 和 false,就像 SQL 中一样。
空值
特殊的 null 关键字表示空值 (类似于 SQL 中的 null 值)。
YSQL 通常不涉及空值,因此很少使用此字面量。包含它只是为了完整性。
表
表名必须始终以其完全限定形式指定,除非用户给出了别名 (如在 from 子句中使用 as ALIAS 语法)。
YSQL 目前支持许多内置表,如 ngx.reqs 和 cpu.profile。详情请参见"内置表"部分。
列
当没有歧义时,列名可以用其裸名称表示,如 uri 和 host,或者用带表名的完全限定形式表示,如:
select ngx.reqs.uri
from ngx.reqs
其中 uri 列使用完全限定形式 ngx.reqs.uri 指定。
列也可以通过用户别名间接引用 (如在 select 列表中使用 as ALIAS 语法)。
运算符和表达式
YSQL 支持许多类似 SQL 的运算符和表达式类型,并有一些自己的补充。
所有运算符的优先级表如下:
3 一元 !
4 - (一元减), + (一元加)
5 || (字符串连接)
7 *, /, %
8 二元 -, +
12 = (比较), >=, >, <=, <, <>, !=, is, like, in, prefix, suffix, contains
13 between
14 not
15 and
17 or
19 left join, inner join
20 , (交叉连接)
通常可以使用括号 (...) 对优先级较低的运算符进行分组。
not ... 变体如 not between 和 is not 未在运算符优先级表中列出。
算术表达式
YSQL 支持以下二元算术运算符:加法 (+)、减法 (-)、乘法 (*)、除法 (/) 和取模 (%)。
它还支持一元算术运算符 - 和 +。
字符串连接
支持 SQL 风格的字符串连接运算符 ||。
关系表达式
YSQL 支持大多数常见的 SQL 风格关系运算符:
=(等于)!=或<>(不等于)<=<>>=between ... andin (value...)like和not likeis或is not
like 运算符支持两种形式的模式:
- SQL 风格的模式,带有元字符如
%(匹配零个或多个任意字符) 和_(匹配一个任意字符)。元字符可以用反斜杠 (/) 转义以表示%和_字符本身。 - 正则表达式字面量,如
/.../和rx{...}。
此外,YSQL 支持以下字符串匹配运算符,分别测试右侧字符串是否是左侧字符串中的前缀、子串或后缀:
prefixcontainssuffix
逻辑表达式
支持以下 SQL 风格的逻辑运算符:
- 二元
and - 二元
or - 一元
not
子查询
YSQL 目前不支持子查询,尽管 YSQL 编译器可以正常解析它们。
Select 查询语句
该语句包含一个 select 查询,带有以下一个或多个子句。注意 select 子句始终是必需的。
Select 子句
支持 SQL 风格的 select 子句。以下是一些示例:
select 3 + 2;
select 3 > 2;
select 'hello' || 'world';
关系表达式、算术表达式和字符串连接表达式都可以出现在 select 列表中。但是,这里不允许使用逻辑表达式。
每个选定的值可以在值表达式后面带一个可选的别名,就像标准 SQL 中一样,如:
select 3 > 2 res;
select 3 > 2 as res;
用户还可以使用星号(*)来表示 from 子句中出现的表或多个表的所有列,如:
select *
from ngx.reqs;
聚合函数如 sum()、avg()、min()、max() 和 count() 也可以在选定的值表达式中使用,如:
select count(*), sum(latency_s)
from ngx.reqs;
From 子句
from 子句也类似于标准 SQL 语言。可以指定单个表,如:
select uri
from ngx.reqs;
或者多个表连接在一起,如:
select user_bt, count(user_bt) cnt
from cpu.profile inner join proc
group by user_bt
order by count(user_bt) desc
limit 1000
目前 YSQL 仅支持 left join 和 inner join。不支持其他连接类型(尽管它们可能可以正常解析)。
Where 子句
where 子句与标准 SQL 语言中的相同。可以在这里指定一个逻辑表达式作为搜索条件。以下是一个示例:
select count(*)
from ngx.reqs
where uri prefix '/css/';
Group By 子句
group by 子句类似于标准 SQL 语言,如:
select count(*) as cnt, host
from ngx.reqs
group by host
order by cnt desc
limit 10;
Having 子句
having 子句类似于标准 SQL 语言。与 where 子句不同,having 子句中的搜索条件可以使用聚合函数,如 count() 和 sum()。以下是一个示例:
select max(latency_s), host
from ngx.reqs
group by host
having max(latency_s) > 0.5
也可以引用 select 列表中的别名,如:
select max(latency_s) max, host
from ngx.reqs
group by host
having max > 0.5;
Order By 子句
order by 子句类似于标准 SQL 语言。不过 YSQL 目前有一些限制:
order by子句中只允许一列。order by列只能是列名或count()聚合函数。
以下是一个示例:
select count(*), host
from ngx.reqs
group by host
order by count(*) desc;
也可以在 order by 子句中引用选定值表达式的别名(如果有),如:
select count(*) cnt, host
from ngx.reqs
group by host
order by cnt desc;
Limit 子句
limit 子句类似于标准 SQL 语言。以下是一个示例:
select *
from ngx.reqs
limit 10;
Offset 子句
offset 子句语法类似于 PostgreSQL 提供的 PL/SQL 语言。以下是一个示例:
select *
from ngx.reqs
offset 1
limit 10;
这将跳过第一行,仅输出第 2 到第 10 行。
内置表
以下是 YSQL 编译器当前支持的内置表的详细列表。我们正在快速添加新表和新列。
cpu.profile
该表表示 CPU 性能分析。它只能用作 from 子句中的第一个表。它没有任何列。它通常与其他表(如 ngx.reqs 等)连接使用。
ngx.reqs
该表用于检查 nginx(主)请求。这里排除了 Nginx 子请求。
它具有以下列:
argsHTTP 请求的 URI 查询字符串。
hostHTTP 请求的主机名。
latency_ms表示请求延迟的整数,单位为毫秒,如
120。latency_s表示请求延迟的浮点数,单位为秒,如
0.32。rewrite_phase_latency_s表示 rewrite 阶段延迟的浮点数,单位为秒,如
0.32。rewrite_phase_latency_ms表示 rewrite 阶段延迟的浮点数,单位为毫秒,如
0.32。access_phase_latency_s表示 access 阶段延迟的浮点数,单位为秒,如
0.32。access_phase_latency_ms表示 access 阶段延迟的浮点数,单位为毫秒,如
0.32。content_phase_latency_s表示 content 阶段延迟的浮点数,单位为秒,如
0.32。content_phase_latency_ms表示 content 阶段延迟的浮点数,单位为毫秒,如
0.32。req_header_latency_s表示接收 HTTP 请求头延迟的浮点数,单位为秒,如
0.32。req_header_latency_ms表示接收 HTTP 请求头延迟的浮点数,单位为毫秒,如
0.32。req_body_latency_s(待实现)表示接收 HTTP 请求体延迟的浮点数,单位为秒,如
0.32。req_body_latency_ms(待实现)表示接收 HTTP 请求体延迟的浮点数,单位为毫秒,如
0.32。keepalive布尔值,表示当前请求是否为当前 TCP 连接启用 HTTP keep-alive。
methodHTTP 请求的方法字符串。
scheme当前 HTTP 请求的协议字符串,如
http和https。uriHTTP 请求 URI(不包括任何查询字符串)。
raw_uriHTTP 原始请求 URI(包括查询字符串)。
client_ip字符串。IP 地址(IPv4 或 IPv6 或 unix socket 文件路径)。
req_body_size整数。请求体大小,单位为字节。
req_size整数。整个请求大小(包括头和体),单位为字节。
resp_size整数。整个响应大小(包括头和体),单位为字节(如果涉及压缩,则为压缩后的大小)。
resp_body_size整数。响应体大小,单位为字节。
server_port整数。当前请求访问的服务器端口。
status整数。HTTP 响应状态码(如 502 和 200)或内部 nginx 错误代码(如果没有有意义的 HTTP 状态码可用)。
is_ssl布尔值。当前请求是否使用 SSL 或 TLS。
tls_ver数字。TLS 协议版本号,如 1.2 和 1.3。
ssl_ver数字。SSL 协议版本号,如 2 和 3。
resp_is_chunked布尔值。响应体是否使用分块编码。
req_is_chunked布尔值。请求体是否使用分块编码。
http_ver数字。HTTP 协议版本(0.9、1.0、1.1、2.0)。
is_websocket布尔值。当前请求是否已升级到 WebSocket 协议。
resp_is_compressed布尔值。当前请求的响应体是否被压缩(通过 gzip 或其他编码)。
resp_gzip_level整数。响应体实际使用的 gzip 压缩级别(仅在当前响应实际被压缩时有意义)。
mime_type字符串。应该是类似 application/javascript 的值。应排除任何尾随参数,如 ; charset=utf-8。
uses_lua布尔值。当前请求是否在任何请求处理阶段使用任何 Lua 代码处理程序(如 log_by_lua、rewrite_by_lua 等)。
for_static_file布尔值。当前请求是否使用静态文件模块来提供当前机器文件系统上的静态文件。
has_upstream布尔值。当前请求是否使用代理(即使用 nginx upstream 模块)。
access_log_buf_size整数。当前请求的访问日志缓冲区大小,单位为字节。
uses_error_page布尔值。当前请求是否提供错误页面。
uri_changes整数。在请求处理阶段完成的 URI 更改次数(对应于 r->uri_changes)。
uri_changed布尔值。当前请求的 URI 是否曾被请求处理阶段更改(对应于 r->uri_changed)。
is_pipelined布尔值。当前请求是否为流水线请求(即 C 层面的 r->pipeline)。
resp_header_only布尔值。当前响应是否仅有头部(r->header_only)。
location字符串。最后服务当前请求的 nginx location 名称。
user_agent字符串。User-Agent 字符串。
conn_is_reused布尔值。当前请求是否重用了由较早请求创建的连接。
req_pool_size整数。当前请求的 nginx 内存池大小,单位为字节。
conn_pool_size整数。当前连接的 nginx 内存池大小,单位为字节。
proc
此表用于检查正在运行的操作系统进程。
它包含以下列:
user_bt用户态回溯,通常用于 C/C++/Rust 程序。
kern_bt内核态回溯。
res_mem整数。常驻内存大小,以字节为单位。
virt_mem整数。虚拟内存大小,以字节为单位。
shr_mem整数。共享内存大小,以字节为单位。
txt_mem整数。文本内存大小,以字节为单位。
page_size整数。页面大小,以字节为单位。
data_size整数。程序数据大小,以字节为单位(数据 + 栈)
pid整数。进程 ID。
pgid整数。进程组 ID。
ppid整数。父进程 ID。
exec_name字符串。目标进程的可执行文件名(在 stap 中映射到 execname())。
pexec_name字符串。目标进程的父进程的可执行文件名(在 stap 中映射到 pexecname())。
cpu_id整数。目标进程当前运行所在的 CPU 的 CPU ID。
luajit.vm
此表用于检查 luajit 虚拟机。
它包含以下列:
lua_btLua 函数级回溯
lua_line_btLua 行级回溯
vm_state应返回 LuaJIT VM 状态常量的整数值。
gc_countlj-gc.y 工具的大小输出,以字节为单位。
is_gc64布尔类型,用于 GC64 模式。
jit_maxtraceLuaJIT JIT 选项 maxtrace 的值
jit_hotloopLuaJIT JIT 选项 hotloop 的值
jit_maxmcodeLuaJIT JIT 选项 maxmcode 的值
jit_sizemcodeLuaJIT JIT 选项 sizemcode 的值
jit_maxsideLuaJIT JIT 选项 maxsize 的值。
jit_maxsnapLuaJIT JIT 选项 maxsnap 的值。
jit_minstitchLuaJIT JIT 选项 minstitch 的值
vfs.reads
此表用于检查 vfs 读取活动。
它包含以下列:
data_size整数。从 VFS 读取的数据大小,以字节为单位。
file_path字符串。我们正在读取数据的文件路径。
latency_s数字。当前 VFS 读取操作的延迟,以秒为单位。纳秒精度。允许小数部分。
latency_ms数字。当前 VFS 读取操作的延迟,以毫秒为单位。纳秒精度。允许小数部分。
vfs.writes
此表用于检查 vfs 写入活动。
它包含以下列:
data_size整数。写入 VFS 的数据大小,以字节为单位。
file_path字符串。我们正在写入数据的文件路径。
latency_s数字。当前 VFS 写入操作的延迟,以秒为单位。纳秒精度。允许小数部分。
latency_ms数字。当前 VFS 写入操作的延迟,以毫秒为单位。纳秒精度。允许小数部分。
作者
章亦春 yichun@openresty.com OpenResty Inc.
版权与许可
版权所有 (C) 2020-2025 OpenResty Inc. 保留所有权利。
本文档为专有文档,包含机密信息。未经版权所有者书面许可, 禁止在任何时候重新分发本文档。