网搜索引擎架构设计


目  录

一、XX网搜索引擎架构设计: 3

1、搜索引擎架构图(基于PHP+MySQL+Sphinx): 3

2、搜索引擎架构设计思路: 3

⑴、调用方式最简化: 3

⑵、创建索引、查询速度快: 3

⑶、按服务类型进行分离: 4

⑷、“主索引+增量索引”更新方式: 4

⑸、“Ext3文件系统+tmpfs内存文件系统”相结合: 4

⑹、中文分词词库: 5

二、MySQL+Sphinx+SphinxSE安装步骤: 5

1、安装python支持 5

2、编译安装LibMMSeg 5

3、编译安装MySQL 5.1.26-rc、Sphinx、SphinxSE存储引擎 5

4、创建Sphinx索引文件和MySQL数据文件存放目录 6

5、创建MySQL配置文件(以线上配置文件为准) 6

⑴、创建配置文件/mysql/3306/my.cnf(以db11的3306端口为例) 6

⑵、创建配置文件/mysql/3406/my.cnf(以db11的3406端口为例) 8

6、制作一份MySQL Slave供搜索引擎使用 10

7、创建快捷启动、停止、重启、杀死MySQL进程的脚本(以db11的3306端口为例) 10

三、Sphinx配置: 11

1、生成Sphinx中文分词词库 11

⑴、词典的构造 12

⑵、词典文件格式 12

⑶、XX网搜索引擎的中文分词词库 12

2、创建Sphinx主索引文件、增量索引文件存放目录 12

3、创建Sphinx配置文件 13

4、初始化sphinx.conf中配置的全部索引 13

5、创建两个shell脚本,一个用来创建主索引、一个用来创建增量索引。 13

⑴、主索引更新脚本 13

①、创建脚本build_main_index.sh: 13

②、赋予主索引更新脚本可执行权限: 13

③、每天凌晨定时重建主索引: 13

⑵、增量索引更新脚本 13

①、创建脚本build_delta_index.sh: 13

②、赋予增量索引更新脚本可执行权限: 14

③、每3分钟自动重建一次搜索引擎的增量索引: 14

6、启动Sphinx守护进程(searchd) 14

7、配置服务器开机启动时需要自动执行的命令(以db11为例) 14

8、创建Sphinx存储引擎表: 14

⑴、设置/etc/hosts 14

⑵、登录运行在3306端口的MySQL服务器(提供“搜索查询服务”): 14

⑶、创建数据库“Sphinx”和相对应的Sphinx表(SQL语句): 15

示例SQL: 15

四、如何通过SQL语句调用搜索引擎: 15

1、搜索应用实例 15

⑴、XX网北京出租房搜索 15

⑵、XX网北京小区搜索 15

⑶、在指定字段中搜索(例如在字段“title”中搜索关键字“中关村”) 16

2、SphinxSE存储引擎及SQL语法详细说明 16

 

一、XX网搜索引擎架构设计:

1、搜索引擎架构图(基于PHP+MySQL+Sphinx):

注:目前有两台搜索数据库,db9(192.168.113.209)(MySQL 3306端口用于搜索查询、3406端口用于建索引)和db11(192.168.113.211)(MySQL 3306、3307端口用于搜索查询,3406端口用于建索引),dbsearch为NetScaler虚拟IP 192.168.113.163(做db9的3306,db11的3306、3307负载均衡)的hosts。

 

2、搜索引擎架构设计思路:

⑴、调用方式最简化:

尽量方便前端Web工程师,只需要一条简单的SQL语句“SELECT ... FROM ... JOIN ... ON (...=...) WHERE query='...';”即可实现高效搜索。

⑵、创建索引、查询速度快:

①、Sphinx Search 是由俄罗斯人Andrew Aksyonoff 开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行。

Sphinx的特征:

·Sphinx支持高速建立索引(可达10 MB/秒,而Lucene建立索引的速度是1.8MB/秒)

·高性能搜索(在2-4 GB的文本上搜索,平均0.1秒内获得结果)

·高扩展性(在单一CPU上,实测最高可对100GB的文本建立索引,单一索引可包含1亿条记录)

·支持分布式检索

·支持基于短语和基于统计的复合结果排序机制

·支持任意数量的文件字段(数值属性或全文检索属性)

·支持不同的搜索模式(“完全匹配”,“短语匹配”和“任一匹配”)

·支持作为Mysql的存储引擎

 

