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

网友投稿 964 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

5

6

7

8

9

10

11

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

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 中国·青岛分会场活动在青岛高新区成功举办
相关文章