跳到主要內容區塊

計資中心電子報C&INC E-paper

技術論壇

Sphinx 搜尋引擎安裝教學
  • 卷期:v0035
  • 出版日期:2015-12-20

作者:楊德倫 / 臺灣大學計算機及資訊網路中心教學研究組幹事


Sphinx是一個開放原始碼(Open Source)的搜尋引擎伺服器,並且可在 Linux、Windows、MacOS、Solaris、FreeBSD…等作業系統上運作,其主要設計在於提供使用者/用戶端「全文檢索(full-text)」的功能,同時可以結合PHP、Java、Python等程式語言,以及MySQL、MariaDB、Postgre、MSSQL、兼容ODBC的資料庫管理系統,並提供相關API,讓開發人員能夠直接操作與運用,非常方便。

 

前言

建置資料庫及資料表時,我們必須注意到哪些查詢結果,需要建立索引(Index),以便於未來針對同一查詢時,可以節省資源,並提高效能。但在專案不斷進行修正時,若無法針對查詢結果的索引進行修改或新增,隨著資料量的增加,錯誤的索引,將會造成空間的浪費,以及不必要的資源耗損。有鑑於此,我們可以透過Sphinx Search Engine Server,將原先資料庫查詢責任,交給Sphinx來處理。Sphinx可以設定T-SQL語法,將資料庫(本案例使用 MySQL)的資料,建立成Sphinx專用的索引,並透過SphinxAPI來進行資料檢索與查詢,速度比傳統資料庫管理系統快上許多,不但能節省資料庫資源,還能將查詢功能獨立出來管理,實用又便利。

 

安裝 Apache Web Server

http://www.cc.ntu.edu.tw/chinese/epaper/0033/20150620_3308.html)一文當中,解釋如何安裝 Apache Web Server,在此就不贅述了,請自行參閱。

 

安裝 PHP 5

  一、安裝 libxml2
  http://xmlsoft.org/sources/libxml2-2.9.2.tar.gz

說明:
$ sudo ./configure
--prefix=/usr/local/libxml2

二、安裝 libiconv
http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz

說明:
原則上執行下列指令
$ sudo ./configure
--prefix=/usr/local/libiconv
--enable-shared
--enable-static
若是 stdio.c 有錯誤,且跟 gets 有關
請至 /usr/local/src/php/libiconv/srclib/stdio.in.h 當中
尋找 _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
然後在其上方加上一段
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !__GLIBC_PREREQ(2, 16)
最後在 _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");下方再多加個 #endif
最後再重新編譯一次(按照原則上執行的指令再跑一次)


圖一 錯誤修正方式

三、安裝 libmcrypt
http://nchc.dl.sourceforge.net/project/mcrypt/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.gz

說明:
$ sudo ./configure
--prefix=/usr/local/libmcrypt
--enable-shared
--enable-static

四、安裝 libssh2
http://www.libssh2.org/download/libssh2-1.4.3.tar.gz

說明:
$ sudo ./configure
--prefix=/usr/local/libssh2
--with-libssl-prefix=/usr/local/openssl

五、安裝 curl
http://curl.haxx.se/download/curl-7.40.0.tar.gz

說明:
$ sudo ./configure
--prefix=/usr/local/curl
--with-ssl=/usr/local/openssl
--with-zlib=/usr/local/zlib
--with-libssh2=/usr/local/libssh2

六、安裝 jpeg
http://www.ijg.org/files/jpegsrc.v9a.tar.gz

說明:
$ sudo ./configure
--prefix=/usr/local/jpeg-9
--enable-shared
--enable-static

七、安裝 libpng
http://jaist.dl.sourceforge.net/project/libpng/libpng16/1.6.16/libpng-1.6.16.tar.gz

說明:
先回到 zlib 原先安裝的資料夾(原先由 tarball 包解開來),再執行
$ sudo make clean
$ sudo ./configure
不需要 --prefix
$ sudo make
$ sudo make install

然後再回 libpng 資料夾執行
$ sudo ./configure
--prefix=/usr/local/libpng
--with-zlib-prefix=/usr/local/zlib/
--enable-shared
--enable-static

八、安裝 freetype
http://download.savannah.gnu.org/releases/freetype/freetype-2.5.5.tar.gz

說明:
1. 安裝 freetype 前,一定要先安裝 libpng;前者依賴後者。
2. 若找不到 libpng-config:
至 /usr/local/libpng/bin,sudo cp libpng-config(此為軟連結)到 /usr/bin
3.
$ sudo ./configure
--prefix=/usr/local/freetype
--enable-shared
--enable-static

九、安裝 gd
https://bitbucket.org/libgd/gd-libgd/downloads/libgd-2.1.1.tar.gz

