1. 程式人生 > >sphinx全文檢索 安裝配置和使用

sphinx全文檢索 安裝配置和使用

conf pty too worker pos 如果 lB 創建索引 AS

https://www.cnblogs.com/findgor/p/5644540.html

公司項目剛剛導入大量產品數據,然後發現網站的產品搜索很卡,原本是原生sql的like來做模糊搜索,數據量20W的時候還可以接受,但是上百萬就很卡了,所以需要做優化。

經過考慮,打算采用全文檢索 sphinx + 數據庫中間件(atlas/mycat) 的架構來優化.

我的環境:

centos6.5 64位

lnmp1.3一鍵環境包

技術分享圖片

CentOS6.4 X64 安裝sphinx及sphinx for php擴展

安裝前請先確定安裝了常用的組件,然後在官方網站下載最新的sphinx,

yum install -y python python-devel

http://sphinxsearch.com/downloads/release/

安裝sphinx

tar zxvf sphinx-2.2.10-release.tar.gz
cd sphinx-2.2.10-release
./configure --prefix=/usr/local/sphinx –-with-mysql
make && make install

在make時如果出現undefined reference to libiconv的錯,請參考 http://www.lvtao.net/database/sphinx-make-error.html 解決方法
libsphinxclient 安裝(PHP模塊需要)

cd api/libsphinxclient
./configure –prefix=/usr/local/sphinx
make &&  make install

安裝PHP的Sphinx模塊
下載地址:http://pecl.php.net/package/sphinx

wget http://pecl.php.net/get/sphinx-1.3.0.tgz
tar zxf sphinx-1.3.3.tgz
cd sphinx-1.3.3
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config --with-sphinx=/usr/local/sphinx/
make && make install

添加php擴展庫
查看php.ini位置
php --ini

技術分享圖片


編輯配置
vi /usr/local/php/etc/php.ini
:$ 跳至文件尾部

extension_dir="/usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/"
[sphinx]
extension=sphinx.so

php -m 或者 phpinfo() 查看是否已經加載擴展

技術分享圖片

首先我們得在服務器端把索引建立好,以便php通過端口訪問獲取

復制默認配置文件,重新創建一個配置文件

cp /usr/local/sphinx/etc/sphinx-min.conf.dist /usr/local/sphinx/etc/sphinx.conf

技術分享圖片

sphinx.conf.dist是完整版默認配置,有很多內容,我這裏選擇復制的是sphinx-min.conf.dist迷你版,只要滿足基本查詢需要即可

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 # # Minimal Sphinx configuration sample (clean, simple, functional) # source src1 { type = mysql sql_host = localhost sql_user = root sql_pass = root sql_db = allchips_test sql_port = 3306 # optional, default is 3306 sql_query = select * from products #sql_attr_uint = id #sql_attr_timestamp = date_added sql_field_string = product_id sql_field_string = partNo } source src2 { type = mysql sql_host = localhost sql_user = root sql_pass = root sql_db = allchips_test sql_port = 3306 # optional, default is 3306 sql_query = select * from product_prices } source src3 { type = mysql sql_host = localhost sql_user = root sql_pass = root sql_db = allchips_test sql_port = 3306 # optional, default is 3306 sql_query = select * from product_attrs } index products { source = src1 path = /mnt/data/products min_infix_len = 1 infix_fields = partNo,short_desc } index prices { source = src2 path = /mnt/data/prices } index attrs { source = src3 path = /mnt/data/attrs } indexer { mem_limit = 128M } searchd { listen = 9312 listen = 9306:mysql41 log = /mnt/data/log/searchd.log query_log = /mnt/data/log/query.log read_timeout = 5 max_children = 30 pid_file = /mnt/data/log/searchd.pid seamless_rotate = 1 preopen_indexes = 1 unlink_old = 1 workers = threads # for RT to work binlog_path = /mnt/data }

  

最下面的indexer和searchd分別是索引創建,和查詢命令的配置,基本只要設置好自己想要日誌路徑即可

重要的上面的部分,source (來源) 和 index (索引)

分析一下我的需求,我的產品搜索主要3張表

產品表products, (id,product_id)

產品價格表product_prices,

產品參數表product_attrs

三者以產品表的product_id關聯1對多

source src1 對應 index products

source src2 對應 index prices

source src3 對應 index attrs

在source中是可以設置自定義返回的字段的

如上面的
sql_field_string = product_id
sql_field_string = partNo

配置好了之後,創建索引

在使用 /usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf --all --rotate 命令的的時候,如果searchd進程沒有在監聽,執行了更新,會出現no rotate的提示。

如果不想全部生成你可以不用--all,分開多個源生成也可以

技術分享圖片

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf products

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf prices

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf attrs

如果沒有什麽問題一般是這樣的。

技術分享圖片

接下來要用searchd作為sphinx在服務器的守護進程

/usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/sphinx.conf(途中的test.conf是以前測試的,使用sphinx.conf即可)

技術分享圖片

一般如果報錯

文件夾不存在,則創建文件夾

如果已經端口進程已經在運行,那麽有2種方法停止

