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

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

 

公司項目剛剛導入大量產品數據,而後發現網站的產品搜索很卡,本來是原生sql的like來作模糊搜索,數據量20W的時候還能夠接受,可是上百萬就很卡了,因此須要作優化。html

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

個人環境:mysql

centos6.5 64位laravel

lnmp1.3一鍵環境包sql

 

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

安裝前請先肯定安裝了經常使用的組件,而後在官方網站下載最新的sphinx,數據庫

yum install -y python python-devel

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

安裝sphinxapi

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據說不少人都在用,安裝測試中 待續 -

相關文章
相關標籤/搜索