②、通过国外《High Performance MySQL》专家组的测试可以看出,根据主键进行查询的类似“SELECT ... FROM ... WHERE id = ...”的SQL语句(其中id为PRIMARY KEY),每秒钟能够处理10000次以上的查询,而普通的SELECT查询每秒只能处理几十次到几百次:

 

 

③、Sphinx不负责文本字段的存储。假设将数据库的id、date、title、body字段,用sphinx建立搜索索引。根据关键字、时间、类别、范围等信息查询一下sphinx,sphinx只会将查询结果的ID号告诉我们。要显示title、body等信息,还需要根据此ID号去查询MySQL数据库,或者从Memcachedb等其他的存储中取得。安装SphinxSE作为MySQL的存储引擎,将MySQL与Sphinx结合起来,是一种便捷的方法。

创建一张Sphinx类型表,将MyISAM表的主键ID和Sphinx表的ID作一个JOIN联合查询。这样,对于MyISAM表来所,只相当于一个WHERE id=...的主键查询,WHERE后的条件都交给Sphinx去处理,可以充分发挥两者的优势,实现高速搜索查询。

 

⑶、按服务类型进行分离:

为了保证数据的一致性,我在配置Sphinx读取索引源的MySQL数据库时,进行了锁表。Sphinx读取索引源的过程会耗费一定时间,由于MyISAM存储引擎的读锁和写锁是互斥的,为了避免写操作被长时间阻塞,导致数据库同步落后跟不上,我将提供“搜索查询服务”的和提供“索引源服务”的MySQL数据库进行了分开。监听3306端口的MySQL提供“搜索查询服务”,监听3406端口的MySQL提供“索引源服务”。

 

⑷、“主索引+增量索引”更新方式:

XX网的特征:发帖较为频繁;刚发完的帖被用户自己编辑、修改的可能性大;新发的帖会被编辑审核(删除、标记为中介等);两天以前的老帖变动性较小。

基于这个特征,我设计了Sphinx主索引和增量索引。对于前天17:00之前的记录建立主索引,每天凌晨自动重建一次主索引;对于前天17:00之后到当前最新的记录,间隔3分钟自动重建一次增量索引。

 

⑸、“Ext3文件系统+tmpfs内存文件系统”相结合:

为了避免每4分钟重建增量索引导致磁盘IO较重,从而引起系统负载上升,我将主索引文件创建在磁盘,增量索引文件创建在tmpfs内存文件系统“/dev/shm/”内。“/dev/shm/”内的文件全部驻留在内存中,读写速度非常快。但是,重启服务器会导致“/dev/shm/”内的文件丢失,针对这个问题,我会在服务器开机时自动创建“/dev/shm/”内目录结构和Sphinx增量索引。

 

⑹、中文分词词库:

XX网搜索引擎使用到的中文分词词库,为本人根据“百度早期中文分词库”+“搜狗拼音输入法细胞词库”+“XX网地标词库”+“LibMMSeg高频字库”综合处理而成。

 

 

二、MySQL+Sphinx+SphinxSE安装步骤:

1、安装python支持(以下针对CentOS系统,其他Linux系统请使用相应的方法安装)

yum install -y python python-devel

 

2、编译安装LibMMSeg(LibMMSeg是为Sphinx全文搜索引擎设计的中文分词软件包,其在GPL协议下发行的中文分词法,采用Chih-Hao Tsai的MMSEG算法。LibMMSeg在本文中用来生成中文分词词库。)

wget http://www.coreseek.com/uploads/sources/mmseg-0.7.3.tar.gz

tar zxvf mmseg-0.7.3.tar.gz

cd mmseg-0.7.3/

./configure

make 

make install

cd ../

 

3、编译安装MySQL 5.1.26-rc、Sphinx、SphinxSE存储引擎

wget http://blog.s135.com/soft/linux/nginx_php/mysql/mysql-5.1.26-rc.tar.gz

tar zxvf mysql-5.1.26-rc.tar.gz

 

wget http://www.sphinxsearch.com/downloads/sphinx-0.9.8-rc2.tar.gz

wget http://www.coreseek.com/uploads/sources/sphinx-0.98rc2.zhcn-support.patch

wget http://www.coreseek.com/uploads/sources/fix-crash-in-excerpts.patch

tar zxvf sphinx-0.9.8-rc2.tar.gz

cd sphinx-0.9.8-rc2/

patch -p1 < ../sphinx-0.98rc2.zhcn-support.patch

