Sphinx API類型以及SphinxSE實現原理分析

Sphinx comes with three different APIs, SphinxAPI, SphinxSE, and SphinxQL.
SphinxAPI is a native library available for Java, PHP, Python, Perl, C, and other languages.
SphinxSE, a pluggable storage engine for MySQL, enables huge result sets to be shipped directly to MySQL server for post-processing.
SphinxQL lets the application query Sphinx using standard MySQL client libary and query syntax.

一. sphinxSE工作原理

sphinxSE是一個mysql的擴展數據庫引擎,通過sphinxSE可以使用類似sql的語法,通過mysql對sphinx進行數據查詢。

它在系統中的角色是作爲一種查詢接口,可以當作是一種api。下圖描述了sphinxSE在整個查詢系統中的位置。

Sphinx的工作過程從下圖中加於說明。

1. 應用程序發起查詢請求,這個查詢請求是查詢mysql數據庫中sphinxSE引擎的schema;

2. Mysql接收到請求以後,經過sql分析優化等,會提交到sphinxSE引擎代碼進行處理;

3. sphinxSE引擎在進行索引查詢的時候,會將查詢截取出來,轉化成sphinx的查詢命令;

4. sphinxSE將查詢命令發送到sphinx查詢服務器進行查詢;

5. Sphinx查詢服務器查詢索引文件,得到結果

6. 將查詢結果返回。

二. sphinxSE的應用

爲一個sphinx應用建立sphinxSE的查詢接口,需要以下一些步驟。

1. 安裝sphinxSE

需要選擇一個mysql數據庫,安裝sphinxSE引擎。這個mysql數據庫,可以跟數據源不是同一臺機器,也可以是同一臺機器。但要注意,如果在查詢的時候想使用join操作,那麼安裝sphinxSE的mysql就需要跟數據源的mysql相同。

具體安裝方法可以參考手冊http://www.coreseek.cn/docs/coreseek_3.2-sphinx_0.9.9.html,這裏就不再重複。

2. 建立引擎類型爲sphinx的搜索表

要通過SphinxSE搜索,您需要建立特殊的ENGINE=SPHINX的“搜索表”。這個表格是一個空表,你不能通過insert命令往裏面插數據。對應每一個searchd進程,應該建立一個這樣的表格。

以店鋪內商品搜索爲例,我們來建立一個搜索表。假設我們只需要查詢商品的添加時間,其他的商品屬性我們暫不關心。

CREATE TABLE sphinxSE_0709

(

id           bigint(20)  UNSIGNED NOT NULL,

weight      INTEGER default 1,

query       VARCHAR(3072) NOT NULL,

Fadd_time    timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00′,

INDEX(query)

) ENGINE=SPHINX CONNECTION=”sphinx://localhost:9312″;

搜索表前三列(字段)的類型必須是INTEGER UNSINGED(或者 BIGINT),INTEGER(或者 BIGINT)和VARCHAR(或者 TEXT),這三列分別對應文檔ID,匹配權值和搜索查詢。這前三個列的映射關係是固定的,你不能忽略這三列中的任何一個,或者移動其位置,或者改變其類型。搜索查詢列必須被索引,其他列必須無索引。列的名字會被忽略,所以可以任意命名。

除此之外,其他列(字段)的類型必須是INTEGER、TIMESTAMP、BIGINT、VARCHAR或者FLOAT之一。它們必須與Sphinx結果集中提供的屬性按名稱綁定,即它們的名字必須與sphinx.conf中指定的屬性名一一對應。如果Sphinx搜索結果中沒有某個屬性名,該列的值就爲NULL.

可以使用字符串參數CONNECTION來指定用這個表搜索時的默認搜索主機、端口號和索引。如果CREATE TABLE中沒有使用連接(connection)串,那麼默認使用索引名“*”(搜索所有索引)和localhost:9312。連接串的語法如下:

CONNECTION=”sphinx://HOST:PORT/INDEXNAME”

默認的連接串也可以日後用alter命令改變。

3. 通過sphinxSE進行查詢

查詢的語句跟普通的sql語句類似。根據一個例子來說明吧。

select *  from   sphinxSE_0709  where query=’space;mode=any; sort=extended:  Fadd_time desc’;

如例子所示,查詢文本和搜索選項都應放在WHERE子句中對query列的限制中(即第三列),選項之間用分號分隔,選項名與選項值用等號隔開。可以指定任意數目的選項。sphinxSE的引擎獲取這些信息以後,會生成查詢命令,發送到sphinx查詢服務器進行查詢。收到返回的結果以後,再返回給用戶。

可以對SphinxSE搜索表和其他引擎的表之間使用JOIN操作,對多個表的數據進行聯合。如果sphinx查詢返回的數據根據查詢過濾條件過濾以後,得到的數據量不大,那麼這種聯合的效率是非常高,花費時間基本可以忽略。下面是我想根據查詢結果,查詢商品的名稱和店鋪名稱的語句。

select ftitle , fqqnick from t_commodity_0709 join  sphinxSE_0709 on (t_commodity_0709.Fcommodity_id = sphinxSE_0709.id) where query=’space;mode=any’;

三. 對sphinxSE的擴展

原來缺省的sphinxSE的搜索表,只返回了搜索的結果,但沒有對本次搜索的統計和性能進行返回,需要通過其他方式獲取。這種兩次獲取的方式,可能導致獲取的統計信息不是本次查詢的信息。而在我們的應用中,都需要這些統計信息,因此我們對sphinxSE引擎進行了擴充,
將原來的三列系統行(搜索表中的前三列)擴展爲六列系統行,增加了查詢總匹配數,本次查詢返回的匹配數和查詢耗時時間三個性能指標。

因此,在創建sphinxSE的搜索表格的時候,需要稍作修改,增加三個系統列。示例如下。

CREATE TABLE sphinxSE_0709

(

id           bigint(20)  UNSIGNED NOT NULL,

weight      INTEGER default 1,

query       VARCHAR(3072) NOT NULL,

Matchestotal   INTEGER default 0,

Matchesfound INTEGER default 0,

Querymsec    INTEGER default 0,

Fadd_time    timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00′,

INDEX(query)

) ENGINE=SPHINX CONNECTION=”sphinx://localhost:9312″;


四. sphinxSE接口的性能

測試環境:表大小265746條記錄,64位機器, 查詢中英文都有,每次測試的查詢詞語都不一樣,查詢時間單位ms

結論:SphinxSE會慢一點,但沒有明顯區別。主要損耗在mysql內部引擎處理會耗費幾個毫秒的時間
,這點時間可以忽略不計。如果業務在查詢的時候使用join操作,那麼在join操作可以省略在應用程序上產生的二次聚合,那麼整體上的速度會更快。但使用join操作的時候注意,如果原來系統使用了諸如mem cache等外部緩存, 數據庫的join操作會不使用外部cache,那麼會不會對mysql數據庫的io操作造成壓力,需要各個業務自己做評估。

特點:

SphinxSE可以跟數據源db和sphinx分開部署

方便切換sphinx服務器(一條sql命令即可切換)

原理上,所有通過api的查詢,都可以通過sphinxSE實現

u sphinxSE和sphinx查詢服務器的短連接,穩定性需要經過考驗。同時爲了避免每次連接都fork出一個進程來處理,最好採用版本比較新的sphinx,因爲可以採用進程池來解決這個問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章