ES|QL 子查询的三种源命令:FROM、TS 与 ROW

发布时间:2026/8/9 1:44:55
ES|QL 子查询的三种源命令:FROM、TS 与 ROW 一条查询三种数据来源 —— 用实时指标动态过滤日志将索引数据与内联测试值自由结合。你的过滤列表由时间序列数据即时生成无需硬编码任何值。在 Elasticsearch 9.5 中Elasticsearch 查询语言ES|QL的子查询功能迎来了重大扩展现在支持三种源命令source command——FROM读取索引数据、TS读取时间序列指标和ROW生成内联字面值。你可以单独使用它们也可以在同一查询中三者组合实现诸如“按实时指标行为过滤应用日志”或“混合真实数据与合成测试行”等高级需求而无需预先创建任何索引结构。如果你已经熟悉 ES|QL可能记得早期子查询只有一扇“正门”FROM。这很自然因为大多数查询开始时我们只想简单地从索引中获取文档。在之前的文章中我们介绍了WHERE命令的新用法 ——IN子查询再往前子查询还出现在FROM命令中用于合并数据源。但无论哪种场景每个子查询都以FROM开头。然而并非所有有用的查询都始于批量获取文档。有时你需要处理时间序列语义有时你只想快速生成几行内联测试数据而最优雅的场景是过滤条件本身来自一个动态查询而非静态写死的列表 —— 子查询能实时生成过滤值让你彻底告别“先查一遍复制粘贴”的繁琐流程。子查询到底做了什么你可以把子查询想象成拥有两个固定“座位”和三种不同的“引擎”。两个座位子查询可以出现在FROM命令内部作为数据源之一也可以出现在WHERE命令内部作为动态过滤条件。三种引擎决定子查询从何处读取数据 —— 索引FROM、时间序列数据流TS或内联字面值ROW。三种源命令速览源命令string 读取对象string 最佳用途string 前置要求FROM读取对象: 索引、数据流、别名、视图最佳用途: 存储文档查找、动态过滤列表前置要求: 无任何索引均可TS最佳用途: 指标聚合自动处理计数器重置和不均匀采集间隔读取对象: 时间序列数据流(TSDS)前置要求: 数据流必须为 time_series 模式(index.mode: time_series)ROW读取对象: 内联字面值最佳用途: 测试用例、种子值、合成占位符前置要求: 无无需索引ES|QL 子查询三种源命令对比版本提醒FROM、TS和ROW源命令在 Elasticsearch 9.5 中已正式发布GA而WHERE IN子查询本身在 9.5 中仍为技术预览版。子查询放哪里——FROM和WHERE两种落点子查询在外层查询中有且仅有两个合法的“座位”1. 在FROM命令内部此时子查询充当一个独立的结果源它产生的所有行都会被纳入外层查询的输入中。如果多个源包括普通索引、子查询等的字段不完全一致缺失的字段会自动填充为null。典型场景你需要将来自不同索引的数据、实时指标汇总行以及手工构造的测试行合并到同一张表中。2. 在WHERE命令内部此时子查询必须配合IN运算符使用它返回一列动态值作为外层查询的过滤条件。这种模式让你能够基于实时查询结果来过滤数据而不是硬编码一个静态列表。典型场景先通过子查询找出满足某些条件的 ID 集合然后在外层查询中只保留这些 ID 对应的记录。三扇门如何启动子查询 门 #1FROM—— 经典正门FROM是你最熟悉的老朋友。当子查询需要读取已存储的数据索引、数据流、别名或视图时就用它。它最出色的用法是“停止复制粘贴 ID”模式你再也不需要先执行一次查询手动复制输出值再粘贴到另一个查询的过滤条件里 —— 子查询直接充当动态过滤列表。示例查询所有“高价值账户”的员工信息。FROM employees | WHERE emp_no IN (FROM high_value_accounts | KEEP emp_no ) | KEEP emp_no, first_name, last_name解释内层子查询从high_value_accounts索引中取出所有emp_no外层WHERE直接使用这个动态列表完全无需手工干预。 门 #2ROW—— 轻量小门ROW是“零依赖”的轻量级选项 —— 它完全不需要任何索引可以直接通过字面值构造出任意行。这使得ROW非常适合提供小规模种子值如测试用 ID 列表构造允许/拒绝列表allow/deny list执行“假设what-if”分析在真实数据上“钉”一个合成标记行示例将访问日志中的 500 错误记录与一条人工合成的“占位”行合并。FROM (FROM access_logs | WHERE status 500 | KEEP cluster, status), (ROW cluster synthetic, status 0) | SORT status | KEEP cluster, status注意FROM命令后紧跟两个子查询用逗号分隔第一个从真实索引取数第二个用ROW生成一行二者共同构成外层查询的输入。 门 #3TS—— 时间序列专线TS命令专门针对时间序列数据流TSDS并启用专为时序数据优化的聚合函数。你可能会问既然FROM也能读数据流为什么还要TS答案是TS针对时序数据做了深度优化并能原生处理棘手场景进程重启导致的计数器重置counter reset指标采集间隔不均匀如有的秒级、有的分钟级自动识别时间戳和维度简化聚合语法使用TS作为子查询你可以实现“根据实时指标行为过滤应用日志”这种高级需求。例如只显示那些“峰值吞吐量超过 800”的集群的日志事件。FROM access_logs | WHERE cluster IN (TS k8s_metrics | STATS peak MAX(bytes_in) BY cluster | WHERE peak 800 | KEEP cluster ) | SORT cluster, path | KEEP cluster, status, path此例中子查询在k8s_metrics时间序列数据流上计算每个集群的bytes_in最大值峰值然后只保留峰值 800 的集群名。外层WHERE使用这个动态集群列表过滤访问日志 ——过滤条件实时响应指标变化绝非硬编码。三扇门齐开组合FROM、TS和ROW于一身由于子查询的“落点”FROM或WHERE和“引擎”FROM/TS/ROW是互相独立的你可以在同一个FROM子句中自由混合使用三种源命令。例如下面的查询将三路数据合并成一张统一表真实访问日志FROM access_logs实时指标汇总TS k8s_metrics按集群统计峰值一条合成行ROW cluster synthetic然后对外层结果按集群分组统计日志事件数和峰值吞吐量。FROM (FROM access_logs | KEEP cluster, status), (TS k8s_metrics | STATS peak MAX(bytes_in) BY cluster), (ROW cluster synthetic) | STATS log_events COUNT(status), peak MAX(peak) BY cluster | SORT cluster | KEEP cluster, log_events, peak这个查询展示了 ES|QL 子查询的强大组合能力 —— 你可以同时利用历史日志、实时指标和人工构造数据进行综合分析。使用子查询的约束条件在尽情使用子查询之前请记住以下几条“红线”IN子查询必须只返回一列如果子查询用于IN运算符它投影的字段必须且只能有一个。推荐使用KEEP命令显式保留唯一列避免歧义。TS命令只能用于时间序列数据流TSDSTSDS 要求索引设置index.mode: time_series。普通索引或数据流无法使用TS命令。子查询不支持嵌套子查询在当前版本中即子查询内部不能再包含子查询但这一限制在未来可能放宽。总结何时选用哪种源命令你的需求推荐源命令理由从索引/数据流中查询已有文档FROM标准数据读取最通用需要动态生成过滤值列表如 ID 集合FROM配合WHERE IN避免硬编码实时更新处理时间序列指标需聚合且关注计数器重置TS专为时序优化语义准确需要快速构建测试数据、占位行或种子值ROW零依赖灵活轻量同一查询中混合真实日志、指标汇总和合成行FROMTSROW组合三者可并存于FROM子句中ES|QL 的子查询机制提供了一种结构化的查询组合方式让一个查询的结果成为另一个查询的输入。通过合理选用FROM、ROW或TS你可以动态过滤无需重复查询逻辑混合真实数据与合成数据实时响应指标变化过滤应用日志这种能力大大减少了手工操作让查询更智能、更可维护。