patch -p1 < ../fix-crash-in-excerpts.patch

cp -rf mysqlse ../mysql-5.1.26-rc/storage/sphinx

cd ../

 

cd mysql-5.1.26-rc/

sh BUILD/autorun.sh

./configure --with-plugins=sphinx --prefix=/usr/local/mysql-search/ --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile

make && make install

cd ../

 

cd sphinx-0.9.8-rc2/

CPPFLAGS=-I/usr/include/python2.4

LDFLAGS=-lpython2.4

./configure --prefix=/usr/local/sphinx --with-mysql=/usr/local/mysql-search

make

make install

cd ../

 

4、创建Sphinx索引文件和MySQL数据文件存放目录(/mysql/3306/data和/mysql/3406/data)

mkdir -p /usr/local/sphinx/var/data/beijing/house/

mkdir -p /usr/local/sphinx/var/data/shanghai/house/

mkdir -p /usr/local/sphinx/var/data/guangzhou/house/

mkdir -p /usr/local/sphinx/var/data/wuhan/house/

mkdir -p /usr/local/sphinx/var/data/nanjing/house/

mkdir -p /usr/local/sphinx/var/data/tianjin/house/

mkdir -p /usr/local/sphinx/var/data/shenzhen/house/

mkdir -p /usr/local/sphinx/var/data/qita/house/

 

mkdir -p /dev/shm/sphinx/var/data/beijing/house/

mkdir -p /dev/shm/sphinx/var/data/shanghai/house/

mkdir -p /dev/shm/sphinx/var/data/guangzhou/house/

mkdir -p /dev/shm/sphinx/var/data/wuhan/house/

mkdir -p /dev/shm/sphinx/var/data/nanjing/house/

mkdir -p /dev/shm/sphinx/var/data/tianjin/house/

mkdir -p /dev/shm/sphinx/var/data/shenzhen/house/

mkdir -p /dev/shm/sphinx/var/data/qita/house/

 

/usr/sbin/groupadd mysql

/usr/sbin/useradd -g mysql mysql

chmod +w /usr/local/mysql-search

chown -R mysql:mysql /usr/local/mysql-search

mkdir -p /mysql/3306/data

chmod +w /mysql/3306/data

mkdir -p /mysql/3307/data

chmod +w /mysql/3307/data

mkdir -p /mysql/3406/data

chmod +w /mysql/3406/data

chown -R mysql:mysql /mysql

#cp support-files/my-medium.cnf /mysql/3306/my.cnf

#cp support-files/my-medium.cnf /mysql/3307/my.cnf

#cp support-files/my-medium.cnf /mysql/3406/my.cnf

 

5、创建MySQL配置文件(以线上配置文件为准)

⑴、创建配置文件/mysql/3306/my.cnf(以db11的3306端口为例)

vi /mysql/3306/my.cnf

输入以下内容:

[client]

#password       = your_password

port            = 3306

socket          = /mysql/3306/mysql.sock

 

[mysqld_safe]

datadir = /mysql/3306/data

log-error = /mysql/3306/mysql_error.log

pid-file = /mysql/3306/mysql.pid

 

[mysqld]

port            = 3306

socket          = /mysql/3306/mysql.sock

skip-locking

#skip-slave-start

key_buffer = 2048M

max_allowed_packet = 2M

table_cache = 2048

sort_buffer_size = 2M

read_buffer_size = 2M

read_rnd_buffer_size = 16M

max_length_for_sort_data = 64

myisam_sort_buffer_size = 128M

thread_cache = 8

query_cache_size = 128M

# Try number of CPU's*2 for thread_concurrency

thread_concurrency = 8

#skip-name-resolve

max_connections = 1000

max_connect_errors = 1000

open_files_limit = 51200

ft_min_word_len = 1

 

concurrent_insert = 2

low_priority_updates = 1

slave-skip-errors = 1032,1062,126,1114,1146,1048,1396,1030

server-id       = 113306

#master-host     =   db1

#master-user     =   repl

#master-password =   slavepass

#master-port     =  3306

 

[mysqldump]

quick

max_allowed_packet = 16M

 

[mysql]

no-auto-rehash

# Remove the next comment character if you are not familiar with SQL

#safe-updates

 

[isamchk]

key_buffer = 256M

sort_buffer_size = 256M

read_buffer = 2M

write_buffer = 2M

 

[myisamchk]

key_buffer = 256M

sort_buffer_size = 256M

read_buffer = 2M