說明:
$ sudo ./configure
--prefix=/usr/local/libgd
--with-libiconv-prefix=/usr/local/libiconv
--with-zlib=/usr/local/zlib
--with-freetype=/usr/local/freetype
--with-jpeg=/usr/local/jpeg-9
--with-png=/usr/local/libpng
--enable-shared
--enable-static

十、安裝 PHP 5
http://php.net/distributions/php-5.6.4.tar.gz

$ sudo ./configure
--prefix=/usr/local/php5
--with-apxs2=/usr/local/apache2/bin/apxs
--with-iconv-dir=/usr/local/libiconv
--with-pcre-regex=/usr/local/pcre
--with-pcre-dir
--with-freetype-dir=/usr/local/freetype
--with-jpeg-dir=/usr/local/jpeg-9
--with-png-dir=/usr/local/libpng
--with-zlib=/usr/local/zlib
--with-zlib-dir=/usr/local/zlib
--with-libxml-dir=/usr/local/libxml2
--with-curl=/usr/local/curl
--with-mcrypt=/usr/local/libmcrypt
--with-openssl=/usr/local/openssl
--with-openssl-dir=/usr/local/openssl
--with-xmlrpc
--with-mysql
--with-mysqli
--with-gettext
--with-gd
--with-pdo-mysql
--enable-zip
--enable-calendar
--enable-bcmath
--enable-xml
--enable-mbstring
--enable-ftp
--enable-gd-native-ttf
--enable-sockets
--enable-soap
--enable-session
--enable-shared
--enable-static

備註:
1. 至 /usr/local/apache2/conf/httpd.conf ;
<IfModule mime_module>
  .
  .
Addtype application/x-httpd-php .php .phtml
  .
  .
</IfModule>

2. 至 php-5.x.x 解開後之資料夾,尋找 php.ini-development
$ sudo cp php.ini-development /usr/local/php5/lib/php.ini

3.
<IfModule dir_module>
DirectoryIndex index.php index.html
</IfModule>

十一、ssh 安裝方式(非必要)
http://pecl.php.net/get/ssh2-0.12.tgz

說明:
1. 先確認有無安裝 autoconf 套件
在 /usr/local/src/當中的ssh2資料夾裡頭,
執行 phpize(指令:/usr/local/php5/bin/phpize)
此時會出現 configure 等檔案,
再進行下列安裝指令:
$ sudo ./configure --prefix=/usr/local/ssh2
--with-ssh2=/usr/local/libssh2
--with-php-config=/usr/local/php5/bin/php-config
--enable-shared
--enable-static
2. 看看是否存在 ssh2.so 檔案
(到 /usr/local/php5/lib/php/extensions/)


圖二 確定 ssh2.so 存在與否

3. 移動至 /usr/local/php5/lib/php.ini,
到 Dynamic Extensions 區塊底下,任一地方加入extension = ssh2.so


圖三 引入 ssh2.so 檔

4. 再至有 phpinfo() 函式的網頁,查看有無下面圖示的結果


圖四 確認 ssh2 是否可以使用

安裝 MySQL

一、下載 MySQL community server 版本
說明:
請選擇「Linux – Generic」,然後視主機支援程度選擇「TAR Archive」,再將最下方的「No thanks, just start my download.」文字網址連結複製下來,貼在 linux 系統中來透過 wget 下載。


圖五 選擇平台


圖六 以 tar 包來進行安裝


圖七 複製「No, thanks ….」連結,並在 Linux 底下進行下載

備註:假設使用者下載檔案後,放置於 /usr/local/src/
$> cd /usr/local/src/
$> sudo wget http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.22-linux-glibc2.5-x86_64.tar.gz
$> tar -xzvf mysql-5.6.21-linux-glibc2.5-x86_64.tar.gz

二、將解壓縮的 mysql 資料夾放到 /usr/local/
$> mv mysql-5.6.21-linux-glibc2.5-x86_64 /usr/local/mysql

三、安裝相關函式庫(如果沒有的話)
$> sudo apt-get install libaio1

四、新增群組、帳號
$> groupadd mysql
$> useradd -s /sbin/nologin -g mysql mysql

五、複製 mysql 啟動腳本檔案到 /etc/init.d/
$> cd /usr/local/mysql/support-files/
$> cp mysql.server /etc/init.d/mysql
$> sudo chmod +x /etc/init.d/mysql

*非必要選項(Optional):
若要讓 mysql 自動開機啟動則可輸入下列指令
$> sudo update-rc.d mysql defaults

六、改變 mysql 資料夾權限,讓 mysql 帳號可以進行存取
$> cd /usr/local/mysql
$> sudo chown -R mysql:mysql ./data

