天天看點

MySQL · 引擎介紹 · Sphinx源碼剖析(三)

在本節中我會介紹Sphinx在建構索引之前做的一些事情,主要是從mysql拉取資料儲存,然後分詞排序儲存到記憶體等等一系列的操作。下面是幾個相關指令

其中sql_query是sphinx每次從mysql拉取資料的sql,而sql_query_range則是取得需要從mysql拉取的資料條目,而sql_rang_step則是表示每次從mysql拉取多少資料。sql_rang_range執行分兩種情況,第一種是第一次拉取資料的時候,第二種是當目前的range資料讀取完畢之後。

首先來看CSphSource_SQL::NextDocument函數,這個函數的主要作用是從mysql讀取資料然後切分儲存,首先我們來看讀取資料這一部分,這裡步驟很簡單,就是執行對應的sql,然後判斷目前range的資料是否讀取完畢,如果讀取完畢則繼續執行sql_query_rang(RunQueryStep)。這裡要注意的是,sphinx讀取資料是一條一條的讀取然後執行的.

上面的代碼我們可以看到一個很關鍵的字段m_uDocID,這個字段表示目前doc的id(是以資料庫的表設計必須有這個id字段).

讀取完畢資料之後,開始處理讀取的資料,這裡會按照字段來切分,主要是将對應的資料庫字段儲存到索引fielld

緊接着就是處理attribute,後續我們會詳細介紹attribute,現在我們隻需要知道它是一個類似二級索引的東西(不進入全文索引).

然後我們來看Sphinx如何處理得到的資料,核心代碼在 RtIndex_t::AddDocument中,這個函數主要是用來分詞(IterateHits中)然後儲存資料到對應的資料結構,而核心的資料結構是RtAccum_t,也就是最終sphinx在寫索引到檔案之前,會将資料儲存到這個資料結構,這裡要注意一般來說sphinx會儲存很多資料,然後最後一次性送出給索引引擎來處理.而索引引擎中處理的就是這個資料結構.是以最終會調用RtAccum_t::AddDocument.

這裡需要注意兩個地方,第一個是m_dAccum這個域,這個域是一個vector,而這個vector裡面儲存了CSphWordHit這個結構,我們來看這個結構的定義

可以看到其實這個結構也就是儲存了對應分詞的資訊.

然後我們來看核心代碼,這裡主要是便利剛才從mysql得到的資料,去重然後儲存資料.

做完上面這些事情之後,就需要送出資料給索引處理引擎了,這裡核心的代碼都是在RtIndex_t::Commit中.

這個函數主要做兩個事情,第一個提取出前面我們構造好的RtAccum_t,然後對于所有的doc進行排序,建立segment,也就是對應的索引塊(ram chunk),最後調用CommitReplayable來送出ram chunk到磁盤.

其實可以這麼了解,儲存在記憶體中的索引也就是segment,然後當記憶體的大小到達限制後就會重新整理記憶體中的索引到磁盤.

然後我們來看RtAccum_t::CreateSegment函數,這個函數用來将分詞好的資料儲存到ram chunk,這裡需要注意兩個資料結構分别是RtDoc_t和RtWord_t,這兩個資料結構分别表示doc資訊和分詞資訊.

結構很簡單,後面的注釋都很詳細

然後來看代碼,首先是初始化對應的寫結構,可以看到都是會寫到我們建立好的segment中.

然後就是寫資料了,這裡主要是做一個聚合,也就是将相同的keyword對應的屬性聚合起來.

這次就分析到這裡,下次我們将會分析最核心的部分就是Sphinx如何重新整理資料到磁盤.

繼續閱讀