write_buffer = 2M

 

[mysqlhotcopy]

interactive-timeout

 

⑵、创建配置文件/mysql/3406/my.cnf(以db11的3406端口为例)

vi /mysql/3406/my.cnf

输入以下内容:

[client]

#password       = your_password

port            = 3406

socket          = /mysql/3406/mysql.sock

 

[mysqld_safe]

datadir = /mysql/3406/data

log-error = /mysql/3406/mysql_error.log

pid-file = /mysql/3406/mysql.pid

 

[mysqld]

port            = 3406

socket          = /mysql/3406/mysql.sock

skip-locking

#skip-slave-start

key_buffer = 512M

max_allowed_packet = 2M

table_cache = 1024

sort_buffer_size = 2M

read_buffer_size = 2M

read_rnd_buffer_size = 8M

max_length_for_sort_data = 64

myisam_sort_buffer_size = 64M

thread_cache = 8

query_cache_size = 32M

# Try number of CPU's*2 for thread_concurrency

thread_concurrency = 8

#skip-name-resolve

max_connections = 1000

max_connect_errors = 1000

open_files_limit = 51200

ft_min_word_len = 1

 

#low_priority_updates = 1

slave-skip-errors = 1032,1062,126,1114,1146,1048,1396,1030

server-id       = 113406

#master-host     =   db1

#master-user     =   repl

#master-password =   slavepass

#master-port     =  3306

 

[mysqldump]

quick

max_allowed_packet = 16M

 

[mysql]

no-auto-rehash

# Remove the next comment character if you are not familiar with SQL

#safe-updates

 

[isamchk]

key_buffer = 256M

sort_buffer_size = 256M

read_buffer = 2M

write_buffer = 2M

 

[myisamchk]

key_buffer = 256M

sort_buffer_size = 256M

read_buffer = 2M

write_buffer = 2M

 

[mysqlhotcopy]

interactive-timeout

 

6、制作一份MySQL Slave供搜索引擎使用

⑴、找一台MySQL从库,停止同步进程(SQL语句:stop slave;);

⑵、查看同步位置(SQL语句:show slave status\G),记录以下几项值:

                  Master_Host: db1

                  Master_User: repl

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000117

          Read_Master_Log_Pos: 822317949

⑶、可以使用导出、导入SQL的方法创建供搜索引擎使用的MySQL从库。对于MyISAM表,可以直接拷贝文件(此步骤略)。

⑷、启动搜索引擎专用MySQL数据库:

ulimit -SHn 500000

/bin/sh /usr/local/mysql-search/bin/mysqld_safe --defaults-file=/mysql/3406/my.cnf &

/bin/sh /usr/local/mysql-search/bin/mysqld_safe --defaults-file=/mysql/3306/my.cnf &

⑸、从命令行登录MySQL服务器(此步骤略)。

⑹、设置同步点,并启动同步(SQL语句如下):

CHANGE master TO master_host="db1", master_user="repl", master_password="slavepass", master_log_file="mysql-bin.000125", master_log_pos=111145646;

START SLAVE;

 

7、创建快捷启动、停止、重启、杀死MySQL进程的脚本(以db11的3306端口为例)

vi /mysql/3306/mysql

输入以下内容:

#!/bin/sh

 

mysql_port=3306

mysql_username="root"

mysql_password="i0705tsstyl"

 

function_start_mysql()

{

    printf "Starting MySQL...\n"

    /bin/sh /usr/local/mysql-search/bin/mysqld_safe --defaults-file=/mysql/${mysql_port}/my.cnf 2>&1 > /dev/null &

}

 

function_stop_mysql()

{

    printf "Stoping MySQL...\n"

    /usr/local/mysql-search/bin/mysqladmin -u ${mysql_username} -p${mysql_password} -S /mysql/${mysql_port}/mysql.sock shutdown

}

 

function_restart_mysql()

{

    printf "Restarting MySQL...\n"

    function_stop_mysql

    function_start_mysql

}

 

function_kill_mysql()

{

    kill -9 $(ps -ef | grep 'bin/mysqld_safe' | grep ${mysql_port} | awk '{printf $2}')

    kill -9 $(ps -ef | grep 'libexec/mysqld' | grep ${mysql_port} | awk '{printf $2}')

}

 

if [ "$1" = "start" ]; then

    function_start_mysql

elif [ "$1" = "stop" ]; then

    function_stop_mysql

elif [ "$1" = "restart" ]; then

