在ES中,已經有Term Index,那還會走倒排索引嗎
你這個問題問得很到位 👍。我們分清楚 Term Index 和 倒排索引 在 Elasticsearch (ES) 里的關系:
1. 倒排索引(Inverted Index)
- 是 Lucene/ES 檢索的核心。
- 文檔 → 詞項 → Posting List(包含出現在哪些 doc、位置等)。
- 當你搜索一個 term 時,最終還是要從倒排索引里取出匹配文檔 ID。
2. Term Dictionary / Term Index
-
Term Dictionary 就是所有 term 的字典表,按字典序組織。
-
如果直接存,可能會很大(幾百萬甚至上億個 term)。
-
為了加速查找,Lucene 會給 Term Dictionary 建立 Term Index(類似于一個 FST 前綴樹)。
- 作用是:快速定位某個 term 在 Term Dictionary 中的位置。
- 比如你要查 “apple”,Term Index 能快速告訴你 “apple” 在字典大概哪一段,而不用順序掃描。
3. 查詢流程(簡化版)
- 用戶查詢
"apple"
。 - 先查 Term Index:快速定位 “apple” 在 Term Dictionary 的范圍。
- 從 Term Dictionary 找到準確的 term。
- 拿到這個 term 的倒排表(Posting List)。
- 根據 Posting List 找出對應的文檔 ID。
4. 回答你的問題
👉 有 Term Index,不代表不走倒排索引。
-
Term Index 只是用來 加速找到 term 的入口,本質上還是要回到 倒排索引(Posting List) 去取文檔。
-
所以兩者關系是:
- Term Index → 幫你定位 term
- 倒排索引 → 真正返回文檔
? 一句話總結:
ES 中,Term Index 是 倒排索引的入口加速結構,最終查文檔時一定會走倒排索引。
就是說Term Index不會完全匹配到,只會返回有共同前綴的第一個Term Dictionary?之后在利用倒排索引進行二分查找?
👌 你理解的方向對,但我幫你捋清楚細節:
1. Term Index 的本質
- Term Index 在 Lucene 里一般是 FST(Finite State Transducer)有窮狀態機。
- 它不是存所有 term,而是存 稀疏采樣的前綴 → Term Dictionary 的跳轉位置。
- 所以 Term Index 的作用是:快速定位到 Term Dictionary 中的某個位置,而不是直接給出完整匹配。
2. 查詢過程(舉例)
假設 Term Dictionary 里有這些 term:
apple
applet
application
banana
band
當你查 "application"
:
- Term Index 先根據前綴找到
"app"
開頭的一個錨點(比如指向"apple"
這一段)。 - 然后在 Term Dictionary 里做精確比較/二分查找,直到找到
"application"
。 - 一旦找到 term,就能取出它對應的 Posting List(倒排表)。
3. 回答你的問題
? 你說的“只會返回有共同前綴的第一個 Term Dictionary”是對的,但有個補充:
- Term Index 會定位到 最接近的一個錨點。
- 然后 Lucene 在 Term Dictionary 中繼續查找(可能是二分查找,也可能是順序掃描,取決于實現)。
- 找到確切的 term 后,才會去讀 倒排索引(Posting List)。
4. 類比理解
- Term Index:像書的目錄,告訴你某個字母開頭的詞在哪一頁。
- Term Dictionary:具體的詞表,按字典序排好。
- 倒排索引:每個詞對應的“在哪些文章里出現”。
所以 Term Index 永遠只是入口,最終要靠 Term Dictionary 精確匹配,拿到 Posting List 才能查文檔。
我想的是,按照你給的例子中appli這個前綴似乎是獨一無二的,總能找到,就算是applet,apple他們也是有區分度的。那么,唯一的可能就是,Term Index不會無限細分下去,比如到app,就不再往下分了,這樣只能搜索到apple
你抓住關鍵點了 👍,正是這樣。
Lucene 里的 Term Index(通常是 FST),不會把所有 term 的路徑都完整存進去,否則就和 Term Dictionary 本身沒區別了,浪費空間。
1. Term Index 不會無限細分
-
它是 稀疏索引,只存一部分前綴作為“跳點”。
-
比如詞表里有:
apple applet application
-
Term Index 可能只存到 “app”,指向這段 term。
-
并不會繼續區分到
"appl"
/"appli"
這種更細的層級。
2. 查找過程
- 你查
"application"
→ 先用 FST 找"app"
的錨點。 - 跳到 Term Dictionary 對應區間(可能是
"apple"
開頭的地方)。 - 然后在這片字典里做二分 / 順序查找,直到找到
"application"
。
3. 為什么這樣設計?
- 節省內存:如果所有前綴都存,就和存一整個 Trie 差不多,太大。
- 查找效率:稀疏索引 + Term Dictionary 二分查找,綜合性能更高。
- 平衡:只要能快速定位到“足夠小的一段”就夠了,沒必要直接精確定位到某個 term。
? 所以你理解對了:
- Term Index 不會無限細分,它只保證能定位到某個“最近的前綴區間”;
- 真正的精確匹配還是要靠 Term Dictionary(而不是 Term Index 本身)。
那一般會細分都幾個字符
好問題 👍,你已經完全抓到 Lucene Term Index 的實現細節了。
1. Term Index(FST)的細分程度
在 Lucene/ES 里,這個“細分到幾個字符”不是寫死的,而是通過 采樣策略決定的。
- Lucene 在構建索引時,不會給每個 term 都建一個索引節點,而是按間隔采樣。
- 這個采樣的粒度由參數控制,主要是:
termIndexInterval
- 含義:在 Term Dictionary 中,每隔多少個 term,往 FST 里加一個跳點。
- 默認值(Lucene 9.x):32。
- 也就是說:Term Index 大約每隔 32 個 term 才存一個 entry。
2. 影響
- 如果 term 很多,比如 320,000 個 term,Term Index 里大概只有 10,000 個跳點。
- 這樣就不會無限細分到
appl
、appli
這種級別,而是存一些“代表性前綴”。 - 查找時,先通過 FST 定位到最接近的跳點,然后再在 Term Dictionary 里做二分/順序查找。
3. 舉個例子
假設 Term Dictionary 里有這些詞(簡化):
apple
applet
application
apply
banana
band
...
-
如果 termIndexInterval = 2,那么 Term Index 可能只存:
"apple"
"application"
"banana"
-
你要查
"applet"
的時候,FST 會定位到"apple"
這一段,然后在 Term Dictionary 里再順序/二分找到"applet"
。
4. 回答你的問題
👉 一般不會細分到具體幾個字符,而是按 term 間隔采樣。
- 默認:32 個 term 采樣一次。
- 所以“細分程度”取決于字典里 term 的分布,而不是固定的字符長度。
? 一句話總結:
Term Index 不是按字符數來細分,而是 每隔一定數量的 term(默認 32)建立一個跳點。最終的精確匹配仍然要依賴 Term Dictionary。