sphinx全文检索 安装配置和使用

网友投稿 1042 2022-05-30

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

sphinx全文检索 安装配置和使用

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端

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 "
"."通过获取的ID来读取数据库中的值即可。"."
"; echo '

'; $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

上面的配置默认监听了,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 '

'; 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 全文检索

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一些SAP Partners能够通过二次开发实现打通 SAP C/4HANA和S/4HANA 的场景分享
下一篇:“技术赋能 生态共享”华为开发者大会2021 中国·青岛分会场活动在青岛高新区成功举办
相关文章