sphinx 增量索引 及時更新、sphinx indexer索引合成時去舊和過濾辦法(轉)

一.sphinx增量索引的設置    數據庫中的已有數據很大,又不斷有新數據加入到數據庫中,也但願可以檢索到。所有從新創建索引很消耗資源,由於咱們須要更新的數據相比較而言不多。例如。原來的數據有幾百萬條,而新增的只是幾千條。這樣就可使用「主索引+增量索引」的模式來實現近乎實時更新的功能。  php

    這個模式實現的基本原理是設置兩個數據源和兩個索引,爲那些基本不更新的數據創建主索引,而對於那些新 增的數據創建增量索引。主索引的更新頻率能夠設置的長一些(例如設置在天天的午夜進行),而增量索引的更新頻率,咱們能夠將時間設置的很短(幾分鐘左 右),這樣在用戶搜索的時候,咱們能夠同時查詢這兩個索引的數據。mysql

    使用「主索引+增量索引」方法有個簡單的實現,在數據庫中增長一個計數表,記錄每次從新構建主索引時,被索引表的最後一個數據id,這樣在增量索引時只須要索引這個id之後的數據便可,每次從新構建主索引時都更新這個表。linux

    測試條件:以默認的sphinx.conf配置爲例,數據庫表的數據也以 example.sql爲例。web

1.先在mysql中插入一個計數表和兩個索引表sql

CREATE TABLE sph_counter (     counter_id   INTEGER PRIMARY KEY NOT NULL ,     max_doc_id   INTEGER NOT NULL ) ;

2.修改sphinx.conf數據庫

source main_src{       type                = mysql       sql_host            = localhost       sql_user            = yourusername       sql_pass            = yourpassword       sql_db              = test   //你所用的數據庫       sql_port            = 3306 //所用端口,默認是3306          服務器

sql_query_pre       = SET NAMES utf8        app

sql_query_pre       = SET SESSION query_cache_type=OFF       #下面的語句是更新sph_counter表中的 max_doc_id。       分佈式

sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents      工具

sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title,\                 content FROM documents \              WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )           }

// 注意:delta_src 中的sql_query_pre的個數需和main_src 對應,不然可能搜索不出相應結果

source delta_src: main_src{         sql_ranged_throttle = 100         sql_query_pre       = SET NAMES utf8         sql_query_pre       = SET SESSION query_cache_type=OFF           sql_query           = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content FROM documents \           WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )} index main //主索引{       source           = main_src       path             = /path/to/main     # example:   /usr/local/sphinx/var/data/main      .............       charset_type     = utf-8    #這個是支持中文必需要設置的       chinese_dictionary =/usr/local/sphinx/etc/xdict       #..........其它能夠默認}

//delta可所有複製主索引,而後更改source 和path以下  

index delta: main //增量索引{         source = delta_src         path     = /path/to/delta    # example:  /usr/local/sphinx/var/data/delta…    }

其它的配置可都用默認的,若是你設置了分佈式檢索的索引,那麼更改下對應的索引名稱便可。
3.從新創建索引: 若是sphinx正在運行,那麼首先中止運行,而後,根據sphinx.conf配置文件來創建全部索引,最後,啓動服務  

/usr/local/sphinx/bin/searchd --stop/usr/local/sphinx/bin/indexer -c  /usr/local/sphinx/etc/sphinx.conf --all/usr/local/sphinx/bin/searchd -c  /usr/local/sphinx/etc/sphinx.conf

P.S /usr/local/sphinx/bin/indexer -c  /usr/local/sphinx/etc/sphinx.conf --all--rotate   這樣就不須要停searchd,索引後也再也不須要重啓searchd了。

