zoukankan      html  css  js  c++  java
  • Sphinx+MySQL5.1x+SphinxSE+mmseg中文分词


     什么是Sphinx

    Sphinx 是一个全文检索引擎,一般而言,Sphinx是一个独立的搜索引擎,意图为其它应用提供快速、低空间占用、高结果相关度的全文搜索功能。Sphinx能够很easy的与SQL数据库和脚本语言集成。当前系统内置MySQL和PostgreSQL 数据库数据源的支持。也支持从标准输入读取特定格式的XML数据。通过改动源码。用户能够自行添加新的数据源(比如:其它类型的DBMS的原生支持)。

    Sphinx的特性

     快速的建立索引(在当代CPU上,峰值性能可达到10 MB/秒);

     高性能的搜索(在2 – 4GB 的文本数据上,平均每次检索响应时间小于0.1秒);

     可处理海量数据(眼下已知能够处理超过100 GB的文本数据, 在单一CPU的系统上可处理100 M 文档);

     提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;支持分布式搜索;

     provides documentexceprts generation;

     可作为MySQL的存储引擎提供搜索服务;

     支持布尔、短语、词语相似度等多种检索模式;

     文档支持多个全文检索字段(最大不超过32个);

     文档支持多个额外的属性信息(比如:分组信息。时间戳等);

     停止词查询;

     支持单一字节编码和UTF-8编码;

     原生的MySQL支持(同一时候支持MyISAM 和InnoDB);

           原生的PostgreSQL 支持.

     

    安装

    本文以CentOS5.5+mysql-5.1.55+sphinx-0.9.9(coreseek-3.2.14.tar.gz)为例介绍

    Sphinx+MySQL5.1x+SphinxSE存储引擎+mmseg中文分词搜索引擎架构搭建过程。

    1.安装MySQL+SphinxSE。进入软件包文件夹

    tar zxvfmysql-5.1.55.tar.gz

    tar zxvfsphinx-0.9.9.tar.gz

    cp -rsphinx-0.9.9/mysqlse/ mysql-5.1.55/storage/sphinx  à 把sphinx的源代码拷贝到mysql源代码中

    cdmysql-5.1.55

    ./BUILD/autorun.sh

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

    make

    make install

    #/usr/sbin/groupadd mysql

    #/usr/sbin/useradd -g mysql mysql

    # chmod +w/usr/local/webserver/mysql

    # chown -Rmysql:mysql /usr/local/webserver/mysql

    ①、创建MySQL数据库存放文件夹

    #---------------------------------+

    # mkdir -p /data0/mysql/3306/data/

    # chown -Rmysql:mysql /data0/mysql/

    #---------------------------------+

    ②、以mysql用户帐号的身份建立数据表:

    #---------------------------------+

    #/usr/local/webserver/mysql/bin/mysql_install_db--basedir=/usr/local/webserver/mysql --datadir=/data0/mysql/3306/data --user=mysql

    #---------------------------------+
    ③、创建my.cnf配置文件:

    #--------------------------------+

    # vi /data0/mysql/3306/my.cnf

    #--------------------------------+

    my.cnf输入下面内容:

    [client]

    default-character-set= utf8

    port = 3306

    socket =/tmp/mysql.sock

    [mysql]

    no-auto-rehash

    [mysqld]

    user = mysql

    port = 3306

    socket =/tmp/mysql.sock

    basedir =/usr/local/webserver/mysql

    datadir =/data0/mysql/3306/data

    open_files_limit= 10240

    back_log = 600

    max_connections= 3000

    max_connect_errors= 6000

    table_cache =614

    external=locking= FALSE

    max_allowed_packet= 32M

    sort_buffer_size= 2M

    join_buffer_size= 2M

    thread_cache_size= 300

    thread_concurrency= 8

    query_cache_size= 32M

    query_cache_limit= 2M

    query_cache_min_res_unit= 2k

    default-storage-engine= MyISAM

    default_table_type= MyISAM

    thread_stack =192K

    transaction_isolation= READ-COMMITTED

    tmp_table_size= 246M

    max_heap_table_size= 246M

    long_query_time= 1

    log_long_format

    log-bin = /data0/mysql/3306/binlog

    binlog_cache_size = 4M

    binlog_format= MIXED

    max_binlog_cache_size= 8M

    max_binlog_size= 512M

    expire_logs_days= 7

    key_buffer_size= 256M

    read_buffer_size= 1M

    read_rnd_buffer_size= 16M

    bulk_insert_buffer_size= 64M

    myisam_sort_buffer_size= 128M

    myisam_max_sort_file_size= 10G

    myisam_repair_threads= 1

    myisam_recover

    skip-name-resolve

    master-connect-retry= 10

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

    server-id = 1

    [mysqldump]

    quick

    max_allowed_packet= 32M

    #--------------------------------开启MYSQL: ---------------+

    /usr/local/webserver/mysql/bin/mysqld_safe--defaults-file=/data0/mysql/3306/my.cnf 2>&1 > /dev/null & 

    #-----------------------------------------------------------+

    #--------------------------------关闭MYSQL: ---------------+

    /usr/local/webserver/mysql/bin/mysqladmin-u root -p -S /tmp/mysql.sock shutdown

    #-----------------------------------------------------------+

    ⑦、通过命令行登录管理MySQLserver(提示输入password时直接回车):

    #----------------------------------------------------------------+

    #/usr/local/webserver/mysql/bin/mysql -u root -p -S /tmp/mysql.sock

    #----------------------------------------------------------------+

    安装完毕启动MySQL后查看sphinx存储引擎是否成功安装

    在mysql命令行下运行

    show engines;

    假设出现例如以下图红色方框内的信息说明SphinxSE已经成功安装!

    安装Sphinx全文检索server

    Sphinx默认不支持中文索引及检索, 曾经用Coreseek的补丁来解决,眼下Coreseek 不单独提供补丁文件,而基于sphinx开发了Coreseek 全文检索server。Coreseek应该是如今用的最多的sphinx中文全文检索,它提供了为Sphinx设计的中文分词包LibMMSeg包括mmseg中文分词,事实上coreseek-3.2.14.tar.gz中已经包括了sphinx。前面安装SphinxSE时也能够使用这个压缩包里的mysqlse。

    我们来看一下的安装过程:

    安装autoconf

    Bzip2 –dautoconf-2.65.tar.bz2

    tar xvfautoconf-2.65.tar

    cdautoconf-2.65

    ./configure--prefix=/usr

    make

    make install

    cd ..

    安装Coreseek

    tar zxvfcoreseek-3.2.14.tar.gz

    cdcoreseek-3.2.14

    cdmmseg-3.2.14/

    ./bootstrap

    ./configure--prefix=/usr/local/mmseg3

    make

    make install

    cd../csft-3.2.14/

    shbuildconf.sh

    ./configure--prefix=/usr/local/coreseek --without-python --without-unixodbc --with-mmseg--with-mmseg-includes=/usr/local/mmseg3/include/mmseg/--with-mmseg-libs=/usr/local/mmseg3/lib/--with-mysql=/usr/local/webserver/mysql --host=arm

    make

    make install

    ln -s/usr/local/webserver/mysql/lib/mysql/libmysqlclient.so.16 /usr/lib

    cd/usr/local/coreseek/etc

    进入配置文件夹通过命令ls能够看到3个文件

    example.sql  sphinx.conf.dist  sphinx-min.conf.dist

    当中example.sql是演示样例sql脚本我们将其导入到数据库中的test数据库中作为測试数据(会创建两张表 documents和tags)

    vi sphinx.conf

    输入下面内容

    # 定义一个数据库源,名字为src1

    source src1

    {

         type                     =mysql

         sql_host                = localhost

         sql_user                = root

         sql_pass                =

         sql_db                      =test

         sql_port                = 3306   #optional, default is 3306

         sql_sock                              = /tmp/mysql.sock

         sql_query_pre           = SET NAMES utf8

         sql_query                =

              SELECTid,title,content FROM songs

         sql_query_info               = SELECT * FROM songs WHERE id=$id

    }

     

    # 定义建立索引项

    index test1

    {

         source                       =src1

         path                     =/usr/local/coreseek/var/data/test1

        charset_type             = zh_cn.utf-8

         charset_dictpath        = /usr/local/mmseg3/etc/

    }

     

    # 建索引程序的设置

    indexer

    {

        # 建索引时所用的内存限制

         mem_limit                = 32M

    }

     

    # 提供服务的进程配置

    searchd

    {

         port                     =9312

         log                           = /usr/local/coreseek/var/log/searchd.log

         query_log                = /usr/local/coreseek/var/log/query.log

         read_timeout            = 5

         max_children            = 30

         pid_file                = /usr/local/coreseek/var/log/searchd.pid

         max_matches                  = 1000

         seamless_rotate              = 1

         preopen_indexes              = 0

         unlink_old                   = 1

    }

    说明:

    代码段source src1{***} 代表数据源里面主要包括了数据库的配置信息,src1表示数据源名字,能够随便写。

    代码段index test1{***} 代表为哪个数据源创建索引,与source *** 是成对出现的,当中的source參数的值必须是某一个数据源的名字。

    其它參数能够查看手冊,这里不再赘述。

    生成索引

    /usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/sphinx.conf --all

    当中參数--all表示生成全部索引

    当然也能够是索引的名字比如:/usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/sphinx.conf test1

    运行后能够在/usr/local/coreseek/var/data文件夹中看到多出一些文件,是以索引名为文件名称的不同的扩展名的文件

    在不启动sphinx的情况下就可以測试命令:

      /usr/local/coreseek/bin/search -c/usr/local/coreseek/etc/sphinx.conf number

    能够看到将内容中含有number数据的数据查询出来。

    /usr/local/coreseek/bin/search-c /usr/local/coreseek/etc/sphinx.conf 研究生创业

    能够看到我们输入的查询文字已经被拆分成了两个词。仅仅是由于我们的測试数据中没有中文数据查询结果为空。

    我们插入几条新数据。

    INSERT INTO`test`.`documents` (

    `id` ,

    `group_id` ,

    `group_id2` ,

    `date_added` ,

    `title` ,

    `content`

    )

    VALUES (

    NULL , '2','3', '2011-02-01 00:37:12', '研究生的故事', '研究生自主创业'

    ), (

    NULL , '1','1', '2011-01-28 00:38:22', '研究', '为了创业而研究生命科学'

    );

    我们再来看下面数据库中的主要数据

    插入新数据后须要又一次生成索引

    /usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/sphinx.conf test1

    然后运行查询測试/usr/local/coreseek/bin/search -c /usr/local/coreseek/etc/sphinx.conf 研究生创业

    我们搜索的词语是“研究生创业”,能够看到词语被拆分成了研究生和创业两个词,尽管有两条记录都包括“创业和”研究生”这几个字可是“研究生命科学”中的“研究生”三个字尽管是紧挨着的可是不是一个词语,结果是仅仅匹配一条“研究生自主创业”,我们再搜索“研究”这个词语

    /usr/local/coreseek/bin/search-c /usr/local/coreseek/etc/sphinx.conf 研究

    相同匹配一条记录。而“研究生的故事”和“研究生自主创业”的词语却没有被查询出来,能够看出sphinx与分词技术结合能够匹配出相关度更高的结果。

    当然我们的目的不仅限与命令行下的測试,我们能够通过搜索API调用来运行搜索。搜索API支持PHP、Python、Perl、Rudy和Java。假设从PHP脚本检索须要先启动守护进程searchd。PHP脚本须要连接到searchd上进行检索:

    /usr/local/coreseek/bin/searchd-c /usr/local/coreseek/etc/sphinx.conf

    在解压后的sphinx-0.9.9/api文件夹下的sphinxapi.php就是sphinx官方为我们提供的API文件(事实上也能够使用PHP的sphinx扩展),仅仅需将其包括进自己的PHP脚本文件就能够了。

    演示样例代码:

    <?

    php

    include('sphinxapi.php');

      $cl = new SphinxClient();

      //设置sphinxserver地址与port,假设是本机则能够为localhost

      $cl->SetServer( "192.168.16.6", 9312 );

      //下面设置用于返回数组形式的结果

     $cl->SetArrayResult ( true );

     //$cl->SetMatchMode( SPH_MATCH_ANY  );//匹配模式

     //$cl->SetFilter( 'group_id', array( 2 ) );

      $result = $cl->Query( '研究生创业', 'test1' );  //參数 keyword  索引名

      if ( $result === false ) {

          echo "Query failed: " . $cl->GetLastError() . ". ";

      }

      else {

          if ( $cl->GetLastWarning() ) {

              echo "WARNING: " . $cl->GetLastWarning() . "";

          }

      

              echo '<pre>';

              print_r( $result );

      }

     ?>

    运行后的结果:

    Array

    (

        [error] =>

        [warning] =>

        [status] => 0

        [fields] => Array

            (

                [0] => title

                [1] => content

            )

        [attrs] => Array

            (

                [group_id] => 1

                [date_added] => 2

            )

        [matches] => Array

            (

                [5] => Array

                    (

                        [weight] => 2

                        [attrs] => Array

                            (

                                [group_id] => 2

                                [date_added] =>1296491832

                            )

                    )

            )

        [total] => 1

        [total_found] => 1

        [time] => 0.078

        [words] => Array

            (

                [研究生] =>Array

                    (

                        [docs] => 1

                        [hits] => 2

                    )

                [创业] =>Array

                   (

                        [docs] => 2

                        [hits] => 2

                    )

            )

    )

    在matches中的就是查询结果。我们注意到sphinx是将记录中的主键ID值返回而不是返回全部数据。上面的样例中的键名5就是记录的ID(假设在查询前运行$cl->SetArrayResult( true );则数组结构会有些许差异)。至此搜索server已经为我们完毕了大部分工作。接下来我们通过主键ID值来查询我们想要的数据就能够了。

    Sphinx存储引擎的使用

    SphinxSE是一个能够编译进MySQL 5.x版本号的MySQL存储引擎。它利用了该版本号MySQL的插件式体系结构。虽然被称作“存储引擎”。SphinxSE自身事实上并不存储不论什么数据。它事实上是一个同意MySQLserver与searchd交互并获取搜索结果的嵌入式client。全部的索引和搜索都发生在MySQL之外。

    SphinxSE的适用于:

     使将MySQL FTS 应用程序移植到Sphinx

     使没有Sphinx API的那些语言也能够使用Sphinx

     当须要在MySQL端对Sphinx结果集做额外处理(比如对原始文档表做JOIN,MySQL端的额外过滤等等)时提供优化。

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

    创建一张表sphinx表(用来连接MYSQL和SPHINX)

    CREATE TABLEt1

    (

        id         INTEGER UNSIGNED NOT NULL,

        weight     INTEGER NOT NULL,

        query      VARCHAR(3072) NOT NULL COMMENT ‘查询的单词’,

        group_id   INTEGER,

        INDEX(query) COMMENT ‘必需要给query字段建一个索引’

    ) ENGINE=SPHINX CONNECTION="sphinx://localhost:9312/songs";

    SELECT b.*

    FROM t1a,curl_songs b WHERE a.id=b.id AND query=’冬天的雪’

    搜索表前三列的类型必须是INTEGER,INTEGER和VARCHAR。这三列分别相应文档ID,匹配权值和搜索查询。查询列必须被索引。其它列必须无索引。列的名字会被忽略,所以能够随意命名,參数CONNECTION来指定用这个表搜索时的默认搜索主机、port号和索引,语法格式:CONNECTION="sphinx://HOST:PORT/INDEXNAME"。

    运行SQL语句

    查询出全部冬天的雪的记录:

    SELECT  a.*

     FROM curl_songs a,t1 b

      WHERE a.id=b.id AND b.query=”冬天的雪”

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

    | id |title              | content               |

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

    |  5 | 研究生的故事 | 研究生自主创业 |

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

    1 row in set(0.04 sec)

    结果返回了我们想要的数据,可见利用SphinxSE能够只在SQL语句上做非常小的修改就可以非常方便的实现全文检索。

    主索引 + 增量索引

         前提:数据不会被改变

         第一步:建表: (用来存索引过的最大的记录 id)

                   Create table a

    {

                        Idint unsigned not null primary key,

                        Max_id  int unsigned,

    }

         第二步:改动配置文件为:见 sphinx配置文件.doc

         第三步:先运行./bin/indexer –c ./etc/sphinx.conf –test1 生成全部的索引-〉一个数据源的主查询,仅仅有第一次运行

         第四步:定期运行:./bin/indexer–c  ./etc/sphinx.conf delta --rotate  à 生成增量的索引文件

         第五步:合并到主索引中./bin/indexer –merge test1 delta –c ./etc/sphinx.conf --rotate

  • 相关阅读:
    SICP习题 1.11 (一个函数的递归与迭代)
    SICP 实例 ExchangeMoney
    SICP 1.2.2 树形递归 与 线性迭代(斐波那契数)
    SICP习题 1.10(Ackermann函数)
    SICP习题 1.9 (递归与迭代初探)
    SICP实例 1.2.1 (阶乘的递归与迭代)
    SICP习题 1.8 (立方根)
    SICP习题 1.7 (求平方根改进)
    SICP习题 1.6 (再探 函数 与 正则序 应用序 关系)
    SICP实例 1.1.7 (求平方根)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5093353.html
Copyright © 2011-2022 走看看