1. 程式人生 > >php+中文分詞scws+sphinx+mysql打造千萬級數據全文搜索

php+中文分詞scws+sphinx+mysql打造千萬級數據全文搜索

libc 海量 modules shell pub redis集群 register 處理 onf

Sphinx是由俄羅斯人Andrew Aksyonoff開發的一個全文檢索引擎。意圖為其他應用提供高速、低空間占用、高結果 相關度的全文搜索功能。Sphinx可以非常容易的與SQL數據庫和腳本語言集成。當前系統內置MySQL和PostgreSQL 數據庫數據源的支持,也支持從標準輸入讀取特定格式 的XML數據。
Sphinx創建索引的速度為:創建100萬條記錄的索引只需3~4分鐘,創建1000萬條記錄的索引可以在50分鐘內完成,而只包含最新10萬條記錄的增量索引,重建一次只需幾十秒。
Sphinx的特性如下:
a) 高速的建立索引(在當代CPU上,峰值性能可達到10 MB/秒);
b) 高性能的搜索(在2 – 4GB 的文本數據上,平均每次檢索響應時間小於0.1秒);

c) 可處理海量數據(目前已知可以處理超過100 GB的文本數據, 在單一CPU的系統上可處理100 M 文檔);
d) 提供了優秀的相關度算法,基於短語相似度和統計(BM25)的復合Ranking方法;
e) 支持分布式搜索;
f) 支持短語搜索
g) 提供文檔摘要生成
h) 可作為MySQL的存儲引擎提供搜索服務;
i) 支持布爾、短語、詞語相似度等多種檢索模式;
j) 文檔支持多個全文檢索字段(最大不超過32個);
k) 文檔支持多個額外的屬性信息(例如:分組信息,時間戳等);
l) 支持斷詞;
雖然mysql的MYISAM提供全文索引,但是性能卻不敢讓人恭維


開始搭建

系統環境:centos6.5+php5.6+apache+MySQL

1、安裝依賴包

[php] view plain copy
  1. yum -y install make gcc g++ gcc-c++ libtool autoconf automake imake php-devel mysql-devel libxml2-devel expat-devel


2、安裝Sphinx

[php] view plain copy
  1. yum install expat expat-devel
  2. wget -c http://sphinxsearch.com/files/sphinx-2.0.7-release.tar.gz
  3. tar zxvf sphinx-2.0.7-release.tar.gz
  4. cd sphinx-2.0.7-release
  5. ./configure --prefix=/usr/local/sphinx --with-mysql --with-libexpat --enable-id64
  6. make && make install

3、安裝libsphinxclient,PHP擴展用到

[php] view plain copy
  1. cd api/libsphinxclient
  2. ./configure --prefix=/usr/local/sphinx/libsphinxclient
  3. make && make install


4、安裝Sphinx的PHP擴展:我的是5.6需裝sphinx-1.3.3.tgz,如果是php5.4以下可sphinx-1.3.0.tgz

[php] view plain copy
  1. wget -c http://pecl.php.net/get/sphinx-1.3.3.tgz
  2. tar zxvf sphinx-1.3.3.tgz
  3. cd sphinx-1.3.3
  4. phpize
  5. ./configure --with-sphinx=/usr/local/sphinx/libsphinxclient/ --with-php-config=/usr/bin/php-config
  6. make && make install
  7. 成功後會提示:
  8. Installing shared extensions: /usr/lib64/php/modules/
  9. echo "[Sphinx]" >> /etc/php.ini
  10. echo "extension = sphinx.so" >> /etc/php.ini
  11. #重啟apache
  12. service httpd restart


5、創建測試數據