function_restart_mysql

elif [ "$1" = "kill" ]; then

function_kill_mysql

else

    printf "Usage: /mysql/${mysql_port}/mysql {start|stop|restart|kill}\n"

fi

赋予脚本可执行权限:

chmod +x /mysql/3306/mysql

脚本执行方法:

/mysql/3306/mysql start

/mysql/3306/mysql stop

/mysql/3306/mysql restart

/mysql/3306/mysql kill

 

注:用同样的方法创建另一个shell脚本“/mysql/3406/mysql”,输入以上内容,将上文中用红色标注的MySQL端口3306换成3406

 

 

三、Sphinx配置:

1、生成Sphinx中文分词词库

mmseg -u unigram.txt

cp unigram.txt.uni /usr/local/sphinx/etc/uni.lib

⑴、词典的构造

mmseg -u unigram.txt

该命令执行后,将会产生一个名为unigram.txt.uni的文件,将该文件改名为uni.lib,完成词典的构造。需要注意的是,unigram.txt 必须为UTF-8编码。

 

⑵、词典文件格式

....

河 187

x:187

造假者 1

x:1

台北队 1

x:1

湖边 1

......

其中,每条记录分两行。其中,第一行为词项,其格式为:[词条]\t[词频率]。需要注意的是,对于单个字后面跟这个字作单字成词的频率,这个频率需要在大量的预先切分好的语料库中进行统计,用户增加或删除词时,一般不需要修改这个数值;对于非单字词,词频率处必须为1。第二行为占位项,LibMMSeg的用户只需要简单的在第二行处填"x:1"即可。

 

⑶、XX网搜索引擎的中文分词词库

XX网搜索引擎使用到的中文分词词库,为本人根据“百度早期中文分词库”+“搜狗拼音输入法细胞词库”+“XX网地标词库”+“LibMMSeg高频字库”综合处理而成。

 

(双击打开)

 

2、创建Sphinx主索引文件、增量索引文件存放目录

mkdir -p /usr/local/sphinx/var/data/beijing/house/

mkdir -p /usr/local/sphinx/var/data/shanghai/house/

mkdir -p /usr/local/sphinx/var/data/guangzhou/house/

mkdir -p /usr/local/sphinx/var/data/wuhan/house/

mkdir -p /usr/local/sphinx/var/data/nanjing/house/

mkdir -p /usr/local/sphinx/var/data/tianjin/house/

mkdir -p /usr/local/sphinx/var/data/shenzhen/house/

mkdir -p /usr/local/sphinx/var/data/qita/house/

 

mkdir -p /dev/shm/sphinx/var/data/beijing/house/

mkdir -p /dev/shm/sphinx/var/data/shanghai/house/

mkdir -p /dev/shm/sphinx/var/data/guangzhou/house/

mkdir -p /dev/shm/sphinx/var/data/wuhan/house/

mkdir -p /dev/shm/sphinx/var/data/nanjing/house/

mkdir -p /dev/shm/sphinx/var/data/tianjin/house/

mkdir -p /dev/shm/sphinx/var/data/shenzhen/house/

mkdir -p /dev/shm/sphinx/var/data/qita/house/

 

3、创建Sphinx配置文件(以db11为例)

vi /usr/local/sphinx/etc/sphinx.conf

输入以下内容(双击打开):

 

 

4、初始化sphinx.conf中配置的全部索引

/usr/local/sphinx/bin/indexer --all

如果searchd处于运行状态,则执行

/usr/local/sphinx/bin/indexer --all --rotate

 

5、创建两个shell脚本,一个用来创建主索引、一个用来创建增量索引。

⑴、主索引更新脚本

①、创建脚本build_main_index.sh:

vi /usr/local/sphinx/bin/build_main_index.sh

输入以下内容(双击打开):

 

 

②、赋予主索引更新脚本可执行权限:

chmod +x /usr/local/sphinx/bin/build_main_index.sh

 

③、每天凌晨定时重建主索引:

crontab -e

增加以下内容:

#每天凌晨4点19分重建一次搜索引擎的主索引

19 4 * * * /bin/sh /usr/local/sphinx/bin/build_main_index.sh

 

⑵、增量索引更新脚本

①、创建脚本build_delta_index.sh:

vi /usr/local/sphinx/bin/build_delta_index.sh

输入以下内容(双击打开):

 

 

②、赋予增量索引更新脚本可执行权限:

chmod +x /usr/local/sphinx/bin/build_delta_index.sh

 