若是想測試增量索引是否成功,往數據庫表中插入數據,查找是否可以檢索到,這個時候檢索應該爲空,而後,單獨重建 delta索引 /usr/local/sphinx/bin/indexer -c /usr/lcoal/sphinx/etc/sphinx.conf delta 查看是否將新的記錄進行了索引。若是成功,此時,再用 /usr/local/sphing/bin/search 工具來檢索,可以看到,在main索引中檢索到的結果爲0,而在delta中檢索到結果。固然,前提條件是,檢索的詞,只在後來插入的數據中存在。
接下來的問題是如何讓增量索引與主索引合併
4.索引合併 合併兩個已有索引 有時比 從新索引全部數據有效,雖然,索引合併時,待合併的兩個索引都會被讀入內存一次,合併後的內容需寫入磁盤一次,即,合併100GB和1GB的兩個因此,將致使202GB的IO操做 命令原型:  indexer --merge DSTINDEX  SRCINDEX [--rotate]   將SRCINDEX合併到 DSTINDEX ,因此只有DSTINDEX會改變,若是兩個索引都正在提供服務,那麼 -- rotate 參數是必須的。例如:將delta合併到main中。 indexer --merge main delta    
5.索引自動更新 須要使用到腳本。 創建兩個腳本:build_main_index.sh 和 build_delta_index.sh.
build_main_index.sh: #!/bin/sh # 中止正在運行的searchd /usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/mersphinx.conf  --stop >> /usr/local/sphinx/var/log/sphinx/searchd.log #創建主索引 /usr/local/sphinx/bin/indexer -c  /usr/local/sphinx/etc/mersphinx.conf main >> /usr/local/sphinx/var/log/sphinx/mainindex.log #啓動searchd守護程序 /usr/local/sphinx/bin/searchd >> /usr/local/sphinx/var/log/sphinx/searchd.log
build_delta_index.sh

#!/bin/sh #中止sphinx服務,將輸出重定向 /usr/local/sphinx/bin/searchd –stop>>/usr/local/sphinx/var/log/sphinx/searchd.log #從新創建索引delta ,將輸出重定向 /usr/local/sphinx/bin/indexerdelta –c/usr/local/sphinx/etc/sphinx.conf>>/usr/lcoal/sphinx/var/log/sphinx/deltaindex.log #將delta合併到main中 /usr/local/sphinx/bin/indexer –merge main delta –c /usr/local/sphinx/etc/sphinx.conf >> /usr/lcoal/sphinx/var/log/sphinx/deltaindex.log #啓動服務 /usr/local/sphinx/bin/searchd>>/usr/local/sphinx/var/log/sphinx/searchd.log

腳本寫好後,須要編譯 chmod +x filename 這樣才能運行。即 chmod +x build_main_index.sh chmod +x build_delta_index.sh
最後,咱們須要腳本可以自動運行,以實現,delta索引每5分鐘從新創建,和main索引只在午夜2:30時從新創建。
使用crontab 命令 這有倆個地方可做參考 crontab crontab文件 crontab -e 來編輯 crontab文件,若是以前沒有使用,會是一個空的文件。寫下下面兩條語句 */30 * * * *  /bin/sh /usr/local/sphinx/etc/build_delta_index.sh > /dev/null 2>&1 30 2 * * * /bin/sh /usr/local/sphinx/etc/build_main_index.sh > /dev/null 2>&1
第一條是表示每30分鐘運行 /usr/local/sphinx/etc/下的build_delta_index.sh 腳本,輸出重定向。 第二條是表示 天天的 凌晨2:30分運行 /usr/local/sphinx/etc下的build_main_inde.sh 腳本,輸出重定向。 關於前面的 5個值的設置,在上面的crontab文件中有詳細的描述。關於重定向的解釋,請看最上面的Crontab筆記 ,也有crontab的介紹。
保存好後:從新啓動服務  

