一、前言
在日常 Elasticsearch(简称 ES)开发中,绝大多数开发者习惯使用原生 DSL 语句实现数据查询、检索与聚合统计。但 ES DSL 存在语法繁琐、学习成本高、可读性差、业务对接效率低等问题,对于后端开发、数据分析人员并不友好。
为此,Elasticsearch 从 7.0 版本开始全面原生支持 ES SQL,兼容标准 SQL 语法,支持查询、筛选、排序、分页、聚合、全文检索等核心能力。开发者无需精通复杂的 DSL,即可快速操作 ES 索引数据,极大降低了 ES 的使用门槛,同时完美适配数据报表、日志分析、业务数据查询等场景。
本文基于 ES 7.x/8.x 稳定版本,结合真实业务索引 page_study_index,从零讲解 ES SQL 核心语法、关键参数、实战场景及避坑方案,所有案例均可直接复制上线使用。
二、环境与索引说明
2.1 适配版本
本文所有语法、参数、请求方式均兼容:Elasticsearch 7.x、8.x 全系列版本,无需额外安装插件,ES 原生开箱即用。
2.2 业务测试索引
本文实战基于业务索引 page_study_index(页面学习数据索引),核心字段结构如下,贴合真实业务场景:
| 字段名 | 字段类型 | 字段说明 |
|---|---|---|
| id | long | 数据唯一主键 |
| number | integer | 排序权重字段 |
| title | text/keyword | 页面标题 |
| content | text | 页面内容(支持全文检索) |
| status | integer | 状态:0-禁用,1-正常 |
| create_time | date | 数据创建时间 |
2.3 执行方式
ES SQL 统一通过 /_sql 接口执行,日常开发最常用 Kibana Dev Tools 调试,生产环境可通过代码 HTTP 请求调用。
POST /_sql?format=json
{
"query": "标准SQL语句",
"fetch_size": 自定义参数
}
三、核心参数深度解析(重点)
在 ES SQL 接口中,fetch_size 是最容易被误用、忽略的核心参数,也是本文重点讲解的配置项。
3.1 fetch_size 参数详解
-
参数作用 :控制 ES 服务端 单次流式返回的数据行数,用于批量查询、全量拉取场景,防止一次性加载海量数据导致内存溢出(OOM)、集群压力过大。
-
默认值 :1000(未手动配置时,ES 默认单次返回 1000 条数据)
-
自定义场景:小数据分页可手动调小,大数据批量同步可适当调大(不建议超过 10000)
你常用的排序查询案例:单次仅返回 2 条排序后数据
GET _sql
{
"query": "SELECT * FROM \"page_study_index\" ORDER BY number DESC ",
"fetch_size":2
}
3.2 关键参数区别(避坑核心)
很多开发者会混淆fetch_size 和 LIMIT,二者本质完全不同:
- fetch_size :服务端分批拉取参数,控制单次网络传输的数据量,属于 底层流式配置
3.3 其他常用公共参数
-
format:指定返回数据格式,支持 json、txt、csv、tsv,开发调试优先用 json
-
timeout:查询超时时间,默认无超时,大数据查询可自定义配置
-
columnar 是否返回列形式的数据
-
filter,通过filter字段,结合dsl+sql
sql
GET _sql
{
"query": """
SELECT * FROM page_study_index ORDER BY number DESC LIMIT 10
""",
"filter":{
"term": {
"number": "11"
}
}
}
- translate 使用这个参数可以直接将我们写的sql语句转化成dsl语法。
四、ES SQL 基础语法实战
ES SQL 高度兼容标准 SQL,日常查询、筛选、排序、分页语法与 MySQL 基本一致,学习成本极低。
4.1 基础字段查询
支持查询全字段、指定字段,适配列表展示、数据导出场景
-- 查询全部字段,默认1000条
SELECT * FROM page_study_index;
-- 查询指定业务字段(推荐,减少返回冗余数据)
SELECT id, title, number, create_time, status FROM page_study_index;
4.2 条件筛选查询(WHERE)
支持等值查询、模糊查询、时间范围查询、多条件组合,完全适配业务筛选需求
-- 1、状态为正常的有效数据
SELECT * FROM page_study_index WHERE status = 1;
-- 2、标题模糊匹配
SELECT * FROM page_study_index WHERE title LIKE '%ES实战%';
-- 3、时间范围筛选
SELECT * FROM page_study_index
WHERE create_time >= '2026-01-01' AND create_time <= '2026-05-14';
-- 4、多条件组合查询
SELECT title, number FROM page_study_index
WHERE status = 1 AND number > 10;
4.3 排序查询(ORDER BY)
支持单字段、多字段升降序排序,适配业务列表排序场景
-- 单字段排序:按权重number倒序(核心实战场景)
SELECT * FROM page_study_index ORDER BY number DESC;
-- 多字段排序:权重倒序,创建时间倒序
SELECT * FROM page_study_index ORDER BY number DESC, create_time DESC;
五、ES SQL 高阶实战能力
5.1 全文检索(ES 核心特色)
区别于普通数据库 SQL,ES SQL 原生支持全文检索,通过 MATCH 函数替代复杂的 DSL 全文查询,适配文章内容搜索、日志检索场景
sql
-- 单字段全文检索:内容包含Elasticsearch
SELECT id, title, content FROM page_study_index WHERE MATCH(content, 'Elasticsearch');
-- 多字段全文检索:标题或内容包含SQL实战
SELECT id, title FROM page_study_index WHERE MATCH((title, content), 'SQL实战');
5.2 聚合统计查询(GROUP BY)
支持各类聚合函数,可快速实现数据统计、报表分析,替代复杂的 ES 聚合 DSL
sql
-- 1、按状态分组统计数据总量
SELECT status, COUNT(*) AS total_count FROM page_study_index GROUP BY status;
-- 2、按日期分组,统计每日新增数据量
SELECT DATE(create_time) AS create_day, COUNT(*) AS add_count
FROM page_study_index
GROUP BY create_day
ORDER BY create_day DESC;
-- 3、综合聚合:最大值、最小值、平均值
SELECT MAX(number) AS max_sort, MIN(number) AS min_sort, COUNT(*) AS total
FROM page_study_index WHERE status = 1;
六、完整综合实战案例(生产可用)
6.1 业务场景
实现有效页面数据分页列表:查询状态正常的业务数据,按权重倒序排序,每页展示 2 条,服务端分批拉取数据,适配前端列表展示。
6.2 完整请求语句
sql
POST /_sql?format=json
{
"query": """
SELECT id, title, number, create_time
FROM page_study_index
WHERE status = 1
ORDER BY number DESC
LIMIT 2
""",
"fetch_size": 2
}
6.3 响应结果示例
sql
{
"columns": [
{"name": "id", "type": "long"},
{"name": "title", "type": "text"},
{"name": "number", "type": "integer"},
{"name": "create_time", "type": "datetime"}
],
"rows": [
[101, "Elasticsearch SQL实战教程", 99, "2026-05-14T10:00:00Z"],
[100, "ES分页与fetch_size详解", 98, "2026-05-14T09:30:00Z"]
]
}
七、Cursor 游标分页
前文提到 fetch_size 是服务端分批拉取参数,很多开发者误以为配置 fetch_size 即可批量获取全量数据,这是典型误区 。单纯配置 fetch_size 仅能获取第一批数据 ,想要获取第二批、第三批剩余数据,必须依赖 ES SQL 提供的 cursor 游标机制。
该机制是 ES SQL 适配大数据量流式查询、全量数据导出、无上限分页的核心方案。
8.1 游标分页核心原理
-
fetch_size:定义每一批次返回的数据条数(单次拉取量)
-
cursor:ES 服务端返回的唯一游标标识,用于标记当前查询位置,下次请求携带该游标,即可继续读取下一批数据
-
生命周期:游标默认存在短暂有效期,查询结束后自动销毁,无内存压力
8.2 完整实战流程(可直接上线)
第一步:首次查询,获取第一批数据 + 游标
首次请求无需携带游标,仅配置 query 和 fetch_size,ES 会返回第一批数据和 cursor 值
sql
POST /_sql?format=json
{
"query": "SELECT id, title, number FROM page_study_index ORDER BY number DESC",
"fetch_size": 2
}
首次响应结果(含游标)
sql
{
"columns": [
{"name": "id", "type": "long"},
{"name": "title", "type": "text"},
{"name": "number", "type": "integer"}
],
"rows": [
[101, "Elasticsearch SQL实战教程", 99],
[100, "ES分页与fetch_size详解", 98]
],
"cursor": "dxlka92mdk1290x...(唯一游标字符串)"
}
第二步:携带游标,循环拉取剩余数据
后续请求不再携带 query,仅携带上一步返回的 cursor 和 fetch_size,持续读取下一批数据
sql
GET _sql
{
"cursor": "+6zrA0RGTACEUMFOg0AU3IemBy5+iQlabcLBw27Cihhpuum+yF4aW0CqCzQLjWE/wL/oH3j0/xRsOTuHl3mTl3mZAUWgIA6QAT89Lv4Y6SVw822m01VTm3ZS7ct1ZshklW9N0wIQONd19Xq8hW84I47Tk2EMwufhSIjr99vgCzB6OPAFlzNr6Eew2NzzSqFv0xDfM/R361LojCkdd1630TpBzney87xnK5o5F1OUOKVM7ZVOLL6xeqEjIa+iWSqL22UYmadACTqCpQmv4pukbGMZFlwuH66xYvMXxMfUaosYUCr++UXpHXFPzQDkpwxj+L4H8gsAAP//AwA="
}
终止条件 :当响应结果中 无 cursor 字段 时,代表所有数据读取完毕,循环结束。
8.3 游标分页核心优势
-
内存安全:配合 fetch_size 分批拉取,不会一次性加载全量数据,彻底避免 OOM
-
适配场景广:全量数据导出、日志批量同步、大数据量报表统计、无限滚动分页