1,/usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/sphinx.conf --stop

2, netstat -tnl 查看端口9312是否在監聽

lsof -i:9312 查看9312端口信息,獲得pid

kill {pid}

殺掉進程之後重新執行searchd命令啟動

==========

php端

技術分享圖片
<?php
    //index.php
    phpinfo();die;
    $s = new SphinxClient;
    $s->setServer("127.0.0.1", 9312);

    $s->setMatchMode(SPH_MATCH_PHRASE);
  
  

  

//$s->setSortMode(SPH_SORT_ATTR_DESC,‘is_tuan‘); //指定模式
$s->setSortMode(SPH_SORT_EXTENDED,‘is_tuan desc‘); //擴展模式

$s->SetFilterString(‘status‘,‘1‘); //這個字段 需要在 sql_attr_string 中設置顯示,不然找不到字段 如果設置的是sql_attr_uint就是int ,後面是類型


$s->setMaxQueryTime(30); $res1 = $s->query(‘usb‘,‘products‘); $res2 = $s->query(‘53e6dde17a667c4b2af1d38ba0a466c4‘,‘prices‘); $res3 = $s->query(‘53e6dde17a667c4b2af1d38ba0a466c4‘,‘attrs‘); //$res = $s->query(‘開關‘,‘products‘); //$res = $s->query(‘products‘); $err = $s->GetLastError(); //var_dump(array_keys($res[‘matches‘])); // echo "<br>"."通過獲取的ID來讀取數據庫中的值即可。"."<br>"; echo ‘<pre>‘; $products=!empty($res1[‘matches‘])?$res1[‘matches‘]:""; $prices=!empty($res2[‘matches‘])?$res2[‘matches‘]:""; $attrs=!empty($res3[‘matches‘])?$res3[‘matches‘]:""; print_r($products); print_r($prices); print_r($attrs); if(!empty($err)){ print_r($err); } $s->close();
技術分享圖片

coreseek的官網掛了下載不了,所以暫時不弄中文。以後看有時間在下載個中文詞典打進去

技術分享圖片

這是打印的query返回的matches匹配結果,如果要查看整個query結果,可以看PHP手冊http://php.net/manual/zh/sphinxclient.query.php

返回數據結構
值說明
"matches" 存儲文檔ID以及其對應的另一個包含文檔權重和屬性值的hash表
"total" 此查詢在服務器檢索所得的匹配文檔總數(即服務器端結果集的大小,且與相關設置有關)
"total_found" (服務器上找到和處理了的)索引中匹配文檔的總數
"words" 將查詢關鍵字(關鍵字已經過大小寫轉換,取詞幹和其他處理)映射到一個包含關於關鍵字的統計數據(“docs”——在多少文檔中出現,“hits”——共出現了多少次)的小hash表上。
"error" searchd報告的錯誤信息
"warning" searchd報告的警告信息

上面的配置默認監聽了,9312和9306端口,9312是給php程序鏈接的,9306是本地數據庫調試端口,如果想要在服務器做測試,可以試試鏈接

mysql -h127.0.0.1 -P9306

技術分享圖片

products是索引名index,match是規則匹配,

通配符可以在官網手冊上 http://sphinxsearch.com/docs/current.html#conf-dict 搜索"wildcards" 看到 search (e.g. "t?st*", "run%", "*abc*") 我在使用時,發現關鍵字分詞不準確,比如 完整產品信號 PSMN1R1-25YLC,115 PSMN1R1-25YLC,115 true PSMN1R1-25YLC,11 false PSMN1R1-25YLC,1 false PSMN1R1-25YLC, true PSMN1R1-25YLC true 由此可以判斷,應該是字符分詞長度設置有問題,解決如下 source中 sql_query_pre = SET NAMES utf8 #sql執行前,會執行,為了保證不是字符集的問題 index中 min_prefix_len = 1   #設置最小索引前綴長度1 php中: 技術分享圖片
use sngrl\SphinxSearch\SphinxSearch;

class TestController extends Controller
{

    public function index(Request $request)
    {    

            
        $sphinx = new SphinxSearch();
        $sphinx->setMatchMode(\Sphinx\SphinxClient::SPH_MATCH_PHRASE);
        $results = $sphinx->search("%PSMN1R1-25YLC,11*", ‘products‘)->query();
        $error=$sphinx->getErrorMessage();
        $products=!empty($results[‘matches‘]) ? $results[‘matches‘] : array();
        echo ‘<pre>‘;
        print_r($products);

        //dd($results);

        //dd($error);

    }
}
技術分享圖片

匹配成功。

使用中會遇到的問題: 1,索引更新,可以使用rt增量索引來記錄變化的記錄id 2,定時更新索引 如果searchd進程正在運行,你除了可以kill掉他的進程外,還可以執行--rotate 參數進行 無縫更新,無需重啟服務 /usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf products --rotate 你可以把這個命令 寫入crontab任務中,定時執行,在laravel中你可以在程序中自定義。

================================================================

Atlas聽說很多人都在用,安裝測試中 待續 -

sphinx全文檢索 安裝配置和使用