七、執行 mysql 的安裝指令,並加入一些參數,成為預設值
$> sudo ./scripts/mysql_install_db
--user=mysql
--basedir=/usr/local/mysql
--datadir=/usr/local/mysql/data

八、開啟 mysql 服務
$> sudo ./bin/mysqld_safe --user=mysql &

九、啟動 mysql
$> sudo /etc/init.d/mysql start

十、查詢 mysql 開啟後的程序列表
$> sudo ps -aux | grep mysql
呈現如下結果


圖八 查詢是否啟動服務

十一、顯示版本
$> sudo ./bin/mysqladmin version


圖九 MySQL 版本查詢

 

十二、顯示 mysql 系統變數
$> sudo ./bin/mysqladmin variables

十三、將服務關掉再開,測試 mysql 安裝過程是否正確
$> sudo ./bin/mysqladmin -u root shutdown
$> sudo ./bin/mysqld_safe --user=mysql &

十四、關閉 mysql 後再開啟
$> sudo /etc/init.d/mysql stop
$> sudo /etc/init.d/mysql start

十五、設定 mysql 的 root 密碼(與 linux 的 root 不同)
$> sudo ./mysqladmin -u root password "newpassword"

十六、登入 mysql 的指令介面
$> sudo ./bin/mysql -u root -p

十七、新增一名使用者,並賦予一定權限
mysql> CREATE USER 'new-user-name'@'%' IDENTIFIED BY 'new-user-password';
GRANT ALL PRIVILEGES ON * . * TO 'new-user-name'@'%' IDENTIFIED BY 'new-user-password' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;

十八、下載 phpMyAdmin,並設定 config.inc.php 檔
說明:
phpMyAdmin是一種網頁介面的資料庫管理工具(網頁伺服器需要能夠執行PHP)。此步驟可有可無,若有安裝網頁伺服器,可考慮一同建置。另外,請放置該工具資料夾於網頁根目錄下,方便使用與測試。

$i++
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'MySQL 伺服器的 IP或本機 localhost';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['compress'] = false;
/* Select mysql if your server does not have mysqli */
$cfg['Servers'][$i]['extension'] = 'mysqli';
$cfg['Servers'][$i]['AllowNoPassword'] = false;

* 備註:
由於 MySQL 的使用,在網路上已有許多文件,在此僅提供安裝方式,使用方式請於網路上尋找與學習。

安裝Sphinx

一、安裝 sphinx
http://sphinxsearch.com/files/sphinx-2.2.7-release.tar.gz

$ sudo tar -zxvf sphinx-2.2.7-release.tar.gz
$ sudo ./configure
--prefix=/usr/local/sphinx
--with-mysql=/usr/local/mysql
$ sudo make
$ sudo make install

二、安裝libsphinxclient
說明:到sphinx-2.2.7資料夾當中,進入api資料夾,找尋libsphinxclient資料夾
$ cd /usr/local/src/sphinx-2.2.7-release/api/libsphinxclient
$ sudo ./configure
$ sudo make
$ sudo make install

三、安裝 sphinx client for PHP(sphinx.so檔)
http://pecl.php.net/get/sphinx

說明:讓 php 支援 Sphinx 套件
$ sudo tar -zxvf sphinx-1.3.2.tgz
$ cd sphinx-1.3.2
$ sudo /usr/local/php5/bin/phpize


圖十 擴展 sphinx 套件(產生 configure 文件)

此時會出現 sphinx client 的相關 configure 檔案


圖十一 看到可編輯的檔案

再進行安裝
$ sudo ./configure
--prefix=/usr/local/sphinx
--with-sphinx
--with-php-config=/usr/local/php5/bin/php-config
--enable-static
--enable-shared
$ sudo make
$ sudo make install
成功後,會出現下列訊息
Installing shared extensions: /usr/local/php5/lib/php/extensions/no-debug-zts-20131226/
我們再到 php.ini 裡面加入 extension = phinx.so(先前有加入 ssh2.so 過)


圖十二 加入 sphinx.so 檔到 php.ini

再來透過 phpinfo() 來檢查是否支援 Sphinx api for php


圖十三 確定 PHP 有支援 sphinx

* 備註:若是出現 configure: error: Cannot find libsphinxclient headers
請下載 http://sphinxsearch.com/files/sphinx-2.2.7-release.tar.gz
解壓縮後,再到 sphinx-2.2.7 資料夾當中,進入 api資料夾,至 libsphinxclient資料夾,進行如同 二、 的步驟安裝。有時候我們只是想在 PHP 上掛.sphinx.so,讓 php 支援,而非架設整個 sphinx 伺服器。

