sphinx是一個全文索引引擎,他被設計為可以非常簡單友善的與各種資料庫(mysql,pg…)進行互動。它提供了兩種讀取接口,a) sphinx自己實作的mysql協定的接口, sphinxql。b) 各種語言用戶端的接口,也就是native搜尋api. c) 也可以直接通過mysql server的一個存儲引擎插件來通路, sphinxse.
接下來我們會有一些列文章來分析sphinx的設計以及源碼實作。
本篇是第一篇,主要是簡要的介紹sphinx的源碼結構,設計以及索引檔案的構成。我們目前分析的代碼版本是sphinx-2.3.2-beta.tar.gz.
sphinx的源碼結構比較簡單,下面主要是一些比較重要的目錄:
api 這個目錄主要是包含了各種sphinx的native用戶端.
config 這個目錄包含了configure需要的一些檔案.
cmake 這個目錄包含了cmake建構需要的一些子產品(目前sphinx支援兩種構模組化式).
mysqlse 這個目錄包含了sphinxse
src 這個目錄就是最主要的源碼目錄。
src/http search服務的http接口
sphinx最終會生成4個可執行檔案,分别是:
indexer 主要是操作索引檔案,比如合并索引,重新建構索引等等
indextool dump索引的一些資訊,比如統計資訊等
searchd 搜尋服務
spelldump 拼寫檢查的工具
我們先來看sphinx源碼的cmakefiles(src/cmakelists.txt) :
通過上面的建構檔案我們可以看到4個可執行檔案對應4個源檔案(除了搜尋服務,searchdha.cpp是分布式搜尋,searchdhttp.cpp是搜尋服務的http接口實作).剩下的源代碼都會被編譯為一個libsphinx的庫.
是以下面簡單介紹下libsphinx的幾個檔案主要作用:
sphinx.cpp 核心的檔案,一些核心功能的實作都在這裡,比如讀寫索引檔案,比如搜尋的核心方法
sphinxexcerpt.cpp 生成excerpt
sphinxquery.cpp 處理query
sphinxstemen.cpp sphinxstemru.cpp sphinxstemcz.cpp sphinxstemar.cpp 各種語言的解析器
sphinxutils.cpp 一些工具函數,比如讀寫檔案,日志,動态庫等
sphinxstd.cpp 庫函數,實作了很多基本資料結構,比如 list/vector 等
sphinxexpr.cpp 處理搜尋的query
sphinxfilter.cpp 處理query的filter
sphinxsearch.cpp 核心的搜尋處理函數
sphinxrt.cpp rt index的實作
sphinxjson.cpp json的處理
以rt索引為例,sphinx會有配置來決定記憶體中的索引大小(rt_mem_limit),超過這個大小後,sphinx将會把記憶體索引重新整理到磁盤中。接下來我們就來看sphinx的索引的含義以及原始格式。
在sphinx中所有的索引最終都是被壓縮的,壓縮算法比較簡單,要麼是delta encoding, 要麼是vlb(variable length byte string):
delta encoding
主要用來儲存遞增的一個序列,每一個元素都儲存和前一個元素的內插補點。這種壓縮更高效,結果更小(比起vlb) 比如:
vlb
将一個固定大小(34/64)的整數值轉換為一個字元串,每個位元組分為高1位和低七位,最高位表示目前是否解析結束,低7位表示壓縮的值,原理很簡單,那麼就是對于大多數整數來說,不需要完整的8個位元組(或者4個位元組)來表示一個整數,因為沒有那麼大。而由于是每次移動7位,那麼對于最高位為1的情況也可以處理(因為每次移動完畢的最高位都是無意義的值)。
例子:
下面我們來看代碼,對應的函數是csphreader::unzipint以及csphwriter::zipint,其中前一個是解壓縮,後一個是壓縮。
先來看壓縮, dword可以簡單地認為是int64_t,代碼比較簡單,首先先計算可以用幾個位元組來儲存目前的數(ibytes),然後循環的儲存每個位元組:
然後是解壓縮,剛好和壓縮相反,也就是通過最高位來判斷是否結束解壓縮,然後通過左移以及累加來不斷地計算原有的值。
在介紹索引檔案之前,我們先介紹幾個概念:
document
每一條資料也就是一個document。
word
這裡word表示一個單詞,也就是sphinx分詞器處理完一條document之後,所得到的分詞。
hits
也就是一個word在一條document中的頻率。
attribute
一些擴充的字段,主要是為了做一些過濾(filter)。
然後來看索引檔案的簡單介紹.
然後我們來看索引的種類以及格式,在sphinx中,每一個索引都包含了下面幾個檔案:
sph檔案 儲存了索引的頭檔案,主要是一些索引元資訊
實作在writeheader/loadheader中。
spi檔案 儲存了wordlist,也就是索引檔案中最核心的一個檔案。
也就是通過spi檔案可以迅速的從一個keywords(word)映射到一堆document list。下面就是spi檔案的格式(dict=keywords):
檔案生成是在cidxhit中。
spa檔案 儲存了attribute
sps檔案 單獨儲存string類型的attribute值
spd檔案 儲存了document list
所有的document id都儲存在這個這個檔案中,也就是通過spi檔案得到document list的資訊後,可以迅速在spd檔案中定位document list。
spe檔案 儲存了skip list
spk檔案 儲存了 kill list
spm檔案 儲存了mva 值
spp檔案 儲存了hit list。
儲存了一個word在document中的所有出現的位置。也就是給定一個document 和一個keywords,這個檔案将會傳回所有的比對位置(在目前的document中).
其中spp/spi/spd/spa/spe檔案的生成都在rtindex_t::savediskdataimpl中實作。
在下一篇文章,我們會詳細的介紹每個索引檔案的生成。
http://sphinxsearch.com/docs/current.html