[php] view plain copy
  1. CREATE TABLE IF NOT EXISTS `items` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `title` varchar(255) NOT NULL,
  4. `content` text NOT NULL,
  5. `created` datetime NOT NULL,
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=‘全文檢索測試的數據表‘ AUTO_INCREMENT=11 ;
  8. INSERT INTO `items` (`id`, `title`, `content`, `created`) VALUES
  9. (1, ‘linux mysql集群安裝‘, ‘MySQL Cluster 是MySQL 適合於分布式計算環境的高實用、可拓展、高性能、高冗余版本‘, ‘2016-09-07 00:00:00‘),
  10. (2, ‘mysql主從復制‘, ‘mysql主從備份(復制)的基本原理 mysql支持單向、異步復制,復制過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器‘, ‘2016-09-06 00:00:00‘),
  11. (3, ‘hello‘, ‘can you search me?‘, ‘2016-09-05 00:00:00‘),
  12. (4, ‘mysql‘, ‘mysql is the best database?‘, ‘2016-09-03 00:00:00‘),
  13. (5, ‘mysql索引‘, ‘關於MySQL索引的好處,如果正確合理設計並且使用索引的MySQL是一輛蘭博基尼的話,那麽沒有設計和使用索引的MySQL就是一個人力三輪車‘, ‘2016-09-01 00:00:00‘),
  14. (6, ‘集群‘, ‘關於MySQL索引的好處,如果正確合理設計並且使用索引的MySQL是一輛蘭博基尼的話,那麽沒有設計和使用索引的MySQL就是一個人力三輪車‘, ‘0000-00-00 00:00:00‘),
  15. (9, ‘復制原理‘, ‘redis也有復制‘, ‘0000-00-00 00:00:00‘),
  16. (10, ‘redis集群‘, ‘集群技術是構建高性能網站架構的重要手段,試想在網站承受高並發訪問壓力的同時,還需要從海量數據中查詢出滿足條件的數據,並快速響應,我們必然想到的是將數據進行切片,把數據根據某種規則放入多個不同的服務器節點,來降低單節點服務器的壓力‘, ‘0000-00-00 00:00:00‘);
  17. CREATE TABLE IF NOT EXISTS `sph_counter` (
  18. `counter_id` int(11) NOT NULL,
  19. `max_doc_id` int(11) NOT NULL,
  20. PRIMARY KEY (`counter_id`)
  21. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT=‘增量索引標示的計數表‘;

以下采用"Main + Delta" ("主索引"+"增量索引")的索引策略,使用Sphinx自帶的一元分詞。

6、Sphinx配置:註意修改數據源配置信息

[php] view plain copy
  1. vi /usr/local/sphinx/etc/sphinx.conf
  2. source items {
  3. type = mysql
  4. sql_host = localhost
  5. sql_user = root
  6. sql_pass = 123456
  7. sql_db = sphinx_items
  8. sql_query_pre = SET NAMES utf8
  9. sql_query_pre = SET SESSION query_cache_type = OFF
  10. sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM items
  11. sql_query_range = SELECT MIN(id), MAX(id) FROM items \
  12. WHERE id<=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1)
  13. sql_range_step = 1000
  14. sql_ranged_throttle = 1000
  15. sql_query = SELECT id, title, content, created, 0 as deleted FROM items \
  16. WHERE id<=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1) \
  17. AND id >= $start AND id <= $end
  18. sql_attr_timestamp = created
  19. sql_attr_bool = deleted
  20. }
  21. source items_delta : items {
  22. sql_query_pre = SET NAMES utf8
  23. sql_query_range = SELECT MIN(id), MAX(id) FROM items \
  24. WHERE id > (SELECT max_doc_id FROM sph_counter WHERE counter_id=1)
  25. sql_query = SELECT id, title, content, created, 0 as deleted FROM items \
  26. WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) \
  27. AND id >= $start AND id <= $end
  28. sql_query_post_index = set @max_doc_id :=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1)
  29. sql_query_post_index = REPLACE INTO sph_counter SELECT 2, IF($maxid, $maxid, @max_doc_id)
  30. }
  31. #主索引
  32. index items {
  33. source = items
  34. path = /usr/local/sphinx/var/data/items
  35. docinfo = extern
  36. morphology = none
  37. min_word_len = 1
  38. min_prefix_len = 0
  39. html_strip = 1
  40. html_remove_elements = style, script
  41. ngram_len = 1
  42. ngram_chars = U+3000..U+2FA1F
  43. charset_type = utf-8
  44. charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
  45. preopen = 1
  46. min_infix_len = 1
  47. }
  48. #增量索引
  49. index items_delta : items {
  50. source = items_delta
  51. path = /usr/local/sphinx/var/data/items-delta
  52. }
  53. #分布式索引
  54. index master {
  55. type = distributed
  56. local = items
  57. local = items_delta
  58. }
  59. indexer {
  60. mem_limit = 256M
  61. }
  62. searchd {
  63. listen = 9312
  64. listen = 9306:mysql41 #Used for SphinxQL
  65. log = /usr/local/sphinx/var/log/searchd.log
  66. query_log = /usr/local/sphinx/var/log/query.log
  67. compat_sphinxql_magics = 0
  68. attr_flush_period = 600
  69. mva_updates_pool = 16M
  70. read_timeout = 5
  71. max_children = 0
  72. dist_threads = 2
  73. pid_file = /usr/local/sphinx/var/log/searchd.pid
  74. max_matches = 1000
  75. seamless_rotate = 1
  76. preopen_indexes = 1
  77. unlink_old = 1
  78. workers = threads # for RT to work
  79. binlog_path = /usr/local/sphinx/var/data
  80. }