③、每3分钟自动重建一次搜索引擎的增量索引:

crontab -e

增加以下内容:

#每3分钟自动重建一次搜索引擎的增量索引

0-57/3 * * * * /bin/sh /usr/local/sphinx/bin/build_delta_index.sh

 

6、启动Sphinx守护进程(searchd)

ulimit -SHn 500000

/usr/local/sphinx/bin/searchd

 

7、配置服务器开机启动时需要自动执行的命令(以db11为例)

vi /etc/rc.local

在最末尾添加以下内容:

#搜索引擎开机自动执行的命令(以下语句放在rc.local文件的最后)

ulimit -SHn 500000

/bin/sh /mysql/3406/mysql start

/bin/sh /mysql/3306/mysql start

/bin/sh /mysql/3307/mysql start

mkdir -p /dev/shm/sphinx/var/data/beijing/house/

mkdir -p /dev/shm/sphinx/var/data/shanghai/house/

mkdir -p /dev/shm/sphinx/var/data/guangzhou/house/

mkdir -p /dev/shm/sphinx/var/data/wuhan/house/

mkdir -p /dev/shm/sphinx/var/data/nanjing/house/

mkdir -p /dev/shm/sphinx/var/data/tianjin/house/

mkdir -p /dev/shm/sphinx/var/data/shenzhen/house/

mkdir -p /dev/shm/sphinx/var/data/qita/house/

#/usr/bin/nohup /bin/sh /usr/local/sphinx/bin/build_delta_index.sh 2>&1 > /dev/null &

#sleep 360

/bin/sh /usr/local/sphinx/bin/build_delta_index.sh  2>&1 > /dev/null

/usr/local/sphinx/bin/searchd

 

8、创建Sphinx存储引擎表: 

⑴、设置/etc/hosts

vi /etc/hosts

添加以下内容:

192.168.113.209      db9

192.168.113.211      db11

 

⑵、登录运行在3306端口的MySQL服务器(提供“搜索查询服务”):

/usr/local/mysql-search/bin/mysql -u root -p -S /mysql/3306/mysql.sock

 

⑶、创建数据库“Sphinx”和相对应的Sphinx表(SQL语句):

示例SQL:

CREATE DATABASE sphinx;

USE sphinx;

 

CREATE TABLE `beijing_house_buy_list` (

  `sphinx_id` INTEGER NOT NULL,

  `weight` INTEGER NOT NULL,

  `query` VARCHAR(3072) NOT NULL,

  INDEX(`query`)

) ENGINE=SPHINX DEFAULT CHARSET=latin1 CONNECTION='sphinx://127.0.0.1:3312/beijing_house_buy_list';

 

完整SQL(双击打开):

 

 

 

四、如何通过SQL语句调用搜索引擎:

1、搜索应用实例

⑴、XX网北京出租房搜索

SELECT * FROM beijing.house_rent_list JOIN sphinx.beijing_house_rent_list ON (beijing_house_rent_list.sphinx_id=house_rent_list.post_id) WHERE query='中关村;index=beijing_house_rent_list,beijing_house_rent_list_delta;mode=boolean;sort=time_segments:date;maxmatches=3200;offset=0;limit=3200;range=price,500,1000;filter=district_id,6;' LIMIT 0,32;

注1:“offset=0;limit=3200;”相当于“LIMIT 0,3200”

注2:“filter=district_id,6;”相当于“WHERE district_id = 6”

注3:“range=price,500,1000;”相当于“WHERE price >= 500 AND price <= 1000”,对于类似“WHERE price >= 5000”的查询,在搜索中请指定一个比较大的数来实现,比如“range=price,5000,99999999;”

注4:filterrange的条件值不能为负数。如果MySQL字段中有负数,将其转为正整数(例如在sphinx.conf中使用SELECT agent+10 AS agent FROM,在搜索时也将该项值加上10)。

 

⑵、XX网北京小区搜索

SELECT * FROM beijing.house_source JOIN sphinx.beijing_house_source ON (beijing_house_source.sphinx_id=house_source.id) WHERE query='中关村;index=beijing_house_source,beijing_house_source_delta;mode=boolean;sort=time_segments:post_at;maxmatches=3200;offset=0;limit=32;';

北京小区可用的条件post_at,agent,district_id,street_id,huxing_shi,price

 

①、普通SQL语句

