Elasticsearch 核心数据结构:FST 原理与应用场景全解析
-
- 前言
- [一、什么是 FST?](#一、什么是 FST?)
-
- [1.1 官方定义](#1.1 官方定义)
- [1.2 大白话解释](#1.2 大白话解释)
- [1.3 FST 最核心特点](#1.3 FST 最核心特点)
- [二、FST 核心原理(极简图解)](#二、FST 核心原理(极简图解))
-
- [2.1 原理一句话](#2.1 原理一句话)
- [2.2 示例](#2.2 示例)
- [2.3 FST 压缩原理图](#2.3 FST 压缩原理图)
- [三、FST 最关键优势(为什么 ES 非要用它?)](#三、FST 最关键优势(为什么 ES 非要用它?))
-
- [3.1 极低内存占用](#3.1 极低内存占用)
- [3.2 前缀查询极快](#3.2 前缀查询极快)
- [3.3 有序性](#3.3 有序性)
- [3.4 启动加载极快](#3.4 启动加载极快)
- [四、FST 在 Elasticsearch 中的应用场景(重点!面试必考!)](#四、FST 在 Elasticsearch 中的应用场景(重点!面试必考!))
- [场景 1:Term Index(词项索引)→ 最核心用途](#场景 1:Term Index(词项索引)→ 最核心用途)
- [场景 2:Prefix Query(前缀查询)](#场景 2:Prefix Query(前缀查询))
- [场景 3:Wildcard Query / Regexp(通配符/正则查询)](#场景 3:Wildcard Query / Regexp(通配符/正则查询))
- [场景 4:Suggest 搜索推荐 / 自动补全](#场景 4:Suggest 搜索推荐 / 自动补全)
- [场景 5:Term 查询(精准匹配)](#场景 5:Term 查询(精准匹配))
- [场景 6:Range Query(范围查询)](#场景 6:Range Query(范围查询))
- [场景 7:Keyword 字段的 Global Ordinals](#场景 7:Keyword 字段的 Global Ordinals)
- [五、FST 结构可视化理解(最简版)](#五、FST 结构可视化理解(最简版))
- [六、FST 总结(面试/工作必背 5 条)](#六、FST 总结(面试/工作必背 5 条))
- 七、一句话终极总结
-
- [**FST 是 Elasticsearch 的"检索大脑",](#**FST 是 Elasticsearch 的“检索大脑”,)
- [它让 ES 在数十亿单词下仍能保持极低内存、毫秒级查询。](#它让 ES 在数十亿单词下仍能保持极低内存、毫秒级查询。)
- [没有 FST,就没有 ES 的高性能。**](#没有 FST,就没有 ES 的高性能。**)
|-----------------------------|
| 🌺The Begin🌺点点关注,收藏不迷路🌺 |
前言
在 Elasticsearch 底层,FST(Finite State Transducer,有限状态转换器) 是支撑高性能、低内存占用 的核心数据结构。
ES 之所以能在数十亿 Term 下仍做到毫秒级检索,根本原因就是 FST。
很多人知道 ES 快,但不知道为什么快 ,核心答案就是:FST + 倒排索引压缩。
本文用通俗语言 + 原理图 + 应用场景 ,彻底讲清:
什么是 FST?它的原理是什么?在 ES 中用在哪里?为什么它这么强?
一、什么是 FST?
1.1 官方定义
FST:Finite State Transducer
有限状态转换器 → 一种极其节省内存、支持快速前缀查找、有序查询 的紧凑字典数据结构。
1.2 大白话解释
FST 就是一种超级省空间、超快查找 的"单词字典"。
它把大量字符串(Term)通过前缀共享、后缀共享 压缩成一张有向无环图。
1.3 FST 最核心特点
- 极高压缩比(共享前缀+后缀)
- 内存占用极低
- 支持前缀快速查询
- 有序检索
- O(1) ~ O(len(key)) 级别查询速度
二、FST 核心原理(极简图解)
2.1 原理一句话
把相同的前缀、后缀合并复用,用图结构存储字符串。
2.2 示例
存储 3 个词:
"Elasticsearch"
"Elastic"
"Electric"
FST 会:
- 共享前缀
El - 共享后缀
ic
最终只存储一份公共部分,空间大幅减少。
2.3 FST 压缩原理图
输入词:cat, bat, car
FST 会共享:
c → a → t
b → a → t
c → a → r
最终变成一张有向无环图 ,公共路径只存一次。
三、FST 最关键优势(为什么 ES 非要用它?)
3.1 极低内存占用
比 HashMap、跳表、B+Tree 内存占用 少 10~100 倍。
3.2 前缀查询极快
prefix query、wildcard、regexp 都是靠 FST 秒级完成。
3.3 有序性
Term 有序,便于范围查询。
3.4 启动加载极快
FST 结构可以直接从磁盘 mmap 映射到内存,不用加载全部数据。
四、FST 在 Elasticsearch 中的应用场景(重点!面试必考!)
FST 是 ES Term 检索的基石 ,下面这些功能 底层全是 FST 实现:
场景 1:Term Index(词项索引)→ 最核心用途
ES 倒排索引结构:
Term Index (FST)
↓
Term Dictionary
↓
Posting List
Term Index 完全由 FST 实现
作用:
- 快速定位 Term 在词典中的位置
- 不把全部词典加载进内存
- 前缀查询秒级响应
场景 2:Prefix Query(前缀查询)
json
{ "prefix": { "field": "app" } }
app → apple, application, applet...
FST 天生支持前缀路径遍历,速度极快。
场景 3:Wildcard Query / Regexp(通配符/正则查询)
field: "*search"
field: "el*tic"
通配符查询本质是在 FST 图上做路径匹配。
场景 4:Suggest 搜索推荐 / 自动补全
elastic → elasticsearch
ES 的 Completion Suggester 底层就是 FST。
场景 5:Term 查询(精准匹配)
{ "term": { "field": "java" } }
通过 FST 快速判断 Term 是否存在。
场景 6:Range Query(范围查询)
field: [a TO f]
FST 有序,范围遍历极快。
场景 7:Keyword 字段的 Global Ordinals
Keyword 聚合时,ES 会把字符串转为数字 ID,
底层也大量使用 FST 做字符串映射。
五、FST 结构可视化理解(最简版)
#mermaid-svg-YllqLbCG7xodnviJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YllqLbCG7xodnviJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YllqLbCG7xodnviJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YllqLbCG7xodnviJ .error-icon{fill:#552222;}#mermaid-svg-YllqLbCG7xodnviJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YllqLbCG7xodnviJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YllqLbCG7xodnviJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YllqLbCG7xodnviJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YllqLbCG7xodnviJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YllqLbCG7xodnviJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YllqLbCG7xodnviJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YllqLbCG7xodnviJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YllqLbCG7xodnviJ .marker.cross{stroke:#333333;}#mermaid-svg-YllqLbCG7xodnviJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YllqLbCG7xodnviJ p{margin:0;}#mermaid-svg-YllqLbCG7xodnviJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YllqLbCG7xodnviJ .cluster-label text{fill:#333;}#mermaid-svg-YllqLbCG7xodnviJ .cluster-label span{color:#333;}#mermaid-svg-YllqLbCG7xodnviJ .cluster-label span p{background-color:transparent;}#mermaid-svg-YllqLbCG7xodnviJ .label text,#mermaid-svg-YllqLbCG7xodnviJ span{fill:#333;color:#333;}#mermaid-svg-YllqLbCG7xodnviJ .node rect,#mermaid-svg-YllqLbCG7xodnviJ .node circle,#mermaid-svg-YllqLbCG7xodnviJ .node ellipse,#mermaid-svg-YllqLbCG7xodnviJ .node polygon,#mermaid-svg-YllqLbCG7xodnviJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YllqLbCG7xodnviJ .rough-node .label text,#mermaid-svg-YllqLbCG7xodnviJ .node .label text,#mermaid-svg-YllqLbCG7xodnviJ .image-shape .label,#mermaid-svg-YllqLbCG7xodnviJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-YllqLbCG7xodnviJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YllqLbCG7xodnviJ .rough-node .label,#mermaid-svg-YllqLbCG7xodnviJ .node .label,#mermaid-svg-YllqLbCG7xodnviJ .image-shape .label,#mermaid-svg-YllqLbCG7xodnviJ .icon-shape .label{text-align:center;}#mermaid-svg-YllqLbCG7xodnviJ .node.clickable{cursor:pointer;}#mermaid-svg-YllqLbCG7xodnviJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YllqLbCG7xodnviJ .arrowheadPath{fill:#333333;}#mermaid-svg-YllqLbCG7xodnviJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YllqLbCG7xodnviJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YllqLbCG7xodnviJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YllqLbCG7xodnviJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YllqLbCG7xodnviJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YllqLbCG7xodnviJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YllqLbCG7xodnviJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YllqLbCG7xodnviJ .cluster text{fill:#333;}#mermaid-svg-YllqLbCG7xodnviJ .cluster span{color:#333;}#mermaid-svg-YllqLbCG7xodnviJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YllqLbCG7xodnviJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YllqLbCG7xodnviJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-YllqLbCG7xodnviJ .icon-shape,#mermaid-svg-YllqLbCG7xodnviJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YllqLbCG7xodnviJ .icon-shape p,#mermaid-svg-YllqLbCG7xodnviJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YllqLbCG7xodnviJ .icon-shape .label rect,#mermaid-svg-YllqLbCG7xodnviJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YllqLbCG7xodnviJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YllqLbCG7xodnviJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YllqLbCG7xodnviJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} root
E
l
a
s
t
i
c
End: Elastic
i
c
e
r
h
End: Elasticsearch
共享前缀,不重复存储 → 极致压缩。
六、FST 总结(面试/工作必背 5 条)
- FST = 有限状态转换器 = 超级压缩字典
- 核心原理:共享前缀 + 共享后缀 → 有向无环图
- 最大优势:极低内存 + 极快前缀/模糊/范围查询
- ES 中最核心用途:Term Index(词项索引)
- 支撑 ES 90% 的查询类型:term、prefix、wildcard、suggest、range
七、一句话终极总结
**FST 是 Elasticsearch 的"检索大脑",
它让 ES 在数十亿单词下仍能保持极低内存、毫秒级查询。
没有 FST,就没有 ES 的高性能。**

|---------------------------|
| 🌺The End🌺点点关注,收藏不迷路🌺 |