四、設定 sphinx.conf 檔
先將 /usr/local/sphinx/etc/sphinx.conf.dist 複製到 /usr/local/sphinx 底下
$ sudo cp /usr/local/sphinx/etc/sphinx.conf.dist /usr/local/sphinx
再重新命名為 sphinx.conf
$sudo mv /usr/local/sphinx/sphinx.conf.dist /usr/local/sphinx/sphinx.conf
內容的設定,原則上以修正兩個部分為主,一個是 src,一個是 index,基本結構如下:
source 來源名稱1{
#資料來源設定
}
index 索引名稱1{
#索引設定
source = 來源名稱1
}
source 來源名稱2{
#資料來源設定
}
index 索引名稱2{
#索引設定
source = 來源名稱2
}
indexer{
# indexer 配置
}
searchd{
# searchd 配置
}
參考配置如下:

啟動 & 使用 Sphinx

一、筆者常用測試指令
$ sudo /usr/local/sphinx/bin/searchd --stop;
(關閉 Sphinx)
$ sudo rm /usr/local/sphinx/var/data/*; sudo rm /usr/local/sphinx/var/log/*;
(刪除先前建立的索引及日誌)
$ sudo /usr/local/sphinx/bin/indexer --all;
(建立所有索引;我們也可以開啟特定 index,例如設定檔中的 test1)
$ sudo /usr/local/sphinx/bin/searchd;
(啟動 Sphinx)
$ sudo /usr/local/sphinx/bin/indexer --rotate --all;
(動態更新索引將尚未建立索引的 MySQL 資料匯入;要先啟動 Sphinx)

二、防止啟動 searchd 時出錯的措施
說明:
如果出現類似以下的訊息
/usr/local/sphinx/bin/indexer:error while loading shared libraries:libmysqlclient.so.18 cannot open shared object file: No such file or directory
請執行下面的指令
$ sudo ln -s /usr/local/mysql/lib/libmysqlclient.so.18 /usr/lib/libmysqlclient.so.18

三、資料庫參考
說明:我們要檢索的部分為 cht_name, eng_name, content

1. 結構


圖十四 資料表結構

2. cht_name 是中文名稱,eng_name 是英文名稱,content 是自訂內容

四、啟動 sphinx
說明:
1. 針對 test1 索引
/usr/local/bin/indexer test1


圖十五 建立索引

2. 啟動 searchd
/usr/local/sphinx/bin/searchd -i test1


圖十六 啟動 Sphinx 服務

五、測試全文檢索機制可否運作
說明:
請建立一 php 檔,寫入下列程式碼
<?php
$s = new SphinxClient;
$s->setServer("localhost", 9312);

//搜尋伺服器模式,之後會介紹
$s->setMatchMode(SPH_MATCH_ALL);

$s->setMaxQueryTime(60);

$result = $s->query("網球");

echo "<pre>";
print_r($result);
echo "</pre>";
?>
而後將有相關陣列資訊呈現,便成功了

最後,就看各位對 PHP 的熟悉程度,來對 Array 進行解析與運用。

Sphinx 搜尋模式簡介

目前可以將搜尋伺服器的模式,簡化成四種。

第一種模式(SPH_MATCH_ALL),
對所有文字進行查詢,
查詢文字的先後可以不同,前後順序不影響權重,
同時文字越多,查詢結果就會愈少。

第二種模式(SPH_MATCH_ANY),
只要符合其中一個文字就會被查詢,
查詢文字的先後可以不同,符合前後順序的權重愈高,
同時文字越多,查詢結果就會越多。(不推薦)

第三種模式(SPH_MATCH_PHRASE),
對所有文字進行查詢,
查詢文字的先後不能不同,順序不同不會出現在結果裡,
算是一種精準的查詢,類似 SQL Like 的語法,只是必須按照順序才會被撈出。

第四種模式(SPH_MATCH_EXTENDED2),
對所有文字進行查詢,
查詢文字的先後可以不同,符合前後順序的權重愈高,
同時文字越多,查詢結果就會越少。
(跟第一種模式很像,差異在於權重計算方式)

後記

現行有許多專案,透過Sphinx來建立查詢機制,同時也支援PHP、Java、Python等程式語言,以及MySQL、MariaDB、Postgre、MSSQL、兼容 ODBC 的資料庫管理系統,並且可在Linux、Windows、MacOS、Solaris、FreeBSD…等作業系統上運作,對入門、進階的開發者而言,不失為一套簡易又便利的全文檢索伺服器。

參考資料

[1] Sphinx (search engine) from Wikipedia
https://en.wikipedia.org/wiki/Sphinx_(search_engine)
[2] Sphinx 官方網站
http://sphinxsearch.com/
[3] Jax 的工作紀錄:MySQL 全文檢索引擎 - Sphinx
http://jax-work-archive.blogspot.tw/2009/05/mysql-sphinx.html#sphinx_conf_deploy