SELECT title, id, huxing_shi, huxing_ting, huxing_wei,area,price,refresh_at as time, district_id, street_id, agent, xiaoqu FROM beijing.house_source WHERE district_id ='1' AND street_id ='9' AND agent ='0' AND price BETWEEN 0 AND 500000 AND huxing_shi ='2' AND ( xiaoqu LIKE '%金隅丽港城%' or xiaoqu_address LIKE '%金隅丽港城%' ) ORDER BY refresh_at DESC LIMIT 128,32;

 

②、以上SQL语句对应的Sphinx搜索SQL语句(相同颜色相对应)

SELECT title, id, huxing_shi, huxing_ting, huxing_wei,area,price,refresh_at as time, district_id, street_id, agent, xiaoqu FROM beijing.house_source JOIN sphinx.beijing_house_source ON (beijing_house_source.sphinx_id=house_source.id) WHERE query='金隅丽港城;index=beijing_house_source,beijing_house_source_delta;mode=boolean;sort=time_segments:refresh_at;maxmatches=3200;offset=128;limit=32;filter=district_id,1;filter=street_id,9;filter=agent,0;range=price,0,500000;filter=huxing_shi,2'

 

⑶、在指定字段中搜索(例如在字段“title”中搜索关键字“中关村”)

SELECT id, user_id, title, agent, refresh_at FROM sphinx.beijing_house_source_1 JOIN beijing.house_source_1 ON (beijing_house_source_1.sphinx_id=house_source_1.id) where query='@title 中关村;index=beijing_house_source_1,beijing_house_source_1_delta;mode=extended; sort=attr_desc:refresh_at;maxmatches=3200;offset=0;limit=32;';

 

2、SphinxSE存储引擎及SQL语法详细说明

SphinxSE 是一个可以编译进MySQL 5.x 版本的MySQL 存储引擎,它利用了该版本MySQL的插件式体系结构。SphinxSE 不能用于MySQL 4.x 系列,它需要MySQL 5.0.22 或更高版本;或MySQL 5.1.12 或更高版本。

 

尽管被称作 “存储引擎”,SphinxSE 自身其实并不存储任何数据。它其实是一个允许MySQL 服务器与searchd 交互并获取搜索结果的嵌入式客户端。所有的索引和搜索都发生在MySQL 之外。

 

要通过SphinxSE 搜索,您需要建立特殊的ENGINE=SPHINX 的 “搜索表”,然后使用 SELECT 语句从中检索,把全文查询放在WHERE 子句中。

 

让我们从一个create 语句和搜索查询的例子开始:

CREATE TABLE t1 

    id          INTEGER NOT NULL, 

    weight      INTEGER NOT NULL, 

    query       VARCHAR(3072) NOT NULL, 

    group_id    INTEGER, 

    INDEX(query) 

) ENGINE=SPHINX CONNECTION="sphinx://localhost:3312/test"; 

 

SELECT * FROM t1 WHERE query='test it;mode=any';

搜索表前三列的类型必须是INTEGER,INTEGER 和VARCHAR,这三列分别对应文档ID,匹配权值和搜索查询。查询列必须被索引,其他列必须无索引。列的名字会被忽略,所以可以任意命名。

 

额外的列的类型必须是INTEGER 或TIMESPTAMP 之一。它们必须与Sphinx 结果集中提供的属性按名称绑定,即它们的名字必须与sphinx.conf 中指定的属性名一一对应。如果Sphinx搜索结果中没有某个属性名,该列的值就为NULL.

 

特殊的 “虚拟”属性名也可以与SphinxSE 列绑定。但特殊符号@用_sph_代替。例如,要取得@group 和@count 虚属性,列名应使用_sph_group 和_sph_count 。

 

可以使用字符串参数CONNECTION 来指定用这个表搜索时的默认搜索主机、端口号和索引。

如果CREATE TABLE 中没有使用连接(connection)串,那么默认使用索引名 “*”(搜索所有索引)和localhost:3312。连接串的语法如下:

CONNECTION="sphinx://HOST:PORT/INDEXNAME"

默认的连接串也可以日后改变:

ALTER TABLE t1 CONNECTION="sphinx://NEWHOST:NEWPORT/NEWINDEXNAME"; 

 

也可以在查询中覆盖全部这些选项。

 

如例子所示,查询文本和搜索选项都应放在WHERE 子句中对query 列的限制中(即第三列),选项之间用分号分隔,选项名与选项值用等号隔开。可以指定任意数目的选项。可用的选项如下:

 

query —— 查询文本

 

