• 网搜索引擎架构设计



    目  录

    一、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

    (全文完)

  • 相关阅读:
    错误error: Exception at 0x613baa14, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)的解决办法
    android项目在eclipse下编译运行的问题
    关于Eigen库在Visual Studio2013中传参对齐报错问题
    实时控制软件设计大作业总结
    实时软件控制成员任务分配进度表
    实时控制软件设计第三次作业
    实时控制软件设计第二次作业
    实时软件控制设计第一次作业
    《构建之法:现代软件工程》第一章读书笔记
    组员名单
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2995430.html
Copyright © 2020-2023  润新知