資料來(lái)源:
- 官方 Java Docs
- 源碼目錄:lucene-9.4.1-src/lucene-9.4.1/lucene/core/src/java/org/apache/lucene/codecs/lucene94/package-info.java
Package org.apache.lucene.codecs.lucene94
Lucene 9.3 file format.
Apache Lucene - Index File Formats
介紹
定義
倒排索引
field 類型
段
doc id
索引結(jié)構(gòu)概述
File Naming
Summary of File Extensions
Lock File
History
Limitations
介紹
此文檔定義了當(dāng)前 Lucene 版本的索引文件格式铆隘。If you are using a different version of Lucene, please consult the copy of docs/ that was distributed with the version you are using.
本文試圖提供 Apache Lucene 文件格式的高級(jí)定義。
定義
Lucene 的基本概念是索引(index)守问、文檔(document)毡泻、字段(field)和詞(term):
- 一個(gè) index 是由多個(gè) doc 組成的
- 一個(gè) doc 是由多個(gè) field 組成的
- 一個(gè) field 是由多個(gè) term 組成的
- 一個(gè) term 是由多個(gè) byte 組成的
文檔 Document
doc 是 json 格式的文本,一個(gè)簡(jiǎn)單的例子:
{"k0":"123", "k1":"123", "k2":"hello world"}
域 Field
field 是一個(gè) json 的 element辆童,由 field name 和 field value 組成丁频,field value 通常叫做 filed text裹粤。
上面 doc 例子中共有 3 個(gè) field:
- field0:
"k0":"123"
,field name 為 k0恬吕,field text 為 123 - field1:
"k1":"123"
签则,field name 為 k1,field text 為 123 - field2:
"k2":"hello world"
铐料,field name 為 k2渐裂,field text 為 hello world
詞 Term
源代碼:lucene-9.4.1-src/lucene-9.4.1/lucene/core/src/java/org/apache/lucene/index/Term.java
MySQL 的基本檢索單位是 column,由 column name 和 column value 組成钠惩;類似的柒凉,在 Lucene 基本檢索單位是 term,term 由 term name 和 term value 組成:
- term name 等同于 field name篓跛,數(shù)據(jù)格式為
text
膝捞。 - term value 是 field text 的子集,我們通過(guò)分詞的方式愧沟,例如 split() 方法绑警,將 field text 劃分為多個(gè) term value,數(shù)據(jù)格式為
string
央渣。
分詞 tokenize 在 Lucene 中是一個(gè)很基本操作计盒,在創(chuàng)建倒排索引時(shí)會(huì)用到,在進(jìn)行檢索時(shí)也會(huì)用到芽丹。不同的語(yǔ)言北启、不同的分詞方式,會(huì)導(dǎo)致很多分詞器 tokenizer 的產(chǎn)生,這些分詞器通常以插件的形式(jar 包)存在
假如使用空格作為分隔符來(lái)進(jìn)行分詞咕村,那么上面的 doc 例子中共有 4 個(gè) term:
- term0:
"k0":"123"
场钉,term name 為 k0,term value 為 123 - term1:
"k1":123
懈涛,term name 為 k1逛万,term value 為 123 - term2:
"k2":"hello"
,term name 為 k2批钠,term value 為 hello - term3:
"k2":"world"
宇植,term name 為 k2,term value 為 world
term0 和 term1 雖然 value 的內(nèi)容是一樣的埋心,但 指郁,term name 不一樣,所以 term0 和 term1 會(huì)被當(dāng)做 2 個(gè)不同的 term拷呆。
倒排索引
Lucene 的 index 存儲(chǔ)了 term 和 term 的統(tǒng)計(jì)信息闲坎,使得基于 term 的搜索更加高效。
類似于 MySQL 的 column 索引茬斧,Lucene 的 term 也有索引腰懂,它們都是針對(duì) value 建立索引,但是不同的是 column 索引是正排索引项秉, 而 term 索引是一個(gè)倒排索引(inverted index)悯恍。在正常思維中,我們通常先找到 doc伙狐,再找到 doc 里面的 term涮毫,這就是正排索引建立的基本邏輯;而倒排索引的基本邏輯是贷屎,通過(guò)指定的 term罢防,反過(guò)來(lái)找包含這個(gè) term 的 doc 。
Types of Fields
一個(gè) field 既可以被存儲(chǔ)唉侄,也可以被索引:
- 被存儲(chǔ)的意思就是:把 field 的原數(shù)據(jù)以非倒排的方式存儲(chǔ)在 index 中
- 被索引的意思就是:開啟了索引特性的 field咒吐,則把 field 信息加入到倒排索引中
也就是說(shuō),一個(gè) Lucene index属划,不但存儲(chǔ)了 field 原數(shù)據(jù)恬叹,也存儲(chǔ)了 field 的索引,這 2 種數(shù)據(jù)存儲(chǔ)在不同的文件中同眯,文件格式也不一樣绽昼。
建立倒排索引時(shí),按照用戶定義的分詞方式须蜗,field text 既可能被分割成多個(gè) term硅确,也可能被當(dāng)成 1 個(gè) term目溉,例如進(jìn)行自然語(yǔ)言識(shí)別時(shí),后者效果顯然比前者的要好菱农。
段
Lucene index 由多個(gè)子索引組成缭付,子索引又稱作段 segment 。每一個(gè) segment 都是一個(gè)完全獨(dú)立的 index循未,提供獨(dú)立的讀寫功能陷猫。所以 index 與 segment 之間有以下表現(xiàn):
- 新加的 doc 有可能寫入現(xiàn)有的 segment,也有可能寫入一個(gè)新創(chuàng)建的 segment
- 多個(gè) segment 之間會(huì)發(fā)生合并 merge
- 1 個(gè)檢索可能會(huì)涉及到多個(gè) segment
文檔編號(hào)
在 Lucene 內(nèi)部的妖,使用文檔編號(hào) document number 來(lái)表示一個(gè)文檔绣檬, document number 也叫 document id。index 的第一個(gè) doc 編號(hào)為 0羔味,依次遞增。
請(qǐng)注意钠右,文檔編號(hào)可能會(huì)變化赋元,因此在 Lucene 之外存儲(chǔ)這些數(shù)字時(shí)要小心。一般來(lái)說(shuō)飒房,一下幾種情況會(huì)導(dǎo)致文檔編號(hào)發(fā)生變化:
-
存儲(chǔ)在每個(gè) segment 中的文檔編號(hào)僅在該 segment 內(nèi)是唯一的搁凸,必須進(jìn)行轉(zhuǎn)換才能在更大的上下文中使用。標(biāo)準(zhǔn)的技術(shù)是根據(jù) segment 中使用的數(shù)字范圍為每個(gè) segment 分配一個(gè)值范圍狠毯。要將文檔編號(hào)從 segment 內(nèi)部值轉(zhuǎn)換為外部值护糖,需要添加 segment 的基本文檔編號(hào)。要將外部值轉(zhuǎn)換回特定 segment 的值嚼松,需要根據(jù)外部值所在的范圍識(shí)別出該 segment嫡良,并減去該 segment 的基本文檔編號(hào)。例如献酗,要組合兩個(gè)只有 5 個(gè)文檔的 segment 時(shí)寝受,第一個(gè) segment 的基本文檔編號(hào) 0,第二個(gè) segment 的基本文檔編號(hào)為 5罕偎,那么可以推斷出第二部分中的 doc3 的外部值為 8 = 5+3:
文檔 基本文檔編號(hào) 原段內(nèi)文檔編號(hào) 合并后的段外文檔編號(hào) segment0 0 0-4 doc3 的為 3 = 0+3 segment1 5 0-4 doc3 的為 8 = 5+3 刪除文檔時(shí)很澄,相關(guān)的文檔編號(hào)不再指向任何文檔,因此會(huì)產(chǎn)生空白編號(hào)颜及。當(dāng)合并 segment 時(shí)甩苛,會(huì)生成一個(gè)新的 segment,已刪除的文檔會(huì)被丟棄俏站,文檔編號(hào)也會(huì)重新生產(chǎn)讯蒲。因此,新合并的段沒(méi)有空白編號(hào)肄扎。
索引結(jié)構(gòu)概述
每個(gè) segment index 包含以下信息:
- Segment info:segment 元數(shù)據(jù)爱葵,例如 segment 的 doc 數(shù)量施戴、segment 使用的文件、segment 存儲(chǔ)的方式等
- Field names:field name 元數(shù)據(jù)
- Stored Field values:field 原始數(shù)據(jù)萌丈,在 Lucene 中在存儲(chǔ) doc 時(shí)不是直接整個(gè) doc 進(jìn)行存儲(chǔ)的赞哗,而是將其拆成多個(gè) attribute-value 對(duì),再進(jìn)行列式存儲(chǔ)辆雾,attribute 是 field name肪笋,value 是 field text。 當(dāng)檢索命中時(shí)度迂,返回 field 原始數(shù)據(jù)藤乙,key 是文檔編碼。
- Term dictionary:term 詞典惭墓,當(dāng) field 開啟索引功能時(shí)坛梁,把 term 記錄到這個(gè)詞典中,該詞典還記錄了包含 term 的文檔數(shù)量腊凶、指向 term 詞頻和位置數(shù)據(jù)的指針划咐。
- Term Frequency data:term 詞頻數(shù)據(jù),在 term 詞典中钧萍,如果沒(méi)有設(shè)置忽略 term 詞頻褐缠,那么每個(gè) term 都有一個(gè) term 出現(xiàn)次數(shù)的匯總,稱之為詞頻风瘦。
- Term Proximity data:term 位置數(shù)據(jù)队魏,在 term 詞典中,如果沒(méi)有設(shè)置忽略 term 位置數(shù)據(jù)万搔,那么每個(gè) term 都會(huì)記錄它的每一個(gè)原文檔編碼 胡桨,稱之為位置數(shù)據(jù)。
- Normalization factors:歸一化因子瞬雹,在 doc 的每個(gè) field 中登失,都存儲(chǔ)著一個(gè)值,用來(lái)乘以命中分?jǐn)?shù)挖炬,實(shí)現(xiàn)歸一化的效果揽浙,使得搜索得分不因 doc 長(zhǎng)度不同而出現(xiàn)較大偏差。For each field in each document, a value is stored that is multiplied into the score for hits on that field.
- Term Vectors:term 向量由 term text 和 term 詞頻組成意敛,doc 的每個(gè) field 可以選擇是否存儲(chǔ) term 向量(有時(shí)也叫 doc 向量)馅巷,請(qǐng)參考 Field 結(jié)構(gòu)
- Per-document values. 與存儲(chǔ)值一樣,這些值也以文檔編號(hào)為鍵草姻,但通常是為了快速訪問(wèn)而加載到主內(nèi)存中钓猬。存儲(chǔ)值通常用于搜索的摘要結(jié)果,而每個(gè)文檔的值對(duì)于諸如評(píng)分因子之類的東西很有用撩独。Like stored values, these are also keyed by document number, but are generally intended to be loaded into main memory for fast access. Whereas stored values are generally intended for summary results from searches, per-document values are useful for things like scoring factors.
- Live documents. An optional file indicating which documents are live.
- Point values. Optional pair of files, recording dimensionally indexed fields, to enable fast numeric range filtering and large numeric values like BigInteger and BigDecimal (1D) and geographic shape intersection (2D, 3D).
- Vector values. The vector format stores numeric vectors in a format optimized for random access and computation, supporting high-dimensional nearest-neighbor search.