[root@test1 init.d]# service crond stop [root@test1 init.d]# service crond start 或者 /etc/init.d/crontab   start
到如今爲止,若是腳本寫的沒有問題,那麼build_delta_index.sh將每30分鐘運行一次,而build_main_index.sh將在凌晨2:30分才運行。
要驗證的話,在腳本中,有將輸出重定向到相關的文件,能夠查看下文件中的記錄是否增多,也能夠看下 /usr/local/sphinx/var/log下的 searchd.log 中,每次重建索引都會有記錄。
總結 1.索引合併問題,前面已經解釋過,兩個索引合併時,都要讀入,而後還要寫一次硬盤,IO操做量很大。而在php API調用時,Query($query,$index)中$index能夠設置多個索引名,如Query($query,"main;delta"),也就沒有必要必定將兩個索引合併,或者,合併的次數不用那麼多。 2.還有一個是沒有嘗試過的,把增量索引存放到共享內存中(/dev/shm)以提升索引性能,減小系統負荷。
關於PHP API 如何可以順利經過PHP頁面來進行檢索。 首先,在服務器上searchd 必須是運行的。 而後,根據test.php來修改下。 運行,鏈接時會出現一個很大的問題 errno =13 permission deny. 最後,查到一個英文的網頁,是由於SElinux的緣由,關於SELinux在網上能搜到。沒有很好的解決辦法,只能把SELinux設置爲不用。使用的命令有下面兩個: setenforce 在 /usr/bin 下 setenforce 1 設置SELinux 成爲enforcing模式 setenforce 0 設置SELinux 成爲permissive模式

 

 

 

過濾:

合併兩個已有的索引比從新對全部數據作索引更有效率,並且有時候必須這樣作(例如在「 主索引+增量索引」分區模式中應合併主索引和增量索引,而不是簡單地從新索引「主索引 對應的數據)。所以indexer有這個選項。合併索引通常比從新索引快,但在大型索引上仍 然不是一蹴而就。基本上,待合併的兩個索引都會被讀入內存一次,而合併後的內容須要寫 入磁盤一次。例如,合併100GB和1GB的兩個索引將致使202GB的IO操做(但極可能還 是比從新索引少) 基本的命令語法以下: indexer --merge DSTINDEX SRCINDEX[--rotate]

 

SRCINDEX的內容被合併到DSTINDEX中,所以只有DSTINDEX索引會被改變。若 DSTINDEX已經被searchd用於提供服務,則--rotate參數是必須的。最初設計的使用模式是, 將小量的更新從SRCINDEX合併到DSTINDEX中。所以,當屬性被合併時,一旦出現了重 復的文檔ID,SRCINDEX中的屬性值更優先(會覆蓋DSTINDEX中的值)。不過要注意, 「舊的」關鍵字並不會被自動刪除。例如,在DSTINDEX中有一個叫作「old」的關鍵字與文 檔123相關聯,而在SRCINDEX中則有關鍵字「new」與同一個文檔相關,那麼在合併後用 這兩個關鍵字都能找到文檔123。您能夠給出一個顯式條件來將文檔從DSTINDEX中移除, 以便應對這種狀況,相關的開關是--merge-dst-range: indexer --merge main delta--merge-dst-range deleted 00 這個開關容許您在合併過程當中對目標索引實施過濾。過濾器能夠有多個,只有知足所有過濾 條件的文檔纔會在最終合併後的索引中出現。在上述例子中,過濾器只容許「deleted」爲0 的那些條件經過,而去除全部標記爲已刪除(「deleted」)的記錄(能夠經過調用 UpdateAttributes() 設置文檔的屬性)。

 

去舊(強行更新):

情景描述:假設有一舊關鍵字「去釣魚」,與論壇貼子「週末的活動」相關聯,用「去釣魚」能夠搜索到這篇帖子。以後樓主把貼子關鍵字部分改爲了「去河邊釣魚」。若是用sphinx的indexer生成增量索引bbsattend,而後用indexer--merge bbs bbsattend--rotate合成到主索引bbs後。用「去河邊釣魚」搜不到結果,用「去釣魚」能夠搜到「去河邊釣魚」的結果。

 

解決辦法:加--merge-killists option(選項)

indexer --merge bbs bbsattend--rotate --merge-killists

相關文章
相關標籤/搜索