保存退出

7、Sphinx創建索引

[php] view plain copy
  1. #第一次需重建索引:
  2. [[email protected] bin]# ./indexer -c /usr/local/sphinx/etc/sphinx.conf --all
  3. Sphinx 2.0.7-id64-release (r3759)
  4. Copyright (c) 2001-2012, Andrew Aksyonoff
  5. Copyright (c) 2008-2012, Sphinx Technologies Inc (http://sphinxsearch.com)
  6. using config file ‘/usr/local/sphinx/etc/sphinx.conf‘...
  7. indexing index ‘items‘...
  8. collected 8 docs, 0.0 MB
  9. sorted 0.0 Mhits, 100.0% done
  10. total 8 docs, 1121 bytes
  11. total 1.017 sec, 1101 bytes/sec, 7.86 docs/sec
  12. indexing index ‘items_delta‘...
  13. collected 0 docs, 0.0 MB
  14. total 0 docs, 0 bytes
  15. total 1.007 sec, 0 bytes/sec, 0.00 docs/sec
  16. skipping non-plain index ‘master‘...
  17. total 4 reads, 0.000 sec, 0.7 kb/call avg, 0.0 msec/call avg
  18. total 14 writes, 0.001 sec, 0.5 kb/call avg, 0.1 msec/call avg
  19. #啟動sphinx
  20. [[email protected] bin]# ./searchd -c /usr/local/sphinx/etc/sphinx.conf
  21. Sphinx 2.0.7-id64-release (r3759)
  22. Copyright (c) 2001-2012, Andrew Aksyonoff
  23. Copyright (c) 2008-2012, Sphinx Technologies Inc (http://sphinxsearch.com)
  24. using config file ‘/usr/local/sphinx/etc/sphinx.conf‘...
  25. listening on all interfaces, port=9312
  26. listening on all interfaces, port=9306
  27. precaching index ‘items‘
  28. precaching index ‘items_delta‘
  29. rotating index ‘items_delta‘: success
  30. precached 2 indexes in 0.012 sec
  31. #查看進程
  32. [[email protected] bin]# ps -ef | grep searchd
  33. root 30431 1 0 23:59 ? 00:00:00 ./searchd -c /usr/local/sphinx/etc/sphinx.conf
  34. root 30432 30431 0 23:59 ? 00:00:00 ./searchd -c /usr/local/sphinx/etc/sphinx.conf
  35. root 30437 1490 0 23:59 pts/0 00:00:00 grep searchd
  36. #停止Searchd:
  37. ./searchd -c /usr/local/sphinx/etc/sphinx.conf --stop
  38. #查看Searchd狀態:
  39. ./searchd -c /usr/local/sphinx/etc/sphinx.conf --status

索引更新及使用說明
"增量索引"每N分鐘更新一次.通常在每天晚上低負載的時進行一次索引合並,同時重新建立"增量索引"。當然"主索引"數據不多的話,也可以直接重新建立"主索引"。
API搜索的時,同時使用"主索引"和"增量索引",這樣可以獲得準實時的搜索數據.本文的Sphinx配置將"主索引"和"增量索引"放到分布式索引master中,因此只需查詢分布式索引"master"即可獲得全部匹配數據(包括最新數據)。

索引的更新與合並的操作可以放到cron job完成:

[php] view plain copy
  1. crontab -e
  2. */1 * * * * /usr/local/sphinx/shell/delta_index_update.sh
  3. 0 3 * * * /usr/local/sphinx/shell/merge_daily_index.sh
  4. crontab -l

cron job所用的shell腳本例子:

delta_index_update.sh:

[php] view plain copy
  1. #!/bin/bash
  2. /usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf --rotate items_delta > /dev/null 2>&1

merge_daily_index.sh:

[php] view plain copy
  1. #!/bin/bash
  2. indexer=`which indexer`
  3. mysql=`which mysql`
  4. QUERY="use sphinx_items;select max_doc_id from sph_counter where counter_id = 2 limit 1;"
  5. index_counter=$($mysql -h192.168.1.198 -uroot -p123456 -sN -e "$QUERY")
  6. #merge "main + delta" indexes
  7. $indexer -c /usr/local/sphinx/etc/sphinx.conf --rotate --merge items items_delta --merge-dst-range deleted 0 0 >> /usr/local/sphinx/var/index_merge.log 2>&1
  8. if [ "$?" -eq 0 ]; then
  9. ##update sphinx counter
  10. if [ ! -z $index_counter ]; then
  11. $mysql -h192.168.1.198 -uroot -p123456 -Dsphinx_items -e "REPLACE INTO sph_counter VALUES (1, ‘$index_counter‘)"
  12. fi
  13. ##rebuild delta index to avoid confusion with main index
  14. $indexer -c /usr/local/sphinx/etc/sphinx.conf --rotate items_delta >> /usr/local/sphinx/var/rebuild_deltaindex.log 2>&1
  15. fi


8、php中文分詞scws安裝:註意擴展的版本和php的版本

[php] view plain copy
  1. wget -c http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2
  2. tar jxvf scws-1.2.3.tar.bz2
  3. cd scws-1.2.3
  4. ./configure --prefix=/usr/local/scws
  5. make && make install


9、scws的PHP擴展安裝:

[php] view plain copy
  1. cd ./phpext
  2. phpize
  3. ./configure
  4. make && make install
  5. echo "[scws]" >> /etc/php.ini
  6. echo "extension = scws.so" >> /etc/php.ini
  7. echo "scws.default.charset = utf-8" >> /etc/php.ini
  8. echo "scws.default.fpath = /usr/local/scws/etc/" >> /etc/php.ini


10、詞庫安裝:

[php] view plain copy
  1. wget http://www.xunsearch.com/scws/down/scws-dict-chs-utf8.tar.bz2
  2. tar jxvf scws-dict-chs-utf8.tar.bz2 -C /usr/local/scws/etc/
  3. chown www:www /usr/local/scws/etc/dict.utf8.xdb

11、php使用Sphinx+scws測試例子
在Sphinx源碼API中,有好幾種語言的API調用.其中有一個是sphinxapi.php。
不過以下的測試使用的是Sphinx的PHP擴展.具體安裝見本文開頭的Sphinx安裝部分。
測試用的搜索類Search.php:註意修改getDBConnection()信息為自己的

[php] view plain copy
  1. <?php
  2. class Search {
  3. /**
  4. * @var SphinxClient
  5. **/
  6. protected $client;
  7. /**
  8. * @var string
  9. **/
  10. protected $keywords;
  11. /**
  12. * @var resource
  13. **/
  14. private static $dbconnection = null;
  15. /**
  16. * Constructor
  17. **/
  18. public function __construct($options = array()) {
  19. $defaults = array(
  20. ‘query_mode‘ => SPH_MATCH_EXTENDED2,
  21. ‘sort_mode‘ => SPH_SORT_EXTENDED,
  22. ‘ranking_mode‘ => SPH_RANK_PROXIMITY_BM25,
  23. ‘field_weights‘ => array(),
  24. ‘max_matches‘ => 1000,
  25. ‘snippet_enabled‘ => true,
  26. ‘snippet_index‘ => ‘items‘,
  27. ‘snippet_fields‘ => array(),
  28. );
  29. $this->options = array_merge($defaults, $options);
  30. $this->client = new SphinxClient();
  31. //$this->client->setServer("192.168.1.198", 9312);
  32. $this->client->setMatchMode($this->options[‘query_mode‘]);
  33. if ($this->options[‘field_weights‘] !== array()) {
  34. $this->client->setFieldWeights($this->options[‘field_weights‘]);
  35. }
  36. /*
  37. if ( in_array($this->options[‘query_mode‘], [SPH_MATCH_EXTENDED2,SPH_MATCH_EXTENDED]) ) {
  38. $this->client->setRankingMode($this->options[‘ranking_mode‘]);
  39. }
  40. */
  41. }
  42. /**
  43. * Query
  44. *
  45. * @param string $keywords
  46. * @param integer $offset
  47. * @param integer $limit
  48. * @param string $index
  49. * @return array
  50. **/
  51. public function query($keywords, $offset = 0, $limit = 10, $index = ‘*‘) {
  52. $this->keywords = $keywords;
  53. $max_matches = $limit > $this->options[‘max_matches‘] ? $limit : $this->options[‘max_matches‘];
  54. $this->client->setLimits($offset, $limit, $max_matches);
  55. $query_results = $this->client->query($keywords, $index);
  56. if ($query_results === false) {
  57. $this->log(‘error:‘ . $this->client->getLastError());
  58. }
  59. $res = [];
  60. if ( empty($query_results[‘matches‘]) ) {
  61. return $res;
  62. }
  63. $res[‘total‘] = $query_results[‘total‘];
  64. $res[‘total_found‘] = $query_results[‘total_found‘];
  65. $res[‘time‘] = $query_results[‘time‘];
  66. $doc_ids = array_keys($query_results[‘matches‘]);
  67. unset($query_results);
  68. $res[‘data‘] = $this->fetch_data($doc_ids);
  69. if ($this->options[‘snippet_enabled‘]) {
  70. $this->buildExcerptRows($res[‘data‘]);
  71. }
  72. return $res;
  73. }
  74. /**
  75. * custom sorting
  76. *
  77. * @param string $sortBy
  78. * @param int $mode
  79. * @return bool
  80. **/
  81. public function setSortBy($sortBy = ‘‘, $mode = 0) {
  82. if ($sortBy) {
  83. $mode = $mode ?: $this->options[‘sort_mode‘];
  84. $this->client->setSortMode($mode, $sortBy);
  85. } else {
  86. $this->client->setSortMode(SPH_SORT_RELEVANCE);
  87. }
  88. }
  89. /**
  90. * fetch data based on matched doc_ids
  91. *
  92. * @param array $doc_ids
  93. * @return array
  94. **/
  95. protected function fetch_data($doc_ids) {
  96. $ids = implode(‘,‘, $doc_ids);
  97. $queries = self::getDBConnection()->query("SELECT * FROM items WHERE id in ($ids)", PDO::FETCH_ASSOC);
  98. return iterator_to_array($queries);
  99. }
  100. /**
  101. * build excerpts for data
  102. *
  103. * @param array $rows
  104. * @return array
  105. **/
  106. protected function buildExcerptRows(&$rows) {
  107. $options = array(
  108. ‘before_match‘ => ‘<b style="color:red">‘,
  109. ‘after_match‘ => ‘</b>‘,
  110. ‘chunk_separator‘ => ‘...‘,
  111. ‘limit‘ => 256,
  112. ‘around‘ => 3,
  113. ‘exact_phrase‘ => false,
  114. ‘single_passage‘ => true,
  115. ‘limit_words‘ => 5,
  116. );
  117. $scount = count($this->options[‘snippet_fields‘]);
  118. foreach ($rows as &$row) {
  119. foreach ($row as $fk => $item) {
  120. if (!is_string($item) || ($scount && !in_array($fk, $this->options[‘snippet_fields‘])) ) continue;
  121. $item = preg_replace(‘/[\r\t\n]+/‘, ‘‘, strip_tags($item));
  122. $res = $this->client->buildExcerpts(array($item), $this->options[‘snippet_index‘], $this->keywords, $options);
  123. $row[$fk] = $res === false ? $item : $res[0];
  124. }
  125. }
  126. return $rows;
  127. }
  128. /**
  129. * database connection
  130. *
  131. * @return resource
  132. **/
  133. private static function getDBConnection() {
  134. $dsn = ‘mysql:host=192.168.1.198;dbname=sphinx_items‘;
  135. $user = ‘root‘;
  136. $pass = ‘123456‘;
  137. if (!self::$dbconnection) {
  138. try {
  139. self::$dbconnection = new PDO($dsn, $user, $pass);
  140. } catch (PDOException $e) {
  141. die(‘Connection failed: ‘ . $e->getMessage());
  142. }
  143. }
  144. return self::$dbconnection;
  145. }
  146. /**
  147. * Chinese words segmentation
  148. *
  149. **/
  150. public function wordSplit($keywords) {
  151. $fpath = ini_get(‘scws.default.fpath‘);
  152. $so = scws_new();
  153. $so->set_charset(‘utf-8‘);
  154. $so->add_dict($fpath . ‘/dict.utf8.xdb‘);
  155. //$so->add_dict($fpath .‘/custom_dict.txt‘, SCWS_XDICT_TXT);
  156. $so->set_rule($fpath . ‘/rules.utf8.ini‘);
  157. $so->set_ignore(true);
  158. $so->set_multi(false);
  159. $so->set_duality(false);
  160. $so->send_text($keywords);
  161. $words = [];
  162. $results = $so->get_result();
  163. foreach ($results as $res) {
  164. $words[] = ‘(‘ . $res[‘word‘] . ‘)‘;
  165. }
  166. $words[] = ‘(‘ . $keywords . ‘)‘;
  167. return join(‘|‘, $words);
  168. }
  169. /**
  170. * get current sphinx client
  171. *
  172. * @return resource
  173. **/
  174. public function getClient() {
  175. return $this->client;
  176. }
  177. /**
  178. * log error
  179. **/
  180. public function log($msg) {
  181. // log errors here
  182. //echo $msg;
  183. }
  184. /**
  185. * magic methods
  186. **/
  187. public function __call($method, $args) {
  188. $rc = new ReflectionClass(‘SphinxClient‘);
  189. if ( !$rc->hasMethod($method) ) {
  190. throw new Exception(‘invalid method :‘ . $method);
  191. }
  192. return call_user_func_array(array($this->client, $method), $args);
  193. }
  194. }


測試文件test.php:

[php] view plain copy
  1. <?php
  2. require(‘Search.php‘);
  3. $s = new Search([
  4. ‘snippet_fields‘ => [‘title‘, ‘content‘],
  5. ‘field_weights‘ => [‘title‘ => 20, ‘content‘ => 10],
  6. ]);
  7. $s->setSortMode(SPH_SORT_EXTENDED, ‘created desc,@weight desc‘);
  8. //$s->setSortBy(‘created desc,@weight desc‘);
  9. $words = $s->wordSplit("mysql集群");//先分詞 結果:(mysql)|(mysql集群)
  10. //print_r($words);exit;
  11. $res = $s->query($words, 0, 10, ‘master‘);
  12. echo ‘<pre/>‘;print_r($res);

測試結果:

技術分享

12、SphinxQL測試

要使用SphinxQL需要在Searchd的配置裏面增加相應的監聽端口(參考上文配置)。

[php] view plain copy
  1. [[email protected] bin]# mysql -h127.0.0.1 -P9306 -uroot -p
  2. Enter password:
  3. Welcome to the MySQL monitor. Commands end with ; or \g.
  4. Your MySQL connection id is 1
  5. Server version: 2.0.7-id64-release (r3759)
  6. Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  7. Oracle is a registered trademark of Oracle Corporation and/or its
  8. affiliates. Other names may be trademarks of their respective
  9. owners.
  10. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement.
  11. mysql> show global variables;
  12. +----------------------+---------+
  13. | Variable_name | Value |
  14. +----------------------+---------+
  15. | autocommit | 1 |
  16. | collation_connection | libc_ci |
  17. | query_log_format | plain |
  18. | log_level | info |
  19. +----------------------+---------+
  20. 4 rows in set (0.00 sec)
  21. mysql> desc items;
  22. +---------+-----------+
  23. | Field | Type |
  24. +---------+-----------+
  25. | id | bigint |
  26. | title | field |
  27. | content | field |
  28. | created | timestamp |
  29. | deleted | bool |
  30. +---------+-----------+
  31. 5 rows in set (0.00 sec)
  32. mysql> select * from master where match (‘mysql集群‘) limit 10;
  33. +------+---------+---------+
  34. | id | created | deleted |
  35. +------+---------+---------+
  36. | 1 | 2016 | 0 |
  37. | 6 | 0 | 0 |
  38. +------+---------+---------+
  39. 2 rows in set (0.00 sec)
  40. mysql> show meta;
  41. +---------------+-------+
  42. | Variable_name | Value |
  43. +---------------+-------+
  44. | total | 2 |
  45. | total_found | 2 |
  46. | time | 0.006 |
  47. | keyword[0] | mysql |
  48. | docs[0] | 5 |
  49. | hits[0] | 15 |
  50. | keyword[1] | 集 |
  51. | docs[1] | 3 |
  52. | hits[1] | 4 |
  53. | keyword[2] | 群 |
  54. | docs[2] | 3 |
  55. | hits[2] | 4 |
  56. +---------------+-------+
  57. 12 rows in set (0.00 sec)
  58. mysql>

php+中文分詞scws+sphinx+mysql打造千萬級數據全文搜索