这是《Elasticsearch 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Query DSL 适合搜索和复杂控制,但很多数据分析师更熟悉 SQL。Elasticsearch 提供 SQL 能力;8.11 之后又逐步推出 ES|QL,用更贴近管道的语言做查询和分析。
本章介绍两者的能力、语法、访问方式和选型边界。
12.1 Elasticsearch SQL
POST /_sql
{
"query": "SELECT brand, COUNT(*) AS cnt, AVG(price) AS avg_price FROM products GROUP BY brand ORDER BY cnt DESC LIMIT 10"
}
返回结构类似表格:
{
"columns": [
{ "name": "brand", "type": "keyword" },
{ "name": "cnt", "type": "long" },
{ "name": "avg_price", "type": "double" }
],
"rows": [
["NOVA", 120, 5999.5]
]
}
12.2 SQL 常用语法
条件过滤:
SELECT product_id, title, price
FROM products
WHERE status = 'ON_SALE'
AND price BETWEEN 3000 AND 9000
ORDER BY price DESC
LIMIT 20
全文搜索:
SELECT product_id, title, SCORE()
FROM products
WHERE MATCH(title, '笔记本')
ORDER BY SCORE() DESC
聚合:
SELECT status, COUNT(*) AS cnt, SUM(amount) AS total
FROM orders
WHERE created_at > NOW() - INTERVAL 30 DAY
GROUP BY status
ORDER BY total DESC
嵌套字段的支持程度与版本、Mapping 和字段结构有关,复杂嵌套建议仍使用 Query DSL。
12.3 SQL TRANSLATE
查看 SQL 翻译后的 DSL:
POST /_sql/translate
{
"query": "SELECT status, COUNT(*) FROM orders GROUP BY status"
}
用途:
- 学习 SQL 与 DSL 的对应关系;
- 检查 SQL 是否被下推为高效查询;
- 排查执行成本;
- 把 BI SQL 逐步迁移为 DSL。
12.4 SQL 分页与游标
POST /_sql
{
"query": "SELECT product_id, title FROM products ORDER BY product_id",
"filter": {
"range": {
"price": { "gte": 1000 }
}
},
"fetch_size": 1000
}
返回 cursor 后可以继续:
POST /_sql
{
"cursor": "..."
}
清理游标:
POST /_sql/close
{
"cursor": "..."
}
12.5 SQL 限制
Elasticsearch SQL 不是完整的关系型数据库 SQL。
| 限制 | 说明 |
|---|---|
| Join 支持有限 | 只支持有限类型和条件 |
| 事务不存在 | 只有查询和写入,不是 ACID |
| 复杂子查询受限 | 并非所有 SQL 都可翻译 |
| 深分页受限 | 使用 cursor 或过滤条件 |
| 字段类型敏感 | text 聚合需要 keyword 子字段 |
| 性能仍受 DSL 影响 | 慢查询同样会拖垮集群 |
它适合临时分析和简单报表,不适合替代数仓或 OLAP 引擎。
12.6 什么是 ES|QL
| ES | QL 是 Elasticsearch 8.11 引入、后续版本持续增强的管道式查询语言。它以一条事件流为中心,通过 | 管道逐层处理。 |
FROM orders
| WHERE created_at > NOW() - 30 DAYS
| EVAL profit = amount - cost
| STATS total_amount = SUM(amount), order_count = COUNT(*) BY status
| SORT total_amount DESC
| LIMIT 10
执行思路:
读取数据 -> 过滤 -> 派生字段 -> 聚合 -> 排序 -> 限制输出
12.7 ES|QL 常用命令
查询:
FROM logs-*
| LIMIT 10
过滤:
FROM logs-*
| WHERE log.level == "ERROR"
| LIMIT 100
选择字段:
FROM orders
| KEEP order_id, user_id, amount, status, created_at
| LIMIT 100
派生字段:
FROM orders
| EVAL amount_wan = amount / 10000.0
| KEEP order_id, amount, amount_wan
统计:
FROM orders
| STATS total = SUM(amount), cnt = COUNT(*), avg_amount = AVG(amount) BY status
时间处理:
FROM logs-*
| EVAL minute = DATE_TRUNC(1 MINUTE, @timestamp)
| STATS error_count = COUNT(*) BY minute
| SORT minute ASC
具体函数和能力与版本强相关,使用前应确认目标集群版本。
12.8 SQL 与 ES|QL 对比
| 维度 | SQL | ES | QL |
|---|---|---|---|
| 用户熟悉度 | 高 | 中等,需要学习管道语法 | |
| 查询形态 | 传统 SELECT | 管道式 | |
| 生态 | BI 工具支持较好 | 新生态逐步增强 | |
| 分析能力 | 常用 SQL 聚合 | 适合事件流和可观测性分析 | |
| 版本边界 | 较早版本可用 | 8.11+,能力随版本变化 | |
| 性能模型 | 翻译为 ES 查询 | 有专用执行引擎 | |
| 复杂查询 | DSL 仍更强 | 持续演进 |
12.9 选型建议
| 场景 | 建议 | |
|---|---|---|
| 应用搜索接口 | Query DSL | |
| 临时排查数据 | SQL 或 ES | QL |
| 运维日志分析 | ES | QL 或 Kibana 查询 |
| BI 简单报表 | SQL | |
| 复杂多维分析 | DSL 聚合或数仓 | |
| 精确财务报表 | 数仓/数据库,ES 只做加速 | |
| 高并发线上接口 | 预聚合成物化结果 |
12.10 权限与资源控制
| SQL 和 ES | QL 仍然是查询集群的入口,必须做权限控制: |
- 只开放必要索引;
- 限制查询时间范围;
- 禁止普通用户全量扫描;
- 限制返回行数和并发;
- 对 BI 用户使用独立角色;
- 开启慢查询日志;
- 敏感字段使用字段级安全策略。
12.11 本章小结
- SQL 适合临时分析和 BI 简单报表,底层仍会翻译为 ES 查询;
-
ES QL 是 8.11+ 的管道式查询语言,适合事件流和可观测性分析; -
SQL/ES QL 不能绕过 Mapping、分片、聚合和深分页的性能约束; - 复杂搜索仍以 Query DSL 为主;
- 精确财务和大规模扫描应使用数仓。
12.12 思考题
- SQL
MATCH和普通LIKE有什么区别? - 如何查看 SQL 翻译后的 Query DSL?
- SQL 游标适合什么场景?为什么不能无限翻页?
-
ES QL 的管道模型有什么优势? - 哪些报表不应该使用 Elasticsearch 实时聚合?