mode —— 匹配模式.必须是 “all”,  “any”,  “phrase”,  “boolean” 或  “extended”之一,默认为 “All”

 

sort —— 匹配项排序模式 必须是 “relevance”, “attr_desc”, “attr_asc”,  “time_segments”或“extended”之一。除了“relevance”模式,其他模式中还必须在一个冒号后附上属性名(或“extended”模式中的排序子句)。

... WHERE query='test;sort=attr_asc:group_id';

... WHERE query='test;sort=extended:@weight desc, group_id asc'; 

 

offset —— 结果集中的偏移量,默认是0。

 

limit —— 从结果集中获取的匹配项数目,默认为20。

 

index —— 待搜索的索引:

... WHERE query='test;index=test1;';

... WHERE query='test;index=test1,test2,test3;';

 

minid, maxid —— 匹配文档ID的最小值和最大值

 

weights —— 逗号分隔的列表,指定Sphinx 全文数据字段的权值

... WHERE query='test;weights=1,2,3;';

 

filter, !filter —— 逗号分隔的列表,指定一个属性名和一系列可匹配的属性值:

# only include groups 1, 5 and 19

... WHERE query='test;filter=group_id,1,5,19;'; 

# exclude groups 3 and 11

... WHERE query='test;!filter=group_id,3,11;';

 

range, !range —— 逗号分隔的列表,指定一个属性名和该属性可匹配的最小值和最大值:

# include groups from 3 to 7, inclusive 

... WHERE query='test;range=group_id,3,7;'; 

 

# exclude groups from 5 to 25

... WHERE query='test;!range=group_id,5,25;';

 

maxmatches —— 此查询最大匹配的数量:

... WHERE query='test;maxmatches=2000;'; 

 

groupby —— 分组(group-by)函数和属性:

... WHERE query='test;groupby=day:published_ts;';

... WHERE query='test;groupby=attr:group_id;'; 

 

groupsort —— 分组(group-by)排序子句

... WHERE query='test;groupsort=@count desc;';

 

indexweights —— 逗号分隔的列表,指定一系列索引名和搜索时这些索引对应的权值

... WHERE query='test;indexweights=idx_exact,2,idx_stemmed,1;';

 

非常重要的注意事项:让Sphinx 来对结果集执行排序、过滤和切片(slice)要比提高大匹配项数量然后在MySQL 端用WHERE、ORDER BY 和LIMIT 子句完成对应的功能来得高效得多。这有两方面的原因。首先,Sphinx 对这些操作做了一些优化,比MySQL 效率更高一些。其次,searchd 可以打包更少的数据,SphinxSE 也可以传输和解包更少的数据。

 

除了结果集,额外的查询信息可以用SHOW ENGINE SPHINX STATUS 语句获得:

mysql> SHOW ENGINE SPHINX STATUS; 

+--------+-------+-------------------------------------------------+ 

| Type   | Name  | Status                                          |

+--------+-------+-------------------------------------------------+ 

| SPHINX | stats | total: 25, total found: 25, time: 126, words: 2 |

| SPHINX | words | sphinx:591:1256 soft:11076:15945                |

+--------+-------+-------------------------------------------------+ 

2 rows in set (0.00 sec)

 

可以对SphinxSE 搜索表和其他引擎的表之间使用JOIN,以下是一个例子,例中“documents”来自example.sql:

mysql> SELECT content, date_added FROM test.documents docs 

-> JOIN t1 ON (docs.id=t1.id) 

-> WHERE query="one document;mode=any";

+-------------------------------------+---------------------+ 

| content                             | docdate             |

+-------------------------------------+---------------------+ 

| this is my test document number two | 2006-06-17 14:04:28 |

| this is my test document number one | 2006-06-17 14:04:28 |

+-------------------------------------+---------------------+

2 rows in set (0.00 sec)

 

mysql> SHOW ENGINE SPHINX STATUS; 

+--------+-------+---------------------------------------------+ 

| Type   | Name  | Status                                      |

+--------+-------+---------------------------------------------+ 

| SPHINX | stats | total: 2, total found: 2, time: 0, words: 2 |

| SPHINX | words | one:1:2 document:2:2                        |

+--------+-------+---------------------------------------------+ 

2 rows in set (0.00 sec) 

 

关于Sphinx更多的信息请见其官方文档(英文):http://www.sphinxsearch.com/doc.html

 

 

(全文完)

 

 

你可能感兴趣的:(搜索引擎)