运维/工具

开发笔记

Centos更改成阿里和网易的源

<ol><li>先备份自已的源:     /etc/yum.repos.d/ 
</li><li>Centos 5.X 安装阿里或者网易的源</li></ol>
<pre style="max-width:100%;overflow-x:auto;">wget -O /etc/yum.repos.d/CentOS-Base.repo http:<span class="hljs-comment">//mirrors.aliyun.com/repo/Centos-5.repo 这个是阿里的源</span>

wget http:<span class="hljs-comment">//mirrors.163.com/.help/CentOS5-Base-163.repo 这个是网易的</span></pre><p> </p><p>     3.Centos 6.X 安装阿里或者网易的源</p>
<pre style="max-width:100%;overflow-x:auto;">wget -O /etc/yum.repos.d/CentOS-Base.repo http:<span class="hljs-comment">//mirrors.aliyun.com/repo/Centos-6.repo 这个是6.X的阿里源</span>

wget http:<span class="hljs-comment">//mirrors.163.com/.help/CentOS6-Base-163.repo 这个是网易的6.x的源</span></pre><p>4.
下载成功以后执行yum clean all
命令,然后执行yum makecache
命令,当yum makecache完成以后,源就安装完了</p><p>
</p>

Linux网络基本网络配置

<p>linux操作系统中,以太网用“eth”表示;eth0:代表第一块以太网卡,eth1:第二块以太网卡。。。</p><h3>查看网卡相关信息:</h3><p># lspci | grep -i eth</p><p>02:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 0c)</p><h3>关闭networkmanager服务</h3><blockquote><p>桌面网络会自动更新,固定IP时这个功能很讨厌</p></blockquote>
<pre style="max-width:100%;overflow-x:auto;"> # rpm -qa | grep -i network

NetworkManager-glib-0.8.1-99.el6.x86_64  
system-config-network-tui-1.6.0.el6.2-1.el6.noarch  
glib-networking-2.28.6.1-2.2.el6.x86_64  
NetworkManager-0.8.1-99.el6.x86_64  
NetworkManager-gnome-0.8.1-99.el6.x86_64  

# chkconfig --list | grep -i network  
NetworkManager  0:off   1:off   2:on    3:on    4:on    5:on    6:off  
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off  

# ps -ef | grep NetworkManager  
root     30004 29978  0 19:04 pts/1    00:00:00 grep NetworkManager  

# service NetworkManager status  
NetworkManager is stopped  </code></pre><h3>查看网卡是否已经连接好</h3><p>#&nbsp;mii-tool&nbsp;eth0</p><p>eth0:&nbsp;negotiated&nbsp;100baseTx-FD&nbsp;flow-control,&nbsp;link&nbsp;ok</p><br><h3>查看ip相关信息:</h3><p>ifconfig&nbsp;</p><p>-a&nbsp;查看所有网卡信息</p><p>ifconfig&nbsp;eth0&nbsp;&nbsp;查看单个网卡信息</p><p>临时给网卡配置IP地址(网络重启失效)</p><p>#&nbsp;ifconfig&nbsp;eth0&nbsp;192.168.5.1&nbsp;netmask&nbsp;255.255.255.0</p><p>临时给网卡配置子接口</p><p>#&nbsp;ifconfig&nbsp;eth0:0&nbsp;10.12.1.110&nbsp;netmask&nbsp;255.255.255.0</p><p>临时关闭和启动网卡</p><p>#&nbsp;ifconfig&nbsp;eth0&nbsp;down</p><p>#&nbsp;ifconfig&nbsp;eth0&nbsp;up</p><br><p>永久关闭网卡或者激活网卡</p><p>ifdown&nbsp;eth0</p><p>ifup&nbsp;eth0</p><h3>自动获取IP地址</h3><p>#&nbsp;dhclient&nbsp;</p><br><p>重启网络:</p><p>service&nbsp;network&nbsp;restart(重启)|start(启动)|stop(停止)|reload(重新加载)</p><p>或者</p><p>/etc/init.d/network&nbsp;restart</p><br><p>ping&nbsp;命令:</p><p>ping&nbsp;服务器IP</p><p>ctrl+c结束</p><br><p>ping&nbsp;-c&nbsp;3&nbsp;服务器IP</p><br><p>默认情况下回显开启</p><p>#&nbsp;cat&nbsp;/proc/sys/net/ipv4/icmp_echo_ignore_all&nbsp;</p><p>0&nbsp;&nbsp;代表开启回显</p><p>#&nbsp;echo&nbsp;1&nbsp;&gt;&nbsp;/proc/sys/net/ipv4/icmp_echo_ignore_all&nbsp;</p><p>#&nbsp;cat&nbsp;/proc/sys/net/ipv4/icmp_echo_ignore_all&nbsp;</p><p>1&nbsp;&nbsp;代表关闭回显信息</p><br><p>NetworkManager&nbsp;服务:</p><p>作用:是redhat6自带的一个检测网络的图形化的工具,干扰网络配置。如:dns经常被刷新。</p><br><p>#&nbsp;service&nbsp;NetworkManager&nbsp;status&nbsp;查看服务运行状态</p><p>NetworkManager&nbsp;(pid&nbsp;&nbsp;2116)&nbsp;is&nbsp;running...</p><p>#&nbsp;service&nbsp;NetworkManager&nbsp;stop&nbsp;&nbsp;立刻关闭服务</p><p>Stopping&nbsp;NetworkManager&nbsp;daemon:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;&nbsp;OK&nbsp;&nbsp;]</p><p>#&nbsp;chkconfig&nbsp;NetworkManager&nbsp;off&nbsp;&nbsp;开机不自动启动</p><br><p>#&nbsp;chkconfig&nbsp;--level&nbsp;35&nbsp;NetworkManager&nbsp;off&nbsp;&nbsp;在第3和5级别开机不自动起来</p><p>#&nbsp;chkconfig&nbsp;--list|grep&nbsp;NetworkManager</p><p>NetworkManager&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0:off&nbsp;&nbsp;&nbsp;&nbsp;1:off&nbsp;&nbsp;&nbsp;&nbsp;2:on&nbsp;&nbsp;&nbsp;&nbsp;3:off&nbsp;&nbsp;&nbsp;&nbsp;4:on&nbsp;&nbsp;&nbsp;&nbsp;5:off&nbsp;&nbsp;&nbsp;&nbsp;6:off</p><br><p>配置静态IP地址:</p><p>物理机IP:192.168.5.11~192.168.5.100</p><p>虚拟机IP:192.168.5.111~192.168.5.200</p><p>方法一:</p><p>setup</p><br><p>重启网络</p><p>service&nbsp;network&nbsp;restart</p><br><p>方法二:</p><h3>跟网络相关的配置文件:</h3><p>/etc/sysconfig/network-scripts/ifcfg-eth0&nbsp;&nbsp;网卡局部配置文件</p><p>/etc/sysconfig/network&nbsp;&nbsp;全局配置文件</p><p>/etc/resolv.conf&nbsp;&nbsp;指定DNS服务器</p><p>/etc/hosts&nbsp;&nbsp;主机名解析</p><br><pre style="max-width:100%;overflow-x:auto;"><code class="javascript hljs" codemark="1">vim /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0 #设备名
HWADDR=<span class="hljs-number">00</span>:<span class="hljs-number">0</span>c:<span class="hljs-number">29</span>:f4:<span class="hljs-number">3</span>d:<span class="hljs-number">41</span> #MAC地址
TYPE=Ethernet #网卡类型,以太网卡
UUID=<span class="hljs-number">641e54</span>ea<span class="hljs-number">-21</span>ce<span class="hljs-number">-4</span>d06<span class="hljs-number">-8708</span>-f31e16ebfce1 #UUID,唯一
ONBOOT=no #代表系统重启不激活网卡;yes代表激活网卡
NM_CONTROLLED=yes #受NetworkManager服务影响
BOOTPROTO=none #none即可以是动态也可以是静态;dhcp代表动态获取IP;<span class="hljs-keyword">static</span>代表静态IP
IPADDR=<span class="hljs-number">192.168</span><span class="hljs-number">.5</span><span class="hljs-number">.1</span> #IP地址
NETMASK=<span class="hljs-number">255.255</span><span class="hljs-number">.255</span><span class="hljs-number">.0</span> #子网掩码
GATEWAY=<span class="hljs-number">192.168</span><span class="hljs-number">.5</span><span class="hljs-number">.254</span> #网关
DNS1=<span class="hljs-number">192.168</span><span class="hljs-number">.5</span><span class="hljs-number">.254</span> #dns
IPV6INIT=no
USERCTL=no #是否允许除了root以外的用户重启网络
</pre><h3>设定主机名</h3><p>FQDN(完全规范的主机名),用"."作为分割符</p><span>www.baidu.com</span><p>   主机头.域.域</p><p>node1.uplook.com</p><p>test.com</p><p>webserver  不规范</p>
<p>查看主机名:</p><p>hostname </p><p>或者</p><p>uname -n</p>
<h3>临时更改主机名:</h3><p>hostname db.test.com</p><p>需要退出重新登录,操作系统重启失效</p>
<p>永久更改主机名:</p>
<p>vim /etc/sysconfig/network</p>
<p>NETWORKING=yes  是否启用网络功能(no意味着使用service network start没有任何反映)</p><p>HOSTNAME=vm1.uplook.com  定义主机名,需要重启操作系统生效</p><p>GATEWAY=192.168.5.254 也可以定义默认网关,如果和子配置文件冲突,以子配置文件为准</p><h3>
</h3><h3>指定DNS服务器:</h3>
<p>vim /etc/resolv.conf</p><p>nameserver 192.168.5.254 DNS服务器的IP</p>
<p>/etc/hosts  主机名域名解析</p>
<p>127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4</p><p>::1         localhost localhost.localdomain localhost6 localhost6.localdomain6</p><p>192.168.5.1 node1.uplook.com node1</p><p>192.168.5.254 demo.example.com demo</p>
<p>说明:</p><p>前两行不要动,不要更改不要删除;在后面将IP地址和主机名一一对应起来</p>
<h3>总结:</h3><p>1、配置网络环境——>检查网线是否ok——>ping 127.0.0.1——>ifconfig——>ping 192.168.5.254——>检查网关——>关闭防火墙</p><p>重启网络测试,如果实在不行,可以尝试打开NetworkManager服务,自动连接。。。</p>
<p># route -n</p><p>Kernel IP routing table</p><p>Destination     Gateway         Genmask         Flags Metric Ref    Use Iface</p><p>192.168.5.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0</p><p>169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0</p><p>0.0.0.0         192.168.5.254   0.0.0.0         UG    0      0        0 eth0</p>
<h3>IP路由</h3><p>route -n 查看路由信息</p><p>route del default 删除默认路由</p><p>route add default gw 192.168.5.254 netmask 255.255.255.0 添加默认路由</p><p>route add -net 192.168.0.0/24 dev eth0 添加一个到目标网段的路由</p><p>route add -host 192.168.7.1 gw 192.168.5.254  添加一个到目标主机的路由</p>
<p>问题:</p><p>2个不同网段的虚拟机之间实现联通,怎么做?</p><p>开启路由转发功能:</p><p>echo 1 > /proc/sys/net/ipv4/ip_forward</p>
<h3>网络模式:</h3><p>VMnet0:用于桥接模式下的虚拟交换机</p><p>VMnet1:用于仅主机模式host-only模式下的虚拟交换机</p><p>VMnet8:用于虚拟NAT网络下的虚拟交换机</p>
<p>桥接模式:</p><p>NAT模式:</p><p>host-only:</p>
<p>虚拟机关闭防火墙:</p><p>service iptables stop</p><p>chkconfig iptables off</p>

<h3>
</h3><h3>虚拟机管理:</h3><p>1、虚拟机网络配置ok,yum源ok,做快照。</p><p>wget -P /etc/yum.repos.d/ ftp://192.168.5.254/demo.repo</p><p>yum clean all</p><p>yum makecache</p><p>2、克隆新虚拟机(克隆全新的虚拟机),需要关闭虚拟机</p><p>3、配置克隆后的虚拟机</p><p>1)主机名修改 eg:node2.uplook.com</p><p>2) 网络配置</p><p>   a、注释或者删除/etc/sysconfig/network-scripts/ifcfg-eth0文件中的MAC地址和UUID</p><p>   b、删除规则文件或者备份</p><p>mv /etc/udev/rules.d/70-persistent-net.rules /etc/udev/rules.d/70-persistent-net.rules.bak</p><p>   c、重启操作系统</p>
<p>
</p>

Web性能压力测试http_load

<p>http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载。</p><p>
但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会把客户机搞死。</p><p>
还可以测试HTTPS类的网站请求。</p><p>网站地址<span>http://acme.com/software/http_load/</span></p><pre style="max-width:100%;overflow-x:auto;">wget http://acme.com/software/http_load/http_load-09Mar2016.tar.gz

tar -zxvf http_load-09Mar2016.tar.gz
cd http_load-09Mar2016
make && make install
</pre><p>使用</p><p>
</p><pre style="max-width:100%;overflow-x:auto;">http_load -p 并发访问进程数 -s 访问时间 需要访问的URL文件
http_load -p30 -s 60 urllist.txt
</pre><p>
</p><p>
</p><pre style="max-width:100%;overflow-x:auto;">##测试HTTPS类网站</pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">#urllist.txt
https:<span class="hljs-comment">//jerryblog.cn/</span>
https:<span class="hljs-comment">//jerryblog.cn/cdn.html</span>
https:<span class="hljs-comment">//jerryblog.cn/jblog/index/cdn/cid/2.html</span>
https:<span class="hljs-comment">//jerryblog.cn/jblog/index/cdn/cid/3.html</span>
https:<span class="hljs-comment">//jerryblog.cn/jblog/tool/doc.html</span>
https:<span class="hljs-comment">//jerryblog.cn/b@MNgm6f918eY6f918e5.html</span>
</pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">
http_load --help
usage: http_load [-checksum] [-throttle] [-proxy host:port] [-verbose] [-timeout secs] [-sip sip_file]

        -parallel N | -rate N [-jitter]
        -fetches N | -seconds N
        url_file

One start specifier, either -parallel or -rate, is required.
One end specifier, either -fetches or -seconds, is required.

参数其实可以自由组合,参数之间的选择并没有什么限制。
比如你写成http_load -parallel 5 -seconds 300 urllist.txt也是可以的。
我们把参数给大家简单说明一下。
-parallel 简写-p :含义是并发的用户进程数。
-fetches 简写-f :含义是总计的访问次数
-rate 简写-p :含义是每秒的访问频率
-seconds 简写-s :含义是总计的访问时间
</pre><p>
</p>

虚拟机nginx 配置

server
{
    listen  80;
    listen  443       ssl;
    server_name  host;
    index index.html index.htm index.php;
    root  /data/public;
    ssl_certificate  cert/server.crt;
    ssl_certificate_key cert/server.key;
    #ssl on;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    error_page 497  https://$host$uri?$args;
   if ($request_uri ~ (.+?\.php)(|/.+)$ ){
        break;
    }


    if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php/$1 last;
    }

    location ~ .*\.php.*
    {
        include php_fcgi.conf;
        include pathinfo.conf;
        include fastcgi_params;
        fastcgi_param HTTPS on; # 多加这一句很重要
     }

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
        expires      30d;
    }

    location ~* \.(ini|sql|conf|bak)$ {
         return 404;
    }

    location ~* ^/(themes|images|logs|data|demo|wap_themes)/.*\.(php|php5)$ {
        deny all;
    }

    location ~ /\.(svn|git|)/ {
       deny all;
    }

    access_log /var/log/nginx/access.log access;
    #access_log off;
}

运维相关工具

系统运维 Grafana
日志处理 elk
mysql监控 zabbix

集群布署

  1. 1. 集群部署

## 1.1. 服务器说明(3web机情况,其他类似)

  • 本文档仅供参考,达到集群部署目的即可,不同运维都有自己的方案,生产环境的要求要复杂于以下文档,具体环境具体对待
  • 软件部署安装具体请参考 linux单机部署,集群部署可能不需按照单机部署那样所有软件都需要安装,根据服务器实际需要安装
  • 集群部署机器分配,由于机器有限,部分服务器同时用做多个服务
  • 实际情况下请根据自己的实际ip进行调整,包括各种配置中的都要根据您真实情况调整

    |机器 |功能 | 安装软件|说明 | |----|----|---| |192.168.10.228| 负载均衡机 | haproxy | 负载均衡服务器 | |192.168.10.229| web1 | nginx+php+rsync+inotify | 主web机,并且推送代码到从web机 | |192.168.10.230| web2 | nginx+php+rsync | 从web机 | |192.168.10.231| web3 | nginx+php+rsync | 从web机 | |192.168.10.232| memcached | memcached | 缓存服务器 | |192.168.10.232| redis | redis | redis服务器 | |192.168.10.232| NFS | nginx+nfs-utils | 资源,图片服务器 | |192.168.10.233| mysql主 | mysql | 主数据库 | |192.168.10.234| mysql从 | mysql | 从数据库 |

  • 关于一些配置文件以及相关目录说明

    | 名称 | 本次版本(2016.07) | 相关说明 | | :-------- | :----| :----- | | nginx | openresty/1.9.7.4 | 配置文件 /usr/local/nginx/conf/nginx.conf
    vhost配置文件 /usr/local/nginx/conf/vhosts/*.conf | | php | 5.6.19 | 配置文件 /usr/local/php56/etc/php.ini
    php 扩展配置文件目录 /usr/local/php56/etc/php.d/
    zend 配置文件 /usr/local/php56/etc/php.d/Zend.ini
    memcached 配置文件 /usr/local/php56/etc/php.d/memcached.ini| | mysql | 5.6.22 | basedir /usr/local/mysql
    datadir /data/mysql/3306
    配置文件 /usr/local/mysql/my.cnf | | redis | 3.0.3 | 配置文件 /etc/redis.conf | | memcached | 1.4.4 | 配置文件 /etc/sysconfig/memcached | | rsync+inotify | 1.4.4 | 配置文件 /etc/rsyncd.conf
    密码文件 /etc/rsyncd.passwd
    配合inotify监控脚本位置 /root/rsync.sh| | 代码目录 | - | /data/httpd |

## 1.2. MySQL主从安装配置

MySQL主192.168.10.233, MySQL从192.168.10.234

### 1.2.1. 主服务器和从服务器都安装MySQL

初始化yum源,将shopex-lnmp源加入到系统中,如果已经参照单机部署初始化过yum源了则省略此步骤

yum install wget -y
cd /etc/yum.repos.d/
wget http://mirrors.shopex.cn/shopex/shopex-lnmp/shopex-lnmp.repo

安装mysql

yum install mysql -y

启动MySQL

/etc/init.d/mysqld start

登录MySQL并且修改密码并且删除空用户

#这里设置 shopex123 为msyql登录密码
mysql&gt; UPDATE mysql.user SET password = PASSWORD('shopex123') WHERE user = 'root';
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0

mysql&gt; SELECT user,host,password FROM mysql.user;
+------+-----------------------+-------------------------------------------+
| user | host                  | password                                  |
+------+-----------------------+-------------------------------------------+
| root | localhost             | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | localhost.localdomain | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | 127.0.0.1             | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | ::1                   | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
|      | localhost             |                                           |
|      | localhost.localdomain |                                           |
+------+-----------------------+-------------------------------------------+
6 rows in set (0.00 sec)

mysql&gt; DROP user ''@localhost;
Query OK, 0 rows affected (0.00 sec)

mysql&gt; DROP user ''@localhost.localdomain;
Query OK, 0 rows affected (0.00 sec)

mysql&gt; SELECT user,host,password FROM mysql.user;
+------+-----------------------+-------------------------------------------+
| user | host                  | password                                  |
+------+-----------------------+-------------------------------------------+
| root | localhost             | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | localhost.localdomain | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | 127.0.0.1             | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | ::1                   | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
+------+-----------------------+-------------------------------------------+
4 rows in set (0.00 sec)

### 1.2.2. 配置

修改主服务器master192.168.10.233 vim /usr/local/mysql/my.cnf

[mysqld]
log-bin=mysql-bin   #[必须]启用二进制日志
server-id=1      #[必须]服务器唯一ID,默认是1,一般取IP最后一段

修改从服务器slave192.168.10.234 vim /usr/local/mysql/my.cnf

[mysqld]
log-bin=mysql-bin   #[不是必须]启用二进制日志
server-id=2      #[必须]服务器唯一ID,默认是1,一般取IP最后一段

重启两台服务器/etc/init.d/mysqld restart

登录master服务器,给Slave服务器授权

mysql&gt;  GRANT REPLICATION SLAVE ON *.* to 'root'@'192.168.10.234' identified by 'shopex123';
Query OK, 0 rows affected (0.00 sec)

mysql&gt;  SELECT user,host,password FROM mysql.user;
+------+-----------------------+-------------------------------------------+
| user | host                  | password                                  |
+------+-----------------------+-------------------------------------------+
| root | localhost             | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | localhost.localdomain | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | 127.0.0.1             | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | ::1                   | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
| root | 192.168.10.234        | *13EB6A5E957F69117458EF4E95776C9B0BB9FA75 |
+------+-----------------------+-------------------------------------------+
6 rows in set (0.00 sec)

查询主数据库状态

mysql&gt; show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      640 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

#这里需要记录 File 以及 Position 的值,在操作从服务器时会用到

配置Slave 服务器

# 登录mysql Slave 服务器
[root@localhost ~]# mysql -uroot -p
Enter password:

# 执行同步SQL语句
mysql&gt; change master to master_host='192.168.10.233',master_user='root',master_password='shopex123',master_log_file='mysql-bin.000001',master_log_pos=640;
Query OK, 0 rows affected (0.03 sec)

# 启动同步进程
mysql&gt; start slave;
Query OK, 0 rows affected (0.00 sec)

# 主从同步检查
mysql&gt; show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.10.233
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 640
               Relay_Log_File: localhost-relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 640
              Relay_Log_Space: 460
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: 4bbab569-4cb1-11e6-86f5-d4bed9a810af
             Master_Info_File: /data/mysql/3306/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
1 row in set (0.00 sec)
# 可以看到:Slave_IO_Running | Slave_SQL_Running两个值都是YES,说明配置成功了

主从服务器测试

# 主服务器Mysql,建立数据库,并在这个库中建表插入一条数据
mysql&gt; create database test_db;
Query OK, 1 row affected (0.00 sec)

mysql&gt; use test_db;
Database changed

mysql&gt;  create table test_tb(id int(3),name char(10));
Query OK, 0 rows affected (0.00 sec)

mysql&gt; insert into test_tb values(001,'test');
Query OK, 1 row affected (0.00 sec)

mysql&gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test_db                |
| mysql                |
| test                 |
+--------------------+
4 rows in set (0.00 sec)

# 从服务器查看
mysql&gt;  show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| test_db            |
+--------------------+
5 rows in set (0.00 sec)

mysql&gt; use test_db;
Database changed

mysql&gt; show tables;
+-------------------+
| Tables_in_test_db |
+-------------------+
| test_tb           |
+-------------------+
1 row in set (0.00 sec)

mysql&gt; select * from test_tb;
+------+------+
| id   | name |
+------+------+
|    1 | test |
+------+------+
1 row in set (0.00 sec)

### 1.2.3. 主web配置Mysql主从

MySQL主服务器给web服务器授权访问

GRANT ALL PRIVILEGES  ON *.* to 'root'@'192.168.10.229' identified by 'shopex123';

#### web服务器配置

修改数据库配置文件vim /data/httpd/config/production/database.php

/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
| 对应原系统: DB_*
|
*/

'connections' =&gt; array(
    #'default' =&gt; array(
    #    'driver'    =&gt; 'mysqli',
    #    'host'      =&gt; '192.168.10.233',
    #    'dbname'  =&gt; 'b2b2c',
    #    'user'  =&gt; 'root',
    #    'password'  =&gt; 'shopex123',
    #    'charset'   =&gt; 'utf8',
    #    //'collation' =&gt; 'utf8_general_ci',
    #),
    'default' =&gt; array(
        'master' =&gt; array('user' =&gt; 'root', 'password' =&gt; 'shopex123', 'host' =&gt; '192.168.10.233', 'dbname' =&gt; 'b2b2c','charset'   =&gt; 'utf8'),
        'slaves' =&gt; array(
            array('user' =&gt; 'root', 'password'=&gt;'shopex123', 'host' =&gt; '192.168.10.234', 'dbname' =&gt; 'b2b2c','charset'   =&gt; 'utf8'),
         ),
        'driver'    =&gt; 'mysqli',
    ),
),

## 1.3. 安装Redis

初始化yum源,将shopex-lnmp源加入到系统中,如果已经参照单机部署初始化过yum源了则省略此步骤

yum install wget -y
cd /etc/yum.repos.d/
wget http://mirrors.shopex.cn/shopex/shopex-lnmp/shopex-lnmp.repo
yum install epel-release -y

### 1.3.1. 安装

yum install redis -y

### 1.3.2. 配置

redis开启远程访问

vim /etc/redis.conf
注释掉绑定127.0.0.1的访问,则所有局域网都能访问
#bind 127.0.0.1

### 1.3.3. 启动

/etc/init.d/redis start

## 1.4. 安装Memcached

初始化yum源,将shopex-lnmp源加入到系统中,如果已经参照单机部署初始化过yum源了则省略此步骤

yum install wget -y
cd /etc/yum.repos.d/
wget http://mirrors.shopex.cn/shopex/shopex-lnmp/shopex-lnmp.repo
yum install epel-release -y

### 1.4.1. 安装

yum install memcached -y

### 1.4.2. 配置

配置文件位置/etc/sysconfig/memcached
可以修改内存大小等配置

### 1.4.3. 启动

/etc/init.d/memcached start

## 1.5. 静态资源服务器配置

通过NFS的方式将web服务器中的图片,模版,js登静态资源进行挂在到静态资源服务器,然后静态资源都通过该服务器进行调用

### 1.5.1. NFS安装

初始化yum源

将shopex-lnmp源加入到系统中,在线地址查看有哪些软件 <http://mirrors.shopex.cn/shopex/shopex-lnmp/> 可以安装

cd /etc/yum.repos.d/
wget http://mirrors.shopex.cn/shopex/shopex-lnmp/shopex-lnmp.repo

安装epel扩展源

yum install epel-release -y

web服务器和storage服务器都安装nfs

yum install nfs-utils -y

#根据Centos选择安装
yum install portmap -y #(适用centos 5)
yum install rpcbind -y #(适用centos 6)

启动NFS服务,启动顺序一定要先启动rpcbind,后在启动nfs

/etc/init.d/rpcbind start
/etc/init.d/nfs start

storage服务器都安装nginx

yum install ngx_openresty -y

### 1.5.2. NFS配置

将web服务器中已有的资源复制到storage服务器

scp -r /data/httpd/public/themes/ root@192.168.10.232:/data/httpd/
scp -r /data/httpd/public/images/ root@192.168.10.232:/data/httpd/
scp -r /data/httpd/public/app/ root@192.168.10.232:/data/httpd/

在storage服务器vim /etc/exports,加入如下参数

#可以使用*不限制挂载机器
#/data/httpd/themes  *(rw,sync,all_squash,anonuid=502,anongid=502)

/data/httpd/themes  192.168.10.229/24(rw,sync,all_squash,anonuid=502,anongid=502)
/data/httpd/images  192.168.10.229/24(rw,sync,all_squash,anonuid=502,anongid=502)
/data/httpd/app     192.168.10.229/24(rw,sync,all_squash,anonuid=502,anongid=502)

修改好执行命令exportfs -rv

查看是否成功

showmount -e 192.168.10.232
Export list for 192.168.10.232:
/data/httpd/app    192.168.10.229/24
/data/httpd/images 192.168.10.229/24
/data/httpd/themes 192.168.10.229/24
  • web服务器中静态资源挂载到storage服务器
mount 192.168.10.232:/data/httpd/themes /data/httpd/public/themes
mount 192.168.10.232:/data/httpd/images /data/httpd/public/images
mount 192.168.10.232:/data/httpd/app    /data/httpd/public/app

### 1.5.3. 解决跨域加载字体问题:firefox和IE9不支持对icon font字体的跨域访问

静态资源服务器修改nginx配置文件

vim /usr/local/nginx/conf/vhosts/default.conf

server {
    ...
    #在server中新增如果下配置
    location ~* \.(eot|ttf|woff)$ {
        add_header Access-Control-Allow-Origin *;
    }
    ...
}

新增 AddType

vim /usr/local/nginx/conf/mime.types

font/ttf                              ttf;
font/otf                              otf;

### 1.5.4. 主web配置

复制配置文件到production cp /data/httpd/config/storager.php /data/httpd/config/production/storager.php

修改配置文件vim /data/httpd/config/production/storager.php

    /*
    |--------------------------------------------------------------------------
    | 静态资源映象站地址(js css)
    |--------------------------------------------------------------------------
    |
    | 资源映像站地址
    |
    */
    'host_mirrors' =&gt; array(
        'http://192.168.10.232',
        //'http://img2.example.com',
    ),

    /*
    |--------------------------------------------------------------------------
    | 图片映象站地址
    |--------------------------------------------------------------------------
    |
    | 图片资源映像站地址
    | 一个域名标识对应一个域名,在替换的时候域名的时候替换对应的值就可以了
    | 图片域名标识不可变,添加后慎重删除,除非确保改标识下不存在图片了
    | 如果未配置则默认使用 defaultHostMirrors 作为图片标识
    */
    'host_mirrors_img' =&gt; [
        'img0'=&gt;'http://192.168.10.232',
        //'img1'=&gt;'http://img2.example.com',
    ],

## 1.6. web机代码同步,采取 rsync+inotify方式

说明:这里的配置是采取单向同步,采取 主web机 向 从web机 推送代码,如要双向同步,请自行配置

### 1.6.1. 安装配置 rsync (主web机和从web机 都需要安装)

  • 安装 rsync

      yum install rsync -y
  • 编辑 rsyncd.conf 配置文件,如果没有则创建一个,主web服务器也可以不配置此文档,但是为了统一也可以配置一下
  • 并且约定从web机中的rsyncd配置的用户名和密码全部一样,如rsyncd.passwd 中为rsync:123456,并且模块名也一样,如rsyncd.conf中为salve_web
  • 同步的时候注意防火墙问题可能导致无法同步

      vim /etc/rsyncd.conf
    
      #添加以下内容
  #rsync通用配置文件,配置的注释不要写在配置后面,否则会有问题

  uid = root
  gid = root
  use chroot = 0
  port = 873
  #允许ip访问设置,请根据实际需要进行配置,这里为了方便设为全网段 *,生产环境下为了安全请指定ip或ip段
  # hosts allow = 192.168.0.1/255.255.255.0 198.162.145.1 10.0.1.0/255.255.255.0
  hosts allow = *
  max connections = 0
  timeout = 300
  pid file = /var/run/rsyncd.pid
  lock file = /var/run/rsyncd.lock
  log file = /var/log/rsyncd.log
  log format = %t %a %m %f %b
  transfer logging = yes
  syslog facility = local3

  #方括号中为模块声明,对应命名,这里master_web对应了主web机配置,从服务器可都为[slave_web],方便inotify脚本配置
  [master_web]
  #指定当前模块在rsync服务器上的同步路径,该参数是必须指定的
  path = /data/httpd/
  #注释,可以同模块名一样,从服务器可都为slave_web
  comment = master_web
  ignore errors
  #是否允许客户端上传文件
  read only = no
  list = no
  #指定由空格或逗号分隔的用户名列表,只有这些用户才允许连接该模块
  auth users = rsync
  #保存密码和用户名文件,需要自己生成
  secrets file = /etc/rsyncd.passwd
  • 编辑 rsyncd.passwd 密码配置文件,如果没有则创建一个

      vim /etc/rsyncd.passwd
`注意:添加以下内容的时候,千万要看清楚,不要全部复制粘贴,分主web服务器和从web服务器`

```
  #从web服务器配置内容,需要填写 用户名:密码 ,多个用户名密码则每添加多行,建议从web机都是一样的用户名和密码

  rsync:123456

  #主web服务器配置内容,只需要填写从服务器的密码,例如这里从服务器配的用户名密码都是rsync:123456,这里主服务器则写123456一个就可以了

  123456
```
  • 修改密码文件 /etc/rsyncd.passwd 的权限为600

      #修改密码文件权限为600
      chmod 600 /etc/rsyncd.passwd
  • 启动 rsync 服务并设置开机自启动。下面两行分别执行,不要全部复制粘贴

      #以守护进程方式启动rsync服务
      /usr/bin/rsync --daemon --config=/etc/rsyncd.conf
    
      #添加开机自启动
      echo &quot;/usr/bin/rsync --daemon --config=/etc/rsyncd.conf&quot;&gt;&gt;/etc/rc.local
  • 验证代码是否能够同步, 在web服务器上执行下面命令,如有报错,请自行查找原因,

      # 主web服务器推送代码到从web服务器,命令中的
      # rsync@192.168.10.230::slave_web
      # 192.168.10.230 为从web服务器的ip,
      # slave_web 为从web服务器的 rsyncd.conf 中配置的模块名,
      # rsync 为为从web服务器的中 rsyncd.passwd 中配置的用户名
      rsync -vzrtopg --delete --progress /data/httpd/ rsync@192.168.10.230::slave_web  --password-file=/etc/rsyncd.passwd

### 1.6.2. 安装配置 inotify (主web机需要安装,从web机不需要)

  • 安装 inotify

      yum install inotify-tools
  • 配置rsync.sh同步监控脚本

      vim /root/rsync.sh
添加以下内容

```
  #!/bin/bash
  src=/data/httpd/
  des=web2
  user=rsync
  #多个ip就用空格间断,每个IP用双引号包起来
  host=&quot;192.168.10.230&quot;
  /usr/bin/inotifywait -mrq --exclude=public/images --exclude=public/themes --exclude=data/logs --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e modify,delete,create,attrib $src | while read file
  do
      for hostip in $host
      do
          rsync -vzrtopg --delete --progress --exclude=public/images --exclude=public/themes --exclude=data/logs ${src} ${user}@${hostip}::${des}  --password-file=/etc/rsyncd.passwd
          echo &quot;${file} was rsynced&quot; &gt;&gt; /tmp/rsync.log 2&gt;&amp;1
      done
  done
```
  • 配置rsync.sh脚本的执行权限

      chmod +x /root/rsync.sh
  • 运行rsync.sh同步监控脚本和配置守护进程

      #主web服务器 推送代码到 从web服务器 的时候主web服务器的rsync.passwd只需要配置密码就可以,不用配置用户名,从服务器最好配置同一个用户名和密码)
      nohup sh /root/rsync.sh &amp;
    
      #建立守护进程运行rsync.sh脚本
      echo &quot;nohup sh /root/rsync.sh &amp;&quot; &gt;&gt; /etc/rc.local
  • 注意:如果inotify报错upper limit on inotify watches reached,要修改inotify的max_user_watches参数

      #编辑 /etc/sysctl.conf 文件,配置fs.inotify.max_user_watches,防止句柄数过多报错
      vim /etc/sysctl.conf
      #加上下面这行,这个不是脚本,不要执行,复制内容到 /etc/sysctl.conf
      fs.inotify.max_user_watches=8192000
      #配置好后,执行下面命令使配置生效
      sysctl -p

# 2. 负载均衡

## 2.1. 安装 haproxy

yum install haproxy -y

## 2.2. 配置

集群部署机器分配,具体请根据实际情况配置 |机器 |功能 | 端口| |----|----|---| |192.168.10.228| haproxy | 80 | |192.168.10.229| web 1 | 80 | |192.168.10.230| web 2 | 80 | |192.168.10.231| web 3 | 80 |

192.168.10.228(负载均衡服务器) 编辑/etc/haproxy/haproxy.cfg文件

vim /etc/haproxy/haproxy.cfg(此配置不分前后台)
#以下为配置内容,根据实际情况调整
global
    log         127.0.0.1 local3
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     30000
    user        haproxy
    group       haproxy
    daemon

    stats socket /var/lib/haproxy/stats

defaults
    option http-keep-alive
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option accept-invalid-http-request
    option http-server-close
    option                  redispatch
    retries                 3
    timeout http-request    60s
    timeout queue           1m
    timeout http-keep-alive 60s
    timeout connect 60s
    timeout client 1m
    timeout server 1m
    timeout check 2000
    maxconn                 30000
    stats enable
    stats uri /shopexadminss
    stats auth admin:r4b7x3m7vVN3
frontend  main *:80
    default_backend             app

backend static
    balance     roundrobin
    server      static 192.168.10.229:80 check


backend app
    balance     roundrobin
    mode http
    cookie SERVERID insert nocache indirect
    server web1 192.168.10.229:80  check inter 1500 rise 1 fall 3 weight 1
    server web2 192.168.10.230:80  check inter 1500 rise 1 fall 3 weight 1
    server web3 192.168.10.231:80  check inter 1500 rise 1 fall 3 weight 1

## 2.3. 启动 haproxy

/etc/init.d/haproxy start

## 2.4. 访问负载均衡服务器,检验效果

## 2.5. FAQ

1、同步的目录必须是已有的目录,并且权限正确

2、同步代码的配置中,请检查好模块名,密码等,主web服务器的密码文件中不需要写用户名,本文档中从web服务器之间的rsync配置的用户名和密码都是一致的

单机环境布署

1. 单机部署

1.1. 以下文档请不要盲目复制粘贴,要稍微看看再去操作

1.2. 约定

  • 操作系统:Centos 6.5 x64或6系列更高版本
  • 服务器的mac地址不可以动态变化,必须是固定的(例如微软云则不支持)
  • nginx、php-fpm的用户和组默认是 www和www
  • 执行代码相关操作的的时候,例如bbc本身的update命令或代码复制的时候最好不要用root直接操作,请用 sudo -u www 您的命令 来进行,防止目录权限错误
  • 不要安装php自带的redis扩展,系统默认可以连接redis

1.3. 部署步骤

  • 关闭selinux

    注意:因为有个别机器会和selinux产生冲突,所以是否关闭请自行衡量

      #命令行临时关闭 SeLinux
      setenforce 0
      #修改SeLinux配置,下次启动则默认关闭
      修改  /etc/selinux/config  文件
      将  SELINUX=enforcing  改为  SELINUX=disabled
  • 初始化yum源

    将shopex-lnmp源加入到系统中,在线地址查看有哪些软件 <http://mirrors.shopex.cn/shopex/shopex-lnmp/> 可以安装

      yum install wget -y
      cd /etc/yum.repos.d/
      wget http://mirrors.shopex.cn/shopex/shopex-lnmp/shopex-lnmp.repo
  • 安装epel扩展源

      yum install epel-release -y
  • 安装ONEX BBC环境 主要是安装:php、nginx、mysql、zend解密工具、memcached、redis

    注:单机部署的时候可不装memcached

      yum install php-fpm56 ngx_openresty mysql Zend56 php-memcached56 memcached redis -y
  • 配置环境

    • 关于配置文件以及相关目录说明

      | 名称 | 本次版本(2016.07) | 相关说明 | | :-------- | :----| :----- | | nginx | openresty/1.9.7.4 | 配置文件 /usr/local/nginx/conf/nginx.conf
      vhost配置文件 /usr/local/nginx/conf/vhosts/*.conf | | php | 5.6.19 | 配置文件 /usr/local/php56/etc/php.ini
      php 扩展配置文件目录 /usr/local/php56/etc/php.d/
      zend 配置文件 /usr/local/php56/etc/php.d/Zend.ini
      memcached 配置文件 /usr/local/php56/etc/php.d/memcached.ini| | mysql | 5.6.22 | basedir /usr/local/mysql
      datadir /data/mysql/3306
      配置文件 /usr/local/mysql/my.cnf | | redis | 3.0.3 | 配置文件 /etc/redis.conf | | memcached
      (选装,单机部署可不装) | 1.4.4 | 配置文件 /etc/sysconfig/memcached | | 代码目录 | - | /data/httpd |

    • 配置ZendGuardLoader的证书文件地址(请不要直接复制下面配置,请填您代码实际的zl文件的地址)

      vim /usr/local/php56/etc/php.d/Zend.ini

        zend_extension='/usr/local/php56/lib/php/extensions/no-debug-non-zts-20131226/ZendGuardLoader.so'
        zend_extension='/usr/local/php56/lib/php/extensions/no-debug-non-zts-20131226/opcache_zend.so'
        zend_loader.enable=1
        zend_loader.disable_licensing=0
        zend_loader.obfuscation_level_support=3
        ;最后一项是证书文件地址,请根据实际情况进行配置
        zend_loader.license_path='/data/httpd/config/developer.zl'
  • 配置php56,开启配置 always_populate_raw_post_data

    vim /usr/local/php56/etc/php.ini #704行,修改对应配置

      #将always_populate_raw_post_data的分号去掉
      always_populate_raw_post_data = -1
  • 配置redis持久化 redis持久化介绍文档

    vim /etc/redis.conf #修改对应配置

      #启用AOF
      appendonly yes
    
      # 文件存放目录,与RDB共用。默认为当前工作目录。
      dir ./
      # 默认文件名为appendonly.aof
      appendfilename &quot;appendonly.aof&quot;
·
  • 启动环境

      /etc/init.d/php-fpm56 start
      /etc/init.d/nginx start
      /etc/init.d/mysqld start
      /etc/init.d/redis start
      #如果安装了memcached,则需要启动,一般单机下BBC无需安装memcached,安装了性能也不高,用默认的本地缓存即可
      /etc/init.d/memcached start
  • 安装ONEX BBC

    将bbc安装包解压,复制b2b2c目录到/data/httpd/目录下,如果是二级目录,则自己在/data/httpd下新建目录存放bbc代码

    注意:配置license路径,可能需要修改/usr/local/php56/etc/php.d/Zend.ini内的zl文件的路径

    并将/data/httpd目录的所有者和组都设置为www:

      chown -R www:www /data/httpd

打开http://example.com/public/index.php/即可安装,域名和目录请填写您的实际域名或者目录(如需rewrite请自行配置)

具体安装过程可以参考 <http://club.ec-os.net/doc/b2b2c-dev/700.operator/100.deploy/500.setup.md>

  • 配置ONEX BBC的定时任务

      #检查 /home/目录下是否有www目录,没有则创建一个
      mkdir /home/www
      #配置定时任务,必须配置的是www权限的crontab,不要在root或者其他用户下配置
      crontab -uwww -e
      #将下面的配置复制进去
      * * * * *  /data/httpd/script/queue/queue.sh /usr/local/php56/bin/php &gt; /dev/null
      * * * * *  /usr/local/php56/bin/php  /data/httpd/script/crontab/crontab.php &gt;/dev/null

nginx配置文件nginx.conf详细讲解

#nginx进程,一般设置为和cpu核数一样
worker_processes 4;                        
#错误日志存放目录 
error_log  /data1/logs/error.log  crit;  
#运行用户,默认即是nginx,可不设置
user nginx       
#进程pid存放位置
pid        /application/nginx/nginx.pid;        

#Specifies the value for maximum file descriptors that can be opened by this process. 
#最大文件打开数(连接),可设置为系统优化后的ulimit -HSn的结果
worker_rlimit_nofile 51200;

cpu亲和力配置,让不同的进程使用不同的cpu

worker_cpu_affinity 0001 0010 0100 1000 0001 00100100 1000;

#工作模式及连接数上限
events 
{
  use epoll;       #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能
  worker_connections 1024;  #;单个后台worker process进程的最大并发链接数
}
###################################################
http 
{

include mime.types; #文件扩展名与类型映射表
default_type application/octet-stream; #默认文件类型

#limit模块,可防范一定量的DDOS攻击
#用来存储session会话的状态,如下是为session分配一个名为one的10M的内存存储区,限制了每秒只接受一个ip的一次请求 1r/s
  limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
  limit_conn_zone $binary_remote_addr zone=addr:10m;
  include       mime.types;
  default_type  application/octet-stream;

#第三方模块lua防火墙
    lua_need_request_body on;
    #lua_shared_dict limit 50m;
    lua_package_path &quot;/application/nginx/conf/waf/?.lua&quot;;
    init_by_lua_file &quot;/application/nginx/conf/waf/init.lua&quot;;
    access_by_lua_file &quot;/application/nginx/conf/waf/access.lua&quot;;

 #设定请求缓存    
  server_names_hash_bucket_size 128;
  client_header_buffer_size 512k;
  large_client_header_buffers 4 512k;
  client_max_body_size 100m;


  #隐藏响应header和错误通知中的版本号
  server_tokens off;
  #开启高效传输模式   
  sendfile on;

-------------------------------------------------------------------------------------------------
  #激活tcp_nopush参数可以允许把httpresponse header和文件的开始放在一个文件里发布,
  积极的作用是减少网络报文段的数量
  tcp_nopush     on;
  #激活tcp_nodelay,内核会等待将更多的字节组成一个数据包,从而提高I/O性能
  tcp_nodelay on;
   #FastCGI相关参数:为了改善网站性能:减少资源占用,提高访问速度

 

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

 

 

----------------------------------------------

#连接超时时间,单位是秒
  keepalive_timeout 60;

  #开启gzip压缩功能
    gzip on;
 #设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取。默认值是0,表示不管页面多大都进行压缩。建议设置成大于1K。如果小于1K可能会越压越大。
  gzip_min_length  1k;

#压缩缓冲区大小。表示申请4个单位为16K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。
  gzip_buffers     4 16k;

#压缩版本(默认1.1,前端为squid2.5时使用1.0)用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可。
  gzip_http_version 1.0;

#压缩比率。用来指定GZIP压缩比,1压缩比最小,处理速度最快;9压缩比最大,传输速度快,但处理最慢,也比较消耗cpu资源。
  gzip_comp_level 9;

#用来指定压缩的类型,“text/html”类型总是会被压缩
  gzip_types       text/plain application/x-javascript text/css application/xml;
  #vary header支持。该选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用

Squid缓存经过Nginx压缩的数据。

gzip_vary off;
#开启ssi支持,默认是off
  ssi on;
  ssi_silent_errors on;
#设置日志模式
    log_format  access  '$remote_addr - $remote_user [$time_local] &quot;$request&quot; '
                        '$status $body_bytes_sent &quot;$http_referer&quot; '
                        '&quot;$http_user_agent&quot; $http_x_forwarded_for';

#反向代理负载均衡设定部分

#upstream表示负载服务器池,定义名字为backend_server的服务器池
upstream backend_server {
    server   10.254.244.20:81 weight=1 max_fails=2 fail_timeout=30s;
    server   10.254.242.40:81 weight=1 max_fails=2 fail_timeout=30s;
    server   10.254.245.19:81 weight=1 max_fails=2 fail_timeout=30s;
    server   10.254.243.39:81 weight=1 max_fails=2 fail_timeout=30s;
  #设置由 fail_timeout 定义的时间段内连接该主机的失败次数,以此来断定 fail_timeout 定义的时间段内该主机是否可用。默认情况下这个数值设置为 1。零值的话禁用这个数量的尝试。

设置在指定时间内连接到主机的失败次数,超过该次数该主机被认为不可用。

#这里是在30s内尝试2次失败即认为主机不可用!
  }
###################

#基于域名的虚拟主机
  server
  {

#监听端口
    listen       80;
    server_name  www.abc.com abc.com;    
    index index.html index.htm index.php;    #首页排序
    root  /data0/abc;                            #站点根目录,即网站程序存放目录 
    error_page 500 502 404 /templates/kumi/phpcms/404.html;   #错误页面
#伪静态   将www.abc.com/list....html的文件转发到index.php。。。
#rewrite ^/list-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /index.php?m=content&amp;c=index&amp;a=lists&amp;catid=$1&amp;types=$2&amp;country=$3&amp;language=$4&amp;age=$5&amp;startDate=$6&amp;typeLetter=$7&amp;type=$8&amp;page=$9 last;
#location 标签,根目录下的.svn目录禁止访问
    location ~ /.svn/ {
     deny all;
    }
            location ~ \.php$   
             {  #符合php扩展名的请求调度到fcgi server  
              fastcgi_pass  127.0.0.1:9000;  #抛给本机的9000端口
              fastcgi_index index.php;    #设定动态首页
              include fcgi.conf;
             }
            allow   219.237.222.30 ;  #允许访问的ip
            allow   219.237.222.31 ;
            allow   219.237.222.32 ;
            allow   219.237.222.33 ;
            allow   219.237.222.34 ;
            allow   219.237.222.35 ;
            allow   219.237.222.61 ;
            allow   219.237.222.28 ;
            deny    all;            #禁止其他ip访问
            }
    location ~ ^/admin.php
         {
            location ~ \.php$
             {
              fastcgi_pass  127.0.0.1:9000;
              fastcgi_index index.php;
              include fcgi.conf;
             }
            allow   219.237.222.30 ;
            allow   219.237.222.31 ;
            allow   219.237.222.32 ;
            allow   219.237.222.33 ;
            allow   219.237.222.34 ;
            allow   219.237.222.35 ;
            allow   219.237.222.61;
            allow   219.237.222.28;
         deny    all;
            }

#将符合js,css文件的等设定expries缓存参数,要求浏览器缓存。

location~ .*\.(js|css)?$ {

       expires      30d; #客户端缓存上述js,css数据30天

    }

##add by 20140321#######nginx防sql注入##########

###start####
if ( $query_string ~* &quot;.*[\;'\&lt;\&gt;].*&quot; ){
    return 444;
    }
if ($query_string  ~* &quot;.*(insert|select|delete|update|count|\*|%|master|truncate|declare|\'|\;|and|or|\(|\)|exec).* &quot;) 
    {  
    return 444; 
    }
if ($request_uri ~* &quot;(cost\()|(concat\()&quot;) {
                 return 444;
    }
if ($request_uri ~* &quot;[+|(%20)]union[+|(%20)]&quot;) {
                 return 444;
    }
if ($request_uri ~* &quot;[+|(%20)]and[+|(%20)]&quot;) {
                 return 444;
    }
if ($request_uri ~* &quot;[+|(%20)]select[+|(%20)]&quot;) {
                 return 444;
    }
set $block_file_injections 0;
if ($query_string ~ &quot;[a-zA-Z0-9_]=(\.\.//?)+&quot;) {
set $block_file_injections 1;
}
if ($query_string ~ &quot;[a-zA-Z0-9_]=/([a-z0-9_.]//?)+&quot;) {
set $block_file_injections 1;
}
if ($block_file_injections = 1) {
return 448;
}
set $block_common_exploits 0;
if ($query_string ~ &quot;(&lt;|%3C).*script.*(&gt;|%3E)&quot;) {
set $block_common_exploits 1;
}
if ($query_string ~ &quot;GLOBALS(=|\[|\%[0-9A-Z]{0,2})&quot;) {
set $block_common_exploits 1;
}
if ($query_string ~ &quot;_REQUEST(=|\[|\%[0-9A-Z]{0,2})&quot;) {
set $block_common_exploits 1;
}
if ($query_string ~ &quot;proc/self/environ&quot;) {
set $block_common_exploits 1;
}
if ($query_string ~ &quot;mosConfig_[a-zA-Z_]{1,21}(=|\%3D)&quot;) {
set $block_common_exploits 1;
}
if ($query_string ~ &quot;base64_(en|de)code\(.*\)&quot;) {
set $block_common_exploits 1;
}
if ($block_common_exploits = 1) {
return 444;
}
set $block_spam 0;
if ($query_string ~ &quot;\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b&quot;) {
set $block_spam 1;
}
if ($query_string ~ &quot;\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b&quot;) {
set $block_spam 1;
}
if ($query_string ~ &quot;\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b&quot;) {
set $block_spam 1;
}
if ($query_string ~ &quot;\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b&quot;) {
set $block_spam 1;
}
if ($block_spam = 1) {
return 444;
}
set $block_user_agents 0;
if ($http_user_agent ~ &quot;Wget&quot;) {
 set $block_user_agents 1;
}
# Disable Akeeba Remote Control 2.5 and earlier
if ($http_user_agent ~ &quot;Indy Library&quot;) {
set $block_user_agents 1;
}
# Common bandwidth hoggers and hacking tools.
if ($http_user_agent ~ &quot;libwww-perl&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;GetRight&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;GetWeb!&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;Go!Zilla&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;Download Demon&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;Go-Ahead-Got-It&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;TurnitinBot&quot;) {
set $block_user_agents 1;
}
if ($http_user_agent ~ &quot;GrabNet&quot;) {
set $block_user_agents 1;
}
if ($block_user_agents = 1) {
return 444;
}

###end####
     location ~ ^/list {
         #如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
         proxy_next_upstream http_502 http_504 error timeout invalid_header;
         proxy_cache cache_one;
         #对不同的HTTP状态码设置不同的缓存时间
         proxy_cache_valid  200 301 302 304 1d;
         #proxy_cache_valid  any 1d;
         #以域名、URI、参数组合成Web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内
         proxy_cache_key $host$uri$is_args$args;
         proxy_set_header Host  $host;
         proxy_set_header X-Forwarded-For  $remote_addr;
         proxy_ignore_headers &quot;Cache-Control&quot; &quot;Expires&quot; &quot;Set-Cookie&quot;;
         #proxy_ignore_headers Set-Cookie;
         #proxy_hide_header Set-Cookie;
         proxy_pass http://backend_server;
         add_header      Nginx-Cache     &quot;$upstream_cache_status  from  km&quot;;

          expires      1d;
        }

    access_log  /data1/logs/abc.com.log access;    #nginx访问日志
  }
-----------------------ssl(https)相关------------------------------------

server {
  listen 13820; #监听端口
  server_name localhost;
  charset utf-8; #gbk,utf-8,gb2312,gb18030 可以实现多种编码识别
  ssl on; #开启ssl
  ssl_certificate /ls/app/nginx/conf/mgmtxiangqiankeys/server.crt; #服务的证书
  ssl_certificate_key /ls/app/nginx/conf/mgmtxiangqiankeys/server.key; #服务端key
  ssl_client_certificate /ls/app/nginx/conf/mgmtxiangqiankeys/ca.crt; #客户端证书
  ssl_session_timeout 5m; #session超时时间
  ssl_verify_client on; # 开户客户端证书验证 
  ssl_protocols SSLv2 SSLv3 TLSv1; #允许SSL协议 
  ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; #加密算法
  ssl_prefer_server_ciphers on; #启动加密算法
  access_log /lw/logs/nginx/dataadmin.test.com.ssl.access.log access ; #日志格式及日志存放路径
  error_log /lw/logs/nginx/dataadmin.test.com.ssl.error.log; #错误日志存放路径

}

-------------------------------------------------------------------------
}

Web性能压力测试ab(apachebench)

<p>ab命令会创建多个并发访问线程,模拟多个访问者同时对某一URL地址进行访问。它的测试目标是基于URL的,因此,它既可以用来测试apache的负载压力,也可以测试nginx、lighthttp、tomcat、IIS等其它Web服务器的压力。</p><p><font color="#ff0000">ab命令对发出负载的计算机要求很低,它既不会占用很高CPU,也不会占用很多内存。但却会给目标服务器造成巨大的负载,其原理类似CC攻击。自己测试使用也需要注意,否则一次上太多的负载。可能造成目标服务器资源耗完,严重时甚至导致死机。</font></p><pre style="max-width:100%;overflow-x:auto;">
查看ab是否安装成功,可以切换到上述目录下,使用ab –V命令进行检测
ab -V

yum -y install httpd-tools #直接安装工具包

ab -V
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
</pre><pre>ab 参数比较多,一般常用的是-c -n
ab -c 10 -n 100 https://jerryblog.cn/index.php

<span class="hljs-deletion">-c10表示并发用户数为10</span>
<span class="hljs-deletion">-n100表示请求总数为10</span>
</pre><div>
</div><p>
</p><pre style="max-width:100%;overflow-x:auto;">#测试需要登陆的信息

先用账户和密码登录后,用开发者工具找到标识这个会话的Cookie值(Session ID)记下来
复制Cookie信息
ab -n 100 -c 100 -H "Cookie: JSESSIONID=01BCDA8D30F3011A1C8136ED9B0A3ED6.server;USER.oooooooooooooooo=ab84b0125a24ecb263c6b677b989683ca26da6b4076ae09e1d5ccb8595a92a6d28233e61d860c9d0b745b0dfd8426494"  http://localhost/user/index

</pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">ab -c 10 -n 100 https://jerryblog.cn/index.php
This is ApacheBench, Version 2.3 <$Revision: 655654 {#content}gt;
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking jerryblog.cn (be patient).....done
Server Software: nginx/1.10.0 #测试软件版本
Server Hostname: jerryblog.cn #域
Server Port: 443 #端口
SSL/TLS Protocol: TLSv1/SSLv3,ECDHE-RSA-AES128-GCM-SHA256,2048,128

Document Path: /index.php
Document Length: 16528 bytes #页面长度

Concurrency Level: 10 #并发数
Time taken for tests: 7.037 seconds #共使用了多少时间
Complete requests: 100 #请求数
Failed requests: 0 #失败请求数
Write errors: 0
Total transferred: 1671300 bytes#总共传输字节数,包含http的头信息等
HTML transferred: 1652800 bytes#html字节数,实际的页面传递字节数
Requests per second: 14.21 [#/sec] (mean)##每秒多少请求,这个是非常重要的参数数值,服务器的吞吐量
Time per request: 703.723 [ms] (mean)#用户平均请求等待时间
Time per request: 70.372 [ms] (mean, across all concurrent requests)#服务器平均处理时间,也就是服务器吞吐量的倒数
Transfer rate: 231.93 [Kbytes/sec] received #每秒获取的数据长度

Connection Times (ms)

          min  mean[+/-sd] median   max

Connect: 12 54 33.9 45 169
Processing: 59 628 114.3 635 894
Waiting: 52 626 114.7 632 894
Total: 150 683 122.6 679 1063

Percentage of the requests served within a certain time (ms)
50% 679 #50%的请求在679ms内返回
66% 706
75% 730
80% 763
90% 829
95% 893
98% 941
99% 1063
100% 1063 (longest request)

</pre><pre style="max-width:100%;overflow-x:auto;">ab --help
ab: wrong number <span class="hljs-keyword">of</span> <span class="hljs-built_in">arguments</span>
Usage: ab [options] [http[s]:<span class="hljs-comment">//]hostname[:port]/path</span>
Options are:

-n requests     <span class="hljs-built_in">Number</span> <span class="hljs-keyword">of</span> requests to perform
-c concurrency  <span class="hljs-built_in">Number</span> <span class="hljs-keyword">of</span> multiple requests to make
-t timelimit    Seconds to max. wait <span class="hljs-keyword">for</span> responses
-b windowsize   Size <span class="hljs-keyword">of</span> TCP send/receive buffer, <span class="hljs-keyword">in</span> bytes
-p postfile     File containing data to POST. Remember also to set -T
-u putfile      File containing data to PUT. Remember also to set -T
-T content-type Content-type header <span class="hljs-keyword">for</span> POSTing, eg.
                <span class="hljs-string">'application/x-www-form-urlencoded'</span>
                Default is <span class="hljs-string">'text/plain'</span>
-v verbosity    How much troubleshooting info to print
-w              Print out results <span class="hljs-keyword">in</span> HTML tables
-i              Use HEAD instead <span class="hljs-keyword">of</span> GET
-x attributes   <span class="hljs-built_in">String</span> to insert <span class="hljs-keyword">as</span> table attributes
-y attributes   <span class="hljs-built_in">String</span> to insert <span class="hljs-keyword">as</span> tr attributes
-z attributes   <span class="hljs-built_in">String</span> to insert <span class="hljs-keyword">as</span> td or th attributes
-C attribute    Add cookie, eg. <span class="hljs-string">'Apache=1234. (repeatable)
-H attribute    Add Arbitrary header line, eg. '</span>Accept-Encoding: gzip<span class="hljs-string">'
                Inserted after all normal header lines. (repeatable)
-A attribute    Add Basic WWW Authentication, the attributes
                are a colon separated username and password.
-P attribute    Add Basic Proxy Authentication, the attributes
                are a colon separated username and password.
-X proxy:port   Proxyserver and port number to use
-V              Print version number and exit
-k              Use HTTP KeepAlive feature
-d              Do not show percentiles served table.
-S              Do not show confidence estimators and warnings.
-g filename     Output collected data to gnuplot format file.
-e filename     Output CSV file with percentages served
-r              Don'</span>t exit on socket receive errors.
-h              Display usage information (<span class="hljs-keyword">this</span> message)
-Z ciphersuite  Specify SSL/TLS cipher suite (See openssl ciphers)
-f protocol     Specify SSL/TLS protocol (SSL2, SSL3, TLS1, or ALL)

</pre><p>
</p>

Web性能压力测试Webbench

<p>Webbench是知名的网站压力测试工具,它是由Lionbridge公司(http://www.lionbridge.com)开发。</p><p>官网地址:http://home.tiscali.cz/~cz210552/webbench.html</p><p>webbench最多可以模拟3万个并发连接去测试网站的负载能力</p><div><font color="#ff0000">注意:</font></div><div><font color="#ff0000">好像不能测试HTTPS!!帮助命令里也没有相关HTTPS的帮助</font>
</div><p><font color="#ff0000">webbench 做压力测试时,该软件自身也会消耗CPU和内存资源,为了测试准确,请将 webbench 安装在别的服务器上。</font></p><p>
</p><p><font color="#ff0000"></font></p><pre style="max-width:100%;overflow-x:auto;">#安装
yum install -y gcc ctags ##需要GCC支持
wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz
tar -zxvf webbench-1.5.tar.gz
cd webbench-1.5
make && make install
</pre><p>使用</p><p>
</p><pre style="max-width:100%;overflow-x:auto;">webbench -c 10 -t 10 http://jerryblog.cn/index.php #不支持https

webbench -c 并发数 -t 运行测试时间 URL

Pages/min:响应请求数/分
bytes/sec:传输数据量/秒

循环测试

for n in seq 5 5 50
do
echo -n $n " "
webbench -c $n -t 60 http://xxx.com/test.php 2&gt;/dev/null | grep Speed | awk '{print $1}' | awk -F= '{print $2}'
echo
done
</pre><pre style="max-width:100%;overflow-x:auto;">webbench --help
webbench [option]... URL
-f|--force Don<span class="hljs-string">'t wait for reply from server.
-r|--reload Send reload request - Pragma: no-cache.
-t|--time <sec> Run benchmark for <sec> seconds. Default 30.
-p|--proxy <server:port> Use proxy server for request.
-c|--clients <n> Run <n> HTTP clients at once. Default one.
-9|--http09 Use HTTP/0.9 style requests.
-1|--http10 Use HTTP/1.0 protocol.
-2|--http11 Use HTTP/1.1 protocol.
--get Use GET request method.
--head Use HEAD request method.
--options Use OPTIONS request method.
--trace Use TRACE request method.
-?|-h|--help This information.
-V|--version Display program version.
</n></n></server:port></sec></sec></span>
</pre><p>
</p>

常用的vagrant 命令

$ vagrant init      # 初始化

$ vagrant up        # 启动虚拟机
$ vagrant halt      # 关闭虚拟机
$ vagrant reload    # 重启虚拟机
$ vagrant ssh       # SSH 至虚拟机
$ vagrant suspend   # 挂起虚拟机
$ vagrant resume    # 唤醒虚拟机
$ vagrant status    # 查看虚拟机运行状态
$ vagrant destroy   # 销毁当前虚拟机


#box管理命令
$ vagrant box list    # 查看本地box列表
$ vagrant box add     # 添加box到列表

$ vagrant box remove  # 从box列表移除 

redis 安装

<pre style="max-width:100%;overflow-x:auto;">#YUM安装
yum -y install redis

源码安装可以参考官网https://redis.io/download

$ wget http://download.redis.io/releases/redis-4.0.9.tar.gz
$ tar xzf redis-4.0.9.tar.gz
$ cd redis-4.0.9
$ make
</pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">#这里需要注意redis 有个配置文件,默认端口6379
126 # By default Redis does not run as a daemon. Use 'yes' if you need it.
127 # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
128 daemonize yes #默认为NO 不然无法连接

查看是否将默认只能本地访问redis改为所有IP均可以访问

bind 127.0.0.1 改为 bind 0.0.0.0 </pre><pre style="max-width:100%;overflow-x:auto;">redis-server /etc/redis.conf ##开启redis

/usr/local/bin/redis-cli ##测试REDIS是否能连接
</pre><pre style="max-width:100%;overflow-x:auto;"># 以下为配置文件详解

redis.conf

Redis configuration file example.

./redis-server /path/to/redis.conf

INCLUDES

这在你有标准配置模板但是每个redis服务器又需要个性设置的时候很有用。

include /path/to/local.conf

include /path/to/other.conf

GENERAL

是否在后台执行,yes:后台运行;no:不是后台运行(老版本默认)

daemonize yes

#3.2里的参数,是否开启保护模式,默认开启。要是配置里没有指定bind和密码。开启该参数后,redis只会本地进行访问,拒绝外部访问。要是开启了密码 和bind,可以开启。否 则最好关闭,设置为no。
protected-mode yes

redis的进程文件

pidfile /var/run/redis/redis-server.pid

redis监听的端口号。

port 6379

此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度, 当然此值必须不大于Linux系统定义的/proc/sys/net/core/somaxconn值,默认是511,而Linux的默认参数值是128。当系统并发量大并且客户端速度缓慢的时候,可以将这二个参数一起参考设定。该内核参数默认值一般是128,对于负载很大的服务程序来说大大的不够。一般会将它修改为2048或者更大。在/etc/sysctl.conf中添加:net.core.somaxconn = 2048,然后在终端中执行sysctl -p。

tcp-backlog 511

指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求

bind 127.0.0.1

配置unix socket来让redis支持监听本地连接。

unixsocket /var/run/redis/redis.sock

配置unix socket使用文件的权限

unixsocketperm 700

此参数为设置客户端空闲超过timeout,服务端会断开连接,为0则服务端不会主动断开连接,不能小于0。

timeout 0

tcp keepalive参数。如果设置不为0,就使用配置tcp的SO_KEEPALIVE值,使用keepalive有两个好处:检测挂掉的对端。降低中间设备出问题而导致网络看似连接却已经与对端端口的问题。在Linux内核中,设置了keepalive,redis会定时给对端发送ack。检测到对端关闭需要两倍的设置值。

tcp-keepalive 0

指定了服务端日志的级别。级别包括:debug(很多信息,方便开发、测试),verbose(许多有用的信息,但是没有debug级别信息多),notice(适当的日志级别,适合生产环境),warn(只有非常重要的信息)

loglevel notice

指定了记录日志的文件。空字符串的话,日志会打印到标准输出设备。后台运行的redis标准输出是/dev/null。

logfile /var/log/redis/redis-server.log

是否打开记录syslog功能

syslog-enabled no

syslog的标识符。

syslog-ident redis

日志的来源、设备

syslog-facility local0

数据库的数量,默认使用的数据库是DB 0。可以通过”SELECT “命令选择一个db

databases 16

SNAPSHOTTING

快照配置

注释掉“save”这一行配置项就可以让保存数据库功能失效

设置sedis进行数据库镜像的频率。

900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)

300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)

60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)

save 900 1
save 300 10
save 60 10000

当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作,可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误

stop-writes-on-bgsave-error yes

使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间

rdbcompression yes

是否校验rdb文件。从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置。

rdbchecksum yes

rdb文件的名称

dbfilename dump.rdb

数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录

dir /var/lib/redis

REPLICATION

复制选项,slave复制对应的master。

slaveof <masterip> <masterport>

如果master设置了requirepass,那么slave要连上master,需要有master的密码才行。masterauth就是用来配置master的密码,这样可以在连上master后进行认证。

masterauth <master-password>

当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。2) 如果slave-serve-stale-data设置为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误”SYNC with master in progress”。

slave-serve-stale-data yes

作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)。

slave-read-only yes

是否使用socket方式复制数据。目前redis复制提供两种方式,disk和socket。如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。有2种方式:disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave。disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式。

repl-diskless-sync no

diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间,等更多的slave连上来。

repl-diskless-sync-delay 5

slave根据指定的时间间隔向服务器发送ping请求。时间间隔可以通过 repl_ping_slave_period 来设置,默认10秒。

repl-ping-slave-period 10

复制连接超时时间。master和slave都有超时时间的设置。master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。需要注意的是repl-timeout需要设置一个比repl-ping-slave-period更大的值,不然会经常检测到超时。

repl-timeout 60

是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。默认是no,即使用tcp nodelay。如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。

repl-disable-tcp-nodelay no

复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。这样在slave离线的时候,不需要完全复制master的数据,如果可以执行部分同步,只需要把缓冲区的部分数据复制给slave,就能恢复正常复制状态。缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有slave连接的时候才分配内存。没有slave的一段时间,内存会被释放出来,默认1m。

repl-backlog-size 5mb

master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。单位为秒。

repl-backlog-ttl 3600

当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举。

slave-priority 100

redis提供了可以让master停止写入的方式,如果配置了min-slaves-to-write,健康的slave的个数小于N,mater就禁止写入。master最少得有多少个健康的slave存活才能执行写命令。这个配置虽然不能保证N个slave都一定能接收到master的写操作,但是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。设置为0是关闭该功能。

min-slaves-to-write 3

延迟小于min-slaves-max-lag秒的slave才认为是健康的slave。

min-slaves-max-lag 10

设置1或另一个设置为0禁用这个特性。

Setting one or the other to 0 disables the feature.

By default min-slaves-to-write is set to 0 (feature disabled) and

min-slaves-max-lag is set to 10.

SECURITY

requirepass配置可以让用户使用AUTH命令来认证密码,才能使用其他命令。这让redis可以使用在不受信任的网络中。为了保持向后的兼容性,可以注释该命令,因为大部分用户也不需要认证。使用requirepass的时候需要注意,因为redis太快了,每秒可以认证15w次密码,简单的密码很容易被攻破,所以最好使用一个更复杂的密码。

requirepass foobared

把危险的命令给修改成其他名称。比如CONFIG命令可以重命名为一个很难被猜到的命令,这样用户不能使用,而内部工具还能接着使用。

rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52

设置成一个空的值,可以禁止一个命令

rename-command CONFIG ""

LIMITS

设置能连上redis的最大客户端连接数量。默认是10000个客户端连接。由于redis不区分连接是客户端连接还是内部打开文件或者和slave连接等,所以maxclients最小建议设置到32。如果超过了maxclients,redis会给新的连接发送’max number of clients reached’,并关闭连接。

maxclients 10000

redis配置的最大内存容量。当内存满了,需要配合maxmemory-policy策略进行处理。注意slave的输出缓冲区是不计算在maxmemory内的。所以为了防止主机内存使用完,建议设置的maxmemory需要更小一些。

maxmemory <bytes>

内存容量超过maxmemory后的处理策略。

volatile-lru:利用LRU算法移除设置过过期时间的key。

volatile-random:随机移除设置过过期时间的key。

volatile-ttl:移除即将过期的key,根据最近过期时间来删除(辅以TTL)

allkeys-lru:利用LRU算法移除任何key。

allkeys-random:随机移除任何key。

noeviction:不移除任何key,只是返回一个写错误。

上面的这些驱逐策略,如果redis没有合适的key驱逐,对于写命令,还是会返回错误。redis将不再接收写请求,只接收get请求。写命令包括:set setnx setex append incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby getset mset msetnx exec sort。

maxmemory-policy noeviction

lru检测的样本数。使用lru或者ttl淘汰算法,从需要淘汰的列表中随机选择sample个key,选出闲置时间最长的key移除。

maxmemory-samples 5

APPEND ONLY MODE

默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。

appendonly no

aof文件名

appendfilename "appendonly.aof"

aof持久化策略的配置

no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。

always表示每次写入都执行fsync,以保证数据同步到磁盘。

everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。

appendfsync everysec

在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no。如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择。设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。

no-appendfsync-on-rewrite no

aof自动重写配置。当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。

auto-aof-rewrite-percentage 100

设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写

auto-aof-rewrite-min-size 64mb

aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项(redis宕机或者异常终止不会造成尾部不完整现象。)出现这种现象,可以选择让redis退出,或者导入尽可能多的数据。如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF文件才可以。

aof-load-truncated yes

LUA SCRIPTING

如果达到最大时间限制(毫秒),redis会记个log,然后返回error。当一个脚本超过了最大时限。只有SCRIPT KILL和SHUTDOWN NOSAVE可以用。第一个可以杀没有调write命令的东西。要是已经调用了write,只能用第二个命令杀。

lua-time-limit 5000

REDIS CLUSTER

集群开关,默认是不开启集群模式。

cluster-enabled yes

集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。这个文件并不需要手动配置,这个配置文件有Redis生成并更新,每个Redis集群节点需要一个单独的配置文件,请确保与实例运行的系统中配置文件名称不冲突

cluster-config-file nodes-6379.conf

节点互连超时的阀值。集群节点超时毫秒数

cluster-node-timeout 15000

在进行故障转移的时候,全部slave都会请求申请为master,但是有些slave可能与master断开连接一段时间了,导致数据过于陈旧,这样的slave不应该被提升为master。该参数就是用来判断slave节点与master断线的时间是否过长。判断方法是:

比较slave断开连接的时间和(node-timeout * slave-validity-factor) + repl-ping-slave-period

如果节点超时时间为三十秒, 并且slave-validity-factor为10,假设默认的repl-ping-slave-period是10秒,即如果超过310秒slave将不会尝试进行故障转移

cluster-slave-validity-factor 10

master的slave数量大于该值,slave才能迁移到其他孤立master上,如这个参数若被设为2,那么只有当一个主节点拥有2 个可工作的从节点时,它的一个从节点会尝试迁移。

cluster-migration-barrier 1

默认情况下,集群全部的slot有节点负责,集群状态才为ok,才能提供服务。设置为no,可以在slot没有全部分配的时候提供服务。不建议打开该配置,这样会造成分区的时候,小分区的master一直在接受写请求,而造成很长时间数据不一致。

cluster-require-full-coverage yes

SLOW LOG

slog log是用来记录redis运行中执行比较慢的命令耗时。当命令的执行超过了指定时间,就记录在slow log中,slog log保存在内存中,所以没有IO操作。

执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒,所以1000000就是1秒。注意,负数时间会禁用慢查询日志,而0则会强制记录所有命令。

slowlog-log-slower-than 10000

慢查询日志长度。当一个新的命令被写进日志的时候,最老的那个记录会被删掉。这个长度没有限制。只要有足够的内存就行。你可以通过 SLOWLOG RESET 来释放内存。

slowlog-max-len 128

LATENCY MONITOR

延迟监控功能是用来监控redis中执行比较缓慢的一些操作,用LATENCY打印redis实例在跑命令时的耗时图表。只记录大于等于下边设置的值的操作。0的话,就是关闭监视。默认延迟监控功能是关闭的,如果你需要打开,也可以通过CONFIG SET命令动态设置。

latency-monitor-threshold 0

EVENT NOTIFICATION

键空间通知使得客户端可以通过订阅频道或模式,来接收那些以某种方式改动了 Redis 数据集的事件。因为开启键空间通知功能需要消耗一些 CPU ,所以在默认配置下,该功能处于关闭状态。

notify-keyspace-events 的参数可以是以下字符的任意组合,它指定了服务器该发送哪些类型的通知:

K 键空间通知,所有通知以 keyspace@ 为前缀

E 键事件通知,所有通知以 keyevent@ 为前缀

g DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知

$ 字符串命令的通知

l 列表命令的通知

s 集合命令的通知

h 哈希命令的通知

z 有序集合命令的通知

x 过期事件:每当有过期键被删除时发送

e 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送

A 参数 g$lshzxe 的别名

输入的参数中至少要有一个 K 或者 E,否则的话,不管其余的参数是什么,都不会有任何 通知被分发。详细使用可以参考http://redis.io/topics/notifications

notify-keyspace-events ""

ADVANCED CONFIG

数据量小于等于hash-max-ziplist-entries的用ziplist,大于hash-max-ziplist-entries用hash

hash-max-ziplist-entries 512

value大小小于等于hash-max-ziplist-value的用ziplist,大于hash-max-ziplist-value用hash。

hash-max-ziplist-value 64

数据量小于等于list-max-ziplist-entries用ziplist,大于list-max-ziplist-entries用list。

list-max-ziplist-entries 512

value大小小于等于list-max-ziplist-value的用ziplist,大于list-max-ziplist-value用list。

list-max-ziplist-value 64

数据量小于等于set-max-intset-entries用iniset,大于set-max-intset-entries用set。

set-max-intset-entries 512

数据量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用zset。

zset-max-ziplist-entries 128

value大小小于等于zset-max-ziplist-value用ziplist,大于zset-max-ziplist-value用zset。

zset-max-ziplist-value 64

value大小小于等于hll-sparse-max-bytes使用稀疏数据结构(sparse),大于hll-sparse-max-bytes使用稠密的数据结构(dense)。一个比16000大的value是几乎没用的,建议的value大概为3000。如果对CPU要求不高,对空间要求较高的,建议设置到10000左右。

hll-sparse-max-bytes 3000

Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用。当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存。

activerehashing yes

对客户端输出缓冲进行限制可以强迫那些不从服务器读取数据的客户端断开连接,用来强制关闭传输缓慢的客户端。

对于normal client,第一个0表示取消hard limit,第二个0和第三个0表示取消soft limit,normal client默认取消限制,因为如果没有寻问,他们是不会接收数据的。

client-output-buffer-limit normal 0 0 0

对于slave client和MONITER client,如果client-output-buffer一旦超过256mb,又或者超过64mb持续60秒,那么服务器就会立即断开客户端连接。

client-output-buffer-limit slave 256mb 64mb 60

对于pubsub client,如果client-output-buffer一旦超过32mb,又或者超过8mb持续60秒,那么服务器就会立即断开客户端连接。

client-output-buffer-limit pubsub 32mb 8mb 60

redis执行任务的频率为1s除以hz。

hz 10

在aof重写的时候,如果打开了aof-rewrite-incremental-fsync开关,系统会每32MB执行一次fsync。这对于把文件写入磁盘是有帮助的,可以避免过大的延迟峰值。

aof-rewrite-incremental-fsync yes</bytes></master-password></masterport></masterip></pre><pre style="max-width:100%;overflow-x:auto;">##php扩展安装 我的PHP是 PHP7.0
weget http://pecl.php.net/get/redis-4.0.2.tgz

/www/wdlinux/apache_php/bin/phpize ##phpize 安装此扩展
./configure --with-php-config=/www/wdlinux/php/bin/php-config
make && make install

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:

  • add LIBDIR to the `LD_LIBRARY_PATH' environment variable
    during execution
  • add LIBDIR to the `LD_RUN_PATH' environment variable
    during linking
  • use the `-Wl,--rpath -Wl,LIBDIR' linker flag
  • have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for

more information, such as the ld(1) and ld.so(8) manual pages.

Build complete.
Don't forget to run 'make test'.

Installing shared extensions: /www/wdlinux/apache_php-7.0.6/lib/php/extensions/no-debug-non-zts-20151012/

在PHP.ini文件中加入
[redis]
extension_dir =/www/wdlinux/apache_php-7.0.6/lib/php/extensions/no-debug-non-zts-20151012/
extension=redis.so
</pre><p>
</p>

简单可靠的Shell脚本来守护一个可能会突发退出的PHP(activeMQ)服务

<p>监控activemq的服务是否正常运行<br/></p><p>/etc/rc.local 里加入开机启动命令:</p><pre class="brush:bash;toolbar:false">nohup /www/web/activemq.sh >>/www/web/activemq.log 2>&1 &</pre><pre class="brush:bash;toolbar:false">#!/bin/sh
DIR=/www/web
INTERVAL=1 ##等待时间
nohup php ${DIR}/activemq.php&nbsp;&gt;&gt;${DIR}/activemq.log 2>&1 & echo $!&nbsp;&gt;&nbsp;${DIR}/activemq.pid while [ 1 ]; do
    if [ ! -d /proc/cat&nbsp;${DIR}/activemq.pid ]; then
        nohup php ${DIR}/send.php&nbsp;&gt;&gt;${DIR}/activemq.log 2>&1 & echo $!&nbsp;&gt;&nbsp;${DIR}/activemq.pid        echo 'NEW_PID:'cat&nbsp;${DIR}/activemq.pid&nbsp;&amp;&amp;&nbsp;date&nbsp;&#39;+%Y-%m-%d&nbsp;%H:%M:%S&#39;    fi
    sleep ${INTERVAL}done</pre><pre class="brush:bash;toolbar:false">nohup 表示忽略SIGHUP信号(编号1),比如退出终端时发送的SIGHUP信号(kill -SIGHUP PID)会被忽略掉.
>>${DIR}/activemq.log 表示把标准输出重定向(>>表示追加,>表示覆盖)到文件activemq.log
2>&1 表示将标准错误(2:stderr)重定向到标准输出(1:stdout).
结尾加上&表示将命令放入后台运行.
$! 表示前面运行在后台的PHP进程PID.</pre><p>网上另外一个写法。</p><pre class="brush:bash;toolbar:false">#!/bin/bash
EMAIL='xxx@xx.com' ##邮箱
start(){
        c=ps&nbsp;w&nbsp;-C&nbsp;php|grep&nbsp;$1|wc&nbsp;-l
        if [ $c -lt 1 ]
        then
          if [ -f "$1" ];then
          /usr/local/php/bin/php $1 > /dev/null &
          else
          echo&nbsp;&#39;no&nbsp;such&nbsp;file&nbsp;&#39;$1&nbsp;|&nbsp;mail&nbsp;-s&nbsp;&#39;process&nbsp;check&nbsp;error&#39;&nbsp;$EMAIL
          fi
        fi
        }
BASE_PATH=dirname&nbsp;$0"/"
cd $BASE_PATH

start del_old_sessions.php</pre><p><br/></p>

将Centos的yum源更换为国内的阿里云源

<pre> 阿里云Linux安装软件镜像源

阿里云是最近新出的一个镜像源。得益与阿里云的高速发展,这么大的需求,肯定会推出自己的镜像源。
阿里云Linux安装镜像源地址:http://mirrors.aliyun.com/

CentOS系统更换软件安装源
第一步:备份你的原镜像文件,以免出错后可以恢复。

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
第二步:下载新的CentOS-Base.repo 到/etc/yum.repos.d/
CentOS 5

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-5.repo
CentOS 6

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
第三步:运行yum makecache生成缓存

yum clean all

yum makecache</pre>
<p> </p>

阿里云服务器CentOS 5.7(64位)安装配置LAMP服务器(Apache+PHP5+MySQL

<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-align: center; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">阿里云服务器CentOS 5.7(64位)安装配置LAMP服务器(Apache+PHP5+MySQL)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">一、快速安装Apache+PHP5+MySql</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="color: rgb(0, 0, 255);"><span style="font-size: small;">补充:由于</span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">163的yum源上只有php5.1.6 mysql 5.0.95 版本较低,请直接看最后面的《</span></span>八、卸载php5.1,mysql5.0 重新安装php5.4,mysql5.5》</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">安装163的yum源(参看我的别一篇文章)</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">ssh登录上服务器,先更新:</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">[root@AY1207241 /]# yum update</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">然后安装LAMP环境:(163的yum源上只有php5.1.6 mysql 5.0.95 版本较低)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">[root@AY1207241 /]# yum -y install httpd php mysql mysql-server php-mysql httpd-manual mod_ssl mod_perl mod_auth_mysql php-mcrypt php-gd php-xml php-mbstring php-ldap php-pear php-xmlrpc mysql-connector-odbc mysql-devel libdbi-dbd-mysql</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">启动apache和mysql:</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">[root@AY1207241 /]#<span style="color: rgb(255, 0, 0);"> service httpd start</span>   (重启是restart)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">[root@AY1207241 /]# <span style="color: rgb(255, 0, 0);">service mysqld start</span>    (重启是restart)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">设置为开机启动</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">chkconfig httpd on   #Apache设为开机启动</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">chkconfig mysqld on   #mysql设为开机启动</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">/etc/init.d/httpd start  #启动Apache</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">/etc/init.d/httpd restart  #重启Apache</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">---------</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">备注:Apache启动之后会提示错误:正在启动 httpd:httpd: Could not reliably determine the server's fully qualif domain name, using ::1 for ServerName      </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">解决办法:</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">vi /etc/httpd/conf/httpd.conf   #编辑</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">找到  #ServerName www.example.com:80</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">修改为 ServerName localhost:80</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">:wq!    #保存退出</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">Apache的配置文件:</span><span style="font-size: small;"><span style="font-size: small;">vi /etc/httpd/conf/httpd.conf</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">其中有:表示apache运行的用户</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">User apache
Group apache</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: medium;"><span style="font-size: small;">二、测试PHP,输出php信息</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">修改以下文件:</span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">[root@AY1207241 /]# vi /var/www/html/index.php</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">输入测试PHP代码如下:</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"><?php  </span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">phpinfo();</span></span></p>
<p style="margin: 0px; padding: 0px 0px 0px 30px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">?> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">浏览器访问服务器IP地址,正常应该可以访问了。</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">三、Apache配置</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">vi /etc/httpd/conf/httpd.conf 编辑文件</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   Options Indexes FollowSymLinks        在331行 修改为:Options Includes ExecCGI FollowSymLinks(允许服务器执行CGI及SSI)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   #AddHandler cgi-script .cgi</span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>在796行 修改为:AddHandler cgi-script .cgi .pl (允许扩展名为.pl的CGI脚本运行)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   AllowOverride None  </span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>在338行 修改为:AllowOverride All (允许.htaccess)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   AddDefaultCharset UTF-8 </span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>在759行 修改为:AddDefaultCharset GB2312 (添加GB2312为默认编码)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> Options Indexes MultiViews  </span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>找到这一行,将“Indexes”删除 ,变为此状态 Options MultiViews (不在浏览器上显示树状目录结构)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   DirectoryIndex index.html index.html.var  </span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>在 402行 修改为:DirectoryIndex index.html index.htm Default.html Default.htm index.php Default.php index.html.var  (设置默认首页文件,增加index.php)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   KeepAlive Off   </span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>在76行 修改为:KeepAlive On (允许程序性联机)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   MaxKeepAliveRequests 100  </span></span><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;"><span style="font-size: small;">        </span></span>在83行 修改为:MaxKeepAliveRequests 1000 (增加同时连接数)  </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">:wq!  #保存退出</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   <span style="color: rgb(255, 0, 0);">/etc/init.d/httpd restart 重启</span></span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   DocumentRoot "/var/www/html"  修改为你的目录   "/data0/www/xxxxxxxxx"  (这个目录就是挂载的数据盘)</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">   rm -f /etc/httpd/conf.d/welcome.conf /var/www/error/noindex.html    #删除默认测试页</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">Apache的日志文件   
    ErrorLog  /etc/httpd/logs/error_log   (php的错误日志也输出到这里)
    CustomLog  /etc/httpd/logs/access_log combined</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">四、php配置</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">vi  /etc/php.ini   #编辑</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">date.timezone = PRC     #在946行 把前面的分号去掉,改为date.timezone = PRC</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">magic_quotes_gpc = On   #在745行 打开magic_quotes_gpc来防止SQL注入  (</span></span>php5.4开始不支持magic_quotes_gpc(防SQL流入))</p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">log_errors = On         #记录错误日志</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;"> </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">:wq!  #保存退出</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small; color: rgb(255, 0, 0);"><span style="font-size: small;">/etc/init.d/httpd restart   #重启Apche , php</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: medium;"><span style="font-size: small;">五、挂载数据盘</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">阿里云服务器的硬盘由两块组成,一块是系统盘,一块是数据盘,默认数据盘是没有挂载的,如果要用到数据盘就需要自己手动挂载。</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">通过命令fdisk -l,可以看到设备名为/dev/xvdb。</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">另外在挂载前要对硬盘(/dev/xvdb)分区和格式化。</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">分区使用命令fdisk,格式化命令为mkfs.ext3。</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">如何操作可以参照官方文档【Linux 系统挂载数据盘 】http://help.aliyun.com/manual?helpId=271  </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">数据盘最多可以挂4块,挂在/data0,以后其它的可以挂在/data1,</span><span style="font-size: small;">/data2,</span><span style="font-size: small;">/data3</span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">数据盘的作用,阿里云服务器控制台提供“重置”功能,可选重置系统盘,还是数据盘,如何操作系统坏了,你可以只重置系统盘,保留网站数据在数据盘。</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"><span style="font-size: small;">六、配置MySql数据库--设置初始密码,</span></span>建库,建表,导入数据</p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);">请看这里:MySql备份与恢复,远程访问MySql服务器</p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"> </p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">七、把mysql的数据文件,移动到“数据盘”上,防止系统坏了重做系统时数据没有了。</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">-----------------------------------------------------</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">主要参考这篇文章:linux下MySQL安装配置及操作<span style="font-size: small;">  </span></span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">我再移mysql的数据文件后,使用<span style="font-size: small;">mysql -u用户名 -p  登录时,</span>遇到了错误 :ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">主要是修改my.cnf文件时有几步与上文不一样,这里说明一下。操作方法如下 :</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">1、停止mysql进程</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">2、把/var/lib/mysql整个目录移到/data0/db</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">mv /var/lib/mysql /home/data/</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">这样就把MySQL的数据文件移动到了/data0/db/mysql下</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">3、修改my.cnf配置文件</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">不要直接使用/etc/my.cnf配置文件,请到/usr/share/mysql/下找到*.cnf文件,拷贝其中一个(我是my-medium.cnf)到/etc/并改名为my.cnf)中。命令如下:</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">[root@test1 mysql]# cp /usr/share/mysql/my-medium.cnf /etc/my.cnf</span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;"> </span></p>
<p style="margin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 25.200000762939453px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="font-size: small;">4、编辑MySQL的配置文件/etc/my.cnf</span><

CENTOS 阿里云服务器磁盘扩容

<p><span style="font-size: 16px; color: rgb(178, 34, 34); font-family: 仿宋_gb2312;">我的<span style="cursor:pointer;border-bottom: 1px solid #FA891B;">系统</span>是centos 6.5 32位,数据盘挂载在/www/web目录下,所以扩容的方法和<span style="cursor:pointer;border-bottom: 1px solid #FA891B;"><span style="cursor: pointer;">阿里</span>云</span>官方的有所不同。</span></p><p><span style="font-size: 16px; color: rgb(178, 34, 34); font-family: 仿宋_gb2312;">备注:如果磁盘已有分两个区,需要把两个区都删除,才能扩容成功(开始一直扩不成功,后面删除2分区后,扩容成功)</span></p><p><span style="font-size: 16px; color: rgb(178, 34, 34); font-family: 仿宋_gb2312;">分区时,删除分区,需要马上新建,以免数据丢失</span></p><p><span style="font-size: 16px; color: rgb(178, 34, 34); font-family: 仿宋_gb2312;">====我还不知道,怎么重新分两个分区,扩容后只能分一个区。。额。。。忘高手指导!
</span></p><p><span style="font-size:16px"><span style="color: rgb(178, 34, 34); font-family: 仿宋_gb2312;"></span><span style="font-family:仿宋_gb2312 ">现将过程记录如下,以备以后使用,本人PHP猿人,LINUX小白。高手可以漂过</span></span></p><p><span style="font-size: 16px; font-family: 仿宋_gb2312;">以下是扩容过程:</span> 

<span style="font-size: 16px; font-family: 仿宋_gb2312;">    首先,做好快照(出现<span style="cursor:pointer;border-bottom: 1px solid #FA891B;">问题</span>好恢复),在后台扩容磁盘。</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;"> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">   </span><span style="font-family: 隶书,SimLi;"><span style="font-size: 16px;"> 1.进入 <span style="cursor: pointer; border-bottom: 1px solid rgb(250, 137, 27);">ECS</span> 控制台</span> <span style="font-size: 16px;"></span>
<span style="font-size: 16px;">    2.选择全部磁盘页或者本实例磁盘页</span> <span style="font-size: 16px;"></span>
<span style="font-size: 16px;">    3.在每一个磁盘条目的最后选择“更多”</span>
<span style="font-size: 16px;">    4.选择“磁盘扩容”,即可进入磁盘扩容<span style="cursor: pointer; border-bottom: 1px solid rgb(250, 137, 27);">操作</span>页</span>
<span style="font-size: 16px;">    5.输入你希望扩容的目标大小(我输入40G)</span>
<span style="font-size: 16px;">    6.提交扩容订单,按量付费的磁盘在下一个计价单位(目前是小时)开始按扩容后的磁盘大小计费;包年包月的磁盘则是补差价</span>
<span style="font-size: 16px;">    扩容仅做磁盘容量的扩大,不做分区和文件系统的扩大,扩容完成后,用户还需要手动分配存储空间。</span> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 18px; color: rgb(255, 0, 0); font-family: 黑体;">    新手难就难在磁盘扩容后的操作:</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;"> 
</span>
<span style="font-family: 隶书,SimLi;"><span style="font-size: 16px; font-family: 仿宋_gb2312;"> </span><span style="font-family: 隶书,SimLi; font-size: 16px;">   1、重启<span style="cursor: pointer; border-bottom: 1px solid rgb(250, 137, 27);">服务器</span>(reboot)</span>
<span style="font-family: 隶书,SimLi; font-size: 16px;">    2、umount /dev/xvdb1</span> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;"> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    结果我的提示错误device is busy 文件正在使用,考虑到可能是<span style="cursor:pointer;border-bottom: 1px solid #FA891B;">网站</span>还在运行,所以service mysqld stop,service httpd stop 停止相关服务</span></p><p><span style="font-size: 16px; font-family: 仿宋_gb2312;">--->再次运行umount /dev/xvdb1 就可以了。</span> 

<span style="font-size: 16px; font-family: 仿宋_gb2312;">   </span><span style="font-family: 隶书,SimLi;"><span style="font-size: 16px;"> 3、运行fdisk -l查看下磁盘号为/dev/xvdb1</span> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>

<span style="font-family: 隶书,SimLi;"><span style="font-size: 16px;">    4、删除原有分区并新建分区</span> 
<span style="font-size: 16px;">    使
用 fdisk 指令,fdisk /dev/xvdb
</span></span></p><p><span style="font-family: 隶书,SimLi;"><span style="font-size: 16px; font-family: 仿宋_gb2312;"> 输入 d 来删除原有的分区,然后依次输入 n,p,1(数字) 来新建分区,选择 sector
时,这边我们直接回车选择默认值,你也可以按照自己的需求来选择。为了保证数据的一致性,First sector 建议和之前的分区保持一致。</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    fdisk /dev/xvdb</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    d</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    n</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    p</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    1</span> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    回车两次出现Command (m for help)</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;"> 
</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    输入w</span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    提示:The partition table has been altered!</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">       Calling ioctl() to re-read partition table.</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">       Syncing disks.</span> 

<span style="font-size: 16px; font-family: 仿宋_gb2312;">    表示成功!</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    6.格式化磁盘</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    使用 resize2fs 指令扩大文件系统大小,原有数据不会丢失。</span> <span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    e2fsck -f /dev/xvdb1</span> <span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    resize2fs /dev/xvdb1</span> <span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    7.mount 磁盘</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    最后,我们再将扩容完毕的磁盘挂载回原有的挂载点</span> <span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    mount /dev/xvdb1 /www/web</span> <span style="font-size: 16px; font-family: 仿宋_gb2312;"></span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    (这个/www/web是我原来的挂载点)</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;"> </span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    8.用 df -vh 指令可以查看到磁盘的信息</span> 
<span style="font-size: 16px; font-family: 仿宋_gb2312;">    df -vh</span>
<span style="font-size: 16px; font-family: 仿宋_gb2312;">  为保险起见,reboot重启下看看是否正常。</span></p><p>
</p>

Apache 安装和虚拟主机的配置

<pre>web架构:
LAMPL=linuxA=apacheM=mysqlP=php
LNMPN=ngixL(A|N)MJtomcat|weblogic|jboss</pre>
<p style="text-align:left">==================================================================================
www.apache.org  官方网站
htp://www.jinbuguo.com/apache/menu22/index.html  中文帮助手册</p>
<p>==============================================================</p>
<p><span style="font-size:12px">软件三步曲: </span></p>
<p style="text-align:left"><span style="font-size:12px"># rpm -aq|grep httpd
httpd-tools-2.2.15-29.el6_4.x86_64 工具包
httpd-2.2.15-29.el6_4.x86_64   服务端软件</span></p>
<p><span style="font-size:12px">============================================================== </span></p>
<blockquote>
<p style="text-align:left"><span style="font-size:12px">yum -y install httpd-manual.noarch  安装英文帮助手册</span></p>
</blockquote>
<blockquote>
<pre>http://www.jinbuguo.com/apache/menu22/index.html<span style="font-size:12px"> 也可以看中文的手册</span></pre>
</blockquote>
<p><span style="font-size:12px">============================================================== </span></p>



<pre>安装过来相关的命令和文档

rmp -ql httpd

/etc/httpd 服务相关目录
/etc/httpd/conf 配置文件存放目录
/etc/httpd/conf.d 子配置文件相关目录
/etc/httpd/conf.d/README 说明
/etc/httpd/conf.d/welcome.conf 没有找到首页文件时,访问该文件
/etc/httpd/conf/httpd.conf 主配置文件

/etc/httpd/logs 日志文件存放目录 和/var/log/httpd 目录互为硬链接
/etc/httpd/modules 相关模块目录
/etc/httpd/run 进程文件
/etc/logrotate.d/httpd 日志轮巡
/etc/rc.d/init.d/htcacheclean apache自己的脚本文件
/etc/rc.d/init.d/httpd 启动脚本

/etc/sysconfig/httpd 额外配置文件
/usr/lib64/httpd 模块存放目录
/usr/lib64/httpd/modules

/usr/sbin/httpd 二进制命令
/var/www web服务的默认数据根目录

/var/www/error 页面错误文件目录
/var/www/error/README 说明</pre>



<p><span style="font-size:12px">配置虚拟主机</span></p>
<p><span style="font-size:12px">找到/etc/httpd/conf/httpd.conf  在最底部加上</span></p>
<blockquote>
<p><span style="font-size:12px"><span style="background-color:rgb(255, 255, 255); color:rgb(0, 0, 0); font-family:verdana,arial,helvetica,sans-serif">将里面的 </span><span style="background-color:rgb(255, 255, 255); color:rgb(0, 0, 255); font-family:verdana,arial,helvetica,sans-serif">#ServerName </span><span style="background-color:rgb(255, 255, 255); color:rgb(0, 0, 255); font-family:verdana,arial,helvetica,sans-serif">localhost:80</span><span style="background-color:rgb(255, 255, 255); color:rgb(0, 0, 0); font-family:verdana,arial,helvetica,sans-serif"> 注释去掉。</span></span></p>
</blockquote>
<blockquote>
<p><span style="font-size:12px">将#NameVirtualHost *:80修改成NameVirtualHost 172.16.12.158 ,注意别忘记了将句首的#去掉; </span></p>
</blockquote>
<p> </p>
<blockquote>
<p style="text-align:start">开启REWRITE</p>
<p style="text-align:start"><span style="font-size:12px"><Directory /></span></p>
<p style="text-align:start"><span style="font-size:12px">Options FollowSymLinks</span></p>
<p style="text-align:start"><span style="font-size:12px">AllowOverride None(修改为AllowOverride All)</span></p>
<p style="text-align:start"><span style="font-size:12px"></Directory></span></p>
</blockquote>
<blockquote>
<p><span style="font-size:12px"><VirtualHost 172.16.12.158:80>
   ServerAdmin root@example.com
    DocumentRoot /mnt/hgfs/html/wlaNews
    ServerName test.wl888.com
    ErrorLog logs/wlanews_error
   CustomLog logs/wlanews_ass common
</VirtualHost></span></p>
<p><span style="font-size:12px"><VirtualHost 172.16.12.158:80>
DocumentRoot "/mnt/hgfs/html/wlasmsg"
ServerName test.cooldreamer.com:80
        <Directory "/mnt/hgfs/html/wlasmsg">
         Options FollowSymLinks IncludesNOEXEC Indexes
         DirectoryIndex index.html index.htm default.htm index.php default.php index.cgi default.cgi index.pl default.pl index.shtml
         AllowOverride Options FileInfo
         Order Deny,Allow
         Allow from all
        </Directory>
</VirtualHost></span></p>
</blockquote>
<p> </p>


<p><span style="font-size:12px">失败相关注意点:</span></p>
<p><span style="font-size:12px">1,目录权限的问题</span></p>
<p><span style="font-size:12px">2.防火墙的设置</span></p>
<p><span style="font-size:12px">3,SELINUX 的设置</span></p>
<p> </p>


<pre>配置的相关说明
DocumentRoot "/var/www/html" 默认数据根目录
<Directory /> 给根目录授权

Options FollowSymLinks 支持软链接
AllowOverride None  不支持.htaccess文件控制

</Directory>

<Directory "/var/www/html">

Options Indexes FollowSymLinks 支持索引,支持软链接

AllowOverride None

Order allow,deny 先allow再deny 访问控制
Allow from all

</Directory>

Alias /error/ "/var/www/error/" 定义别名发布相应目录</pre>

正向代理与反向代理的区别

<p><br/></p><br/><h2>一、正向代理的概念</h2><p>  正向代理,也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。</p><p>  结论:<span style="color: #ff0000;">正向代理是一个位于客户端和原始服务器(origin
server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。
</span></p><h2>二、反向代理的概念</h2><p>  举例:用户想访问:"http://ooxx.me/readme",但ooxx.me上并不存在readme页面,他是偷偷从另外一台服务器上取回来,然后作为自己的内容吐给用户,但用户并不知情,这很正常,用户一般都很笨。这里所提到的ooxx.me
这个域名对应的服务器就设置了反向代理功能。</p><p>  结论:<span style="color: #ff0000;">反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样</span>。</p><h2>三、正向代理和反向代理的区别</h2><p>  从<span style="color: #ff0000;">用途</span>上来讲:<span style="color: #ff0000;">正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径</span>。正向代理还可以使用缓冲特性减少网络使用率。<span style="color: #ff0000;">反向代理的典型用途是将防火墙后面的服务器提供给Internet用户访问</span>。反向代理还可以为后端的多台服务器提供负载平衡,或为后端较慢的服务器提供缓冲服务。另外,反向代理还可以启用高级URL策略和管理技术,从而使处于不同web服务器系统的web页面同时存在于同一个URL空间下。</p><p>  从<span style="color: #ff0000;">安全性</span>来讲:<span style="color: #ff0000;">正向代理允许客户端通过它访问任意网站并且隐藏客户端自身</span>,因此你必须采取安全措施以确保仅为经过授权的客户端提供服务。<span style="color: #ff0000;">反向代理对外都是透明的,访问者并不知道自己访问的是一个代理</span>。</p><p>  打个比方,<span style="color: #ff0000;">a,b,c三个人,正向代理是a通过b向C借钱,a知道c的存在 。反向代理是a向b借钱,b又向C借,a不知道c的存在</span>。</p><p><br/></p>

wdcp中apache配置反向代理

<p>1,首先进入目录</p><pre class="brush:cpp;toolbar:false">cd /www/wdlinux/apache/conf/vhost
vim host.config</pre><p>2.修改配置文件</p><pre class="brush:cpp;toolbar:false"><VirtualHost *:88>
DocumentRoot 网站目录
ServerName 网站域名
ServerAlias 解析的网站域名
ErrorDocument 400 /errpage/400.html
ErrorDocument 403 /errpage/403.html
ErrorDocument 404 /errpage/404.html
ErrorDocument 503 /errpage/503.html
ProxyPass /  反向地址
ProxyPassReverse / 反向地址
</VirtualHost>
<Directory 网站目录>
    Options FollowSymLinks
    AllowOverride All
    Require all granted
</Directory></pre><p>===============</p><pre class="brush:cpp;toolbar:false"># Reverse Proxy  
  

 设置反向代理  

ProxyPass /foo http://foo.example.com/bar  

 设置反向代理使用代理服务的HOST重写内部原始服务器响应报文头中的Location和Content-Location  

ProxyPassReverse /foo http://foo.example.com/bar</pre><p><br/></p>

mac virtualbox centos 挂载分享的目录

<p>这段时间,改用MAC电脑开发。SO。。遇到的问题太多了,特别记录下。</p><p>1,virtualbox LINUX系统挂载MAC共享目录</p><p>刚开始用MAC ,共享的目录一直找不到,然后说是要安装<span style="color:rgb(57, 57, 57)">增强功能包VBoxLinuxAdditions,好像和WIN下面区别还是挺大的。</span></p><p>1.安装需要的环境</p><p>yum update</p><p>yum install gcc</p><p>yum install gcc-c++</p><p>yum install make</p><p>yum install kernel-headers</p><p>yum install kernel-devel</p><p>2.重启系统</p><p>reboot</p><p>3.挂载并安装 VBoxGuestAdditions.iso</p><p>需要加载VBoxGuestAdditions,virtualbox安装目录里面会有VBoxGuestAdditions.iso,或者到<span style="color:rgb(0, 56, 132)">http://download.virtualbox.org/virtualbox</span>下载对应版本的增强包</p><p>新增目录</p><p>mkdir /home/website</p><p>挂载到CD/DVD虚拟光驱</p><p>mount -t auto /dev/cdrom /home/website</p><p>(这里的cdrom是cd的,有时是dvd1,具体有什么光驱到 /dev目录下查看)</p><p>转到目录</p><p>cd /home/website</p><p>ls</p><p>此时看到列表中有VBoxLinuxAdditions.run说明挂载成功</p><p> </p><p>sh ./VBoxLinuxAdditions.run</p><p>等待安装完成</p><p>(如果安装结果提示内核错误,尝试 使用 yum update kernel 更新内核,需要reboot后安装VBoxLinuxAdditions)</p><p>最后 重启以使 GuestAddition 生效</p><p>reboot</p><p>4.共享文件夹</p><p>设备-〉共享文件夹</p><p>这里会有点要注意,<span style="color:#FF0000">如果你想自定义挂载目录,就不要勾选自动挂载</span>,因为我们在做开发时,都是自定义挂载目录</p><p>  自动义挂载</p><p><span style="color:#FF0000">mount -t vboxsf vm_share(共享文件夹名) /mnt/vm_share/  //挂载创建共享文件vm_share 到 /mnt/vm_share</span></p><p>若想删除挂载,可执行命令</p><p>umount <span style="color:rgb(0, 128, 128)">-f</span> /mnt/share</p><p>对于“开机自动挂载”模块,我试了好多遍都以失败告终,大部分网络资料都是说在 /etc/fstab 文件中追加</p><p>VirtualBox虚拟机文件夹共享挂载命令 sharing /mnt/share vboxsf defaults 0 0 ”,其实是错误的,</p><p>因为系统调用fstab的时候,Virtualbox的共享目录的模块还没有加载,所以每次加载都会失败,最终的解决方案如下:</p><p>在文件 /etc/rc.local 中(用root用户)追加如下命令</p><p><span style="color:#FF0000">mount -t vboxsf vm_share /mnt/vm_share/</span></p><p>最后重启系统,大功告成!!!</p><p><span style="color:rgb(223, 64, 42)">对权限的处理办法,在开发时,发现目录不可写。</span></p><p>首先查出执行程序的UID和GID</p><p>id -u user</p><p>如 id -u www 查看WWW所在的UID和GID 或 id www</p><p> </p><p>然后重新挂载</p><p>mount -t vboxsf -o uid=1000,gid=1000 vm_share /mnt/vm_share/</p><p>=========================================================</p><p>有点乱。。总结如下。</p><p>1,安装增强插件</p><p>2,自定义挂载共享文件夹</p><p><span style="color:#FF0000">mount -t vboxsf vm_share /mnt/vm_share/</span></p><p>3,开机自动挂载</p><p><span style="color:#FF0000">具体GID和UID,通过id -u user查找</span></p><p><span style="color:#FF0000">vim /etc/rc.local </span></p><p><span style="color:#FF0000">mount -t vboxsf -o uid=1000,gid=1000 vm_share /mnt/vm_share/</span></p><p>重启就可完成自动挂载</p><p><br/></p>

Sphinx 配置文件

<pre style="max-width:100%;overflow-x:auto;">#vim /usr/local/sphinx/etc/sphinx.conf

我的配置文件

source blog
{
type = mysql
sql_host = 127.0.0.1
sql_user =
sql_pass =
sql_db =
sql_query_pre = SET NAMES utf8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query = SELECT id,c_id,title,message,comments,add_time,create_date FROM thinkask_blog where status = 1
sql_attr_uint = c_id
sql_field_string = title
##sql_field_string = message ## 不要显示内容,太多了。。。。
sql_attr_timestamp = add_time
sql_ranged_throttle = 0

}

index blog
{
source = blog
path = /usr/local/sphinx/var/data/blog
docinfo = extern
mlock = 0
morphology = none
min_word_len = 1
html_strip = 1
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
}
searchd
{
listen = 9312
log = /usr/local/sphinx/var/log/searchd.log
query_log = /usr/local/sphinx/var/log/query.log
read_timeout = 5
max_children = 30
pid_file = /usr/local/sphinx/var/log/searchd.pid

seamless_rotate = 1
binlog_path = /usr/local/sphinx/var/data
}
</pre><div>
</div><pre><span class="hljs-comment">##请根据注释开启功能块。以下为网上查找,仅做对照使用</span>
<span class="hljs-comment">## 数据源src1</span>
<span class="hljs-built_in">source</span> src1
{

<span class="hljs-comment">## 说明数据源的类型。数据源的类型可以是:mysql,pgsql,mssql,xmlpipe,odbc,python</span>
<span class="hljs-comment">## 有人会奇怪,python是一种语言怎么可以成为数据源呢?</span>
<span class="hljs-comment">## python作为一种语言,可以操作任意其他的数据来源来获取数据,更多数据请看:(http://www.coreseek.cn/products-install/python/)</span>
<span class="hljs-built_in">type</span>            = mysql

<span class="hljs-comment">## 下面是sql数据库特有的端口,用户名,密码,数据库名等。</span>
sql_host        = localhost
sql_user        = root
sql_pass        = 
sql_db          = 
sql_port        = 3306

<span class="hljs-comment">## 如果是使用unix sock连接可以使用这个。</span>
<span class="hljs-comment"># sql_sock      = /tmp/mysql.sock</span>

<span class="hljs-comment">## indexer和mysql之间的交互,需要考虑到效率和安全性。</span>
<span class="hljs-comment">## 比如考虑到效率,他们两者之间的交互需要使用压缩协议;考虑到安全,他们两者之间的传输需要使用ssl</span>
<span class="hljs-comment">## 那么这个参数就代表这个意思,0/32/2048/32768  无/使用压缩协议/握手后切换到ssl/Mysql 4.1版本身份认证。</span>
<span class="hljs-comment"># mysql_connect_flags   = 32</span>

<span class="hljs-comment">## 当mysql_connect_flags设置为2048(ssl)的时候,下面几个就代表ssl连接所需要使用的几个参数。</span>
<span class="hljs-comment"># mysql_ssl_cert        = /etc/ssl/client-cert.pem</span>
<span class="hljs-comment"># mysql_ssl_key     = /etc/ssl/client-key.pem</span>
<span class="hljs-comment"># mysql_ssl_ca      = /etc/ssl/cacert.pem</span>

<span class="hljs-comment">## mssql特有,是否使用windows登陆</span>
<span class="hljs-comment"># mssql_winauth     = 1</span>

<span class="hljs-comment">## mssql特有,是使用unicode还是单字节数据。</span>
<span class="hljs-comment"># mssql_unicode     = 1 # request Unicode data from server</span>

<span class="hljs-comment">## odbc的dsn串</span>
<span class="hljs-comment"># odbc_dsn      = DBQ=C:\data;DefaultDir=C:\data;Driver={Microsoft Text Driver (*.txt; *.csv)};</span>

<span class="hljs-comment">## sql某一列的缓冲大小,一般是针对字符串来说的。</span>
<span class="hljs-comment">## 为什么要有这么一种缓冲呢?</span>
<span class="hljs-comment">## 有的字符串,虽然长度很长,但是实际上并没有使用那么长的字符,所以在Sphinx并不会收录所有的字符,而是给每个属性一个缓存作为长度限制。</span>
<span class="hljs-comment">## 默认情况下非字符类型的属性是1KB,字符类型的属性是1MB。</span>
<span class="hljs-comment">## 而如果想要配置这个buffer的话,就可以在这里进行配置了。</span>
<span class="hljs-comment"># sql_column_buffers    = content=12M, comments=1M</span>

<span class="hljs-comment">## indexer的sql执行前需要执行的操作。</span>
<span class="hljs-comment"># sql_query_pre     = SET NAMES utf8</span>
<span class="hljs-comment"># sql_query_pre     = SET SESSION query_cache_type=OFF</span>

<span class="hljs-comment">## indexer的sql执行语句</span>
sql_query              =SELECT id,title,message,create_date,<span class="hljs-built_in">source</span>,is_top FROM blog <span class="hljs-built_in">where</span> status=1

<span class="hljs-comment">## 有的时候有多个表,我们想要查询的字段在其他表中。这个时候就需要对sql_query进行join操作。</span>
<span class="hljs-comment">## 而这个join操作可能非常慢,导致建立索引的时候特别慢,那么这个时候,就可以考虑在sphinx端进行join操作了。</span>
<span class="hljs-comment">## sql_joined_field是增加一个字段,这个字段是从其他表查询中查询出来的。</span>
<span class="hljs-comment">## 这里封号后面的查询语句是有要求的,如果是query,则返回id和查询字段,如果是payload-query,则返回id,查询字段和权重。</span>
<span class="hljs-comment">## 并且这里的后一个查询需要按照id进行升序排列。</span>
<span class="hljs-comment"># sql_joined_field  = tags from query; SELECT docid, CONCAT('tag',tagid) FROM tags ORDER BY docid ASC</span>
<span class="hljs-comment"># sql_joined_field  = wtags from payload-query; SELECT docid, tag, tagweight FROM tags ORDER BY docid ASC</span>

<span class="hljs-comment">## 外部文件字段,意思就是一个表中,有一个字段存的是外部文件地址,但是实际的字段内容在文件中。比如这个字段叫做content_file_path。</span>
<span class="hljs-comment">## 当indexer建立索引的时候,查到这个字段,就读取这个文件地址,然后加载,并进行分词和索引建立等操作。</span>
<span class="hljs-comment"># sql_file_field        = content_file_path</span>

<span class="hljs-comment">## 当数据源数据太大的时候,一个sql语句查询下来往往很有可能锁表等操作。</span>
<span class="hljs-comment">## 那么我么就可以使用多次查询,那么这个多次查询就需要有个范围和步长,sql_query_range和sql_range_step就是做这个使用的。</span>
<span class="hljs-comment">## 获取最大和最小的id,然后根据步长来获取数据。比如下面的例子,如果有4500条数据,这个表建立索引的时候就会进行5次sql查询。 </span>
<span class="hljs-comment">## 而5次sql查询每次的间隔时间是使用sql_ranged_rhrottle来进行设置的。单位是毫秒。</span>
<span class="hljs-comment"># sql_query_range       = SELECT MIN(id),MAX(id) FROM documents</span>
<span class="hljs-comment"># sql_range_step        = 1000</span>
<span class="hljs-comment"># sql_ranged_throttle   = 0</span>

<span class="hljs-comment">## 下面都是些不同属性的数据了</span>
<span class="hljs-comment">## 先要了解属性的概念:属性是存在索引中的,它不进行全文索引,但是可以用于过滤和排序。</span>

<span class="hljs-comment">## uint无符号整型属性</span>
<span class="hljs-comment">#sql_attr_uint       = group_id</span>

<span class="hljs-comment">## bool属性</span>
<span class="hljs-comment"># sql_attr_bool     = is_deleted</span>

<span class="hljs-comment">## 长整型属性</span>
<span class="hljs-comment"># sql_attr_bigint       = my_bigint_id</span>

<span class="hljs-comment">## 时间戳属性,经常被用于做排序</span>
sql_attr_timestamp  = create_date

<span class="hljs-comment">## 字符串排序属性。一般我们按照字符串排序的话,我们会将这个字符串存下来进入到索引中,然后在查询的时候比较索引中得字符大小进行排序。</span>
<span class="hljs-comment">## 但是这个时候索引就会很大,于是我们就想到了一个方法,我们在建立索引的时候,先将字符串值从数据库中取出,暂存,排序。</span>
<span class="hljs-comment">## 然后给排序后的数组分配一个序号,然后在建立索引的时候,就将这个序号存入到索引中去。这样在查询的时候也就能完成字符串排序的操作。</span>
<span class="hljs-comment">## 这,就是这个字段的意义。</span>
<span class="hljs-comment"># sql_attr_str2ordinal  = author_name</span>

<span class="hljs-comment">## 浮点数属性,经常在查询地理经纬度的时候会用到。</span>
<span class="hljs-comment"># sql_attr_float        = lat_radians</span>
<span class="hljs-comment"># sql_attr_float        = long_radians</span>

<span class="hljs-comment">## 多值属性(MVA)</span>
<span class="hljs-comment">## 试想一下,有一个文章系统,每篇文章都有多个标签,这个文章就叫做多值属性。</span>
<span class="hljs-comment">## 我要对某个标签进行查询过滤,那么在建立查询的时候就应该把这个标签的值放入到索引中。</span>
<span class="hljs-comment">## 这个字段,sql_attr_multi就是用来做这个事情的。</span>
<span class="hljs-comment"># sql_attr_multi        = uint tag from query; SELECT docid, tagid FROM tags</span>
<span class="hljs-comment"># sql_attr_multi        = uint tag from ranged-query; \</span>
<span class="hljs-comment">#   SELECT docid, tagid FROM tags WHERE id&gt;=$start AND id&lt;=$end; \</span>
<span class="hljs-comment">#   SELECT MIN(docid), MAX(docid) FROM tags</span>

<span class="hljs-comment">## 字符串属性。</span>
<span class="hljs-comment"># sql_attr_string       = stitle</span>

<span class="hljs-comment">## 文档词汇数记录属性。比如下面就是在索引建立的时候增加一个词汇数的字段</span>
<span class="hljs-comment"># sql_attr_str2wordcount    = stitle</span>

<span class="hljs-comment">## 字符串字段,可全文搜索,可返回原始文本信息。</span>
<span class="hljs-comment"># sql_field_string  = author</span>

<span class="hljs-comment">## 文档词汇数记录字段,可全文搜索,可返回原始信息</span>
<span class="hljs-comment"># sql_field_str2wordcount   = title</span>

<span class="hljs-comment">## 取后查询,在sql_query执行后立即操作。</span>
<span class="hljs-comment">## 它和sql_query_post_index的区别就是执行时间不同</span>
<span class="hljs-comment">## sql_query_post是在sql_query执行后执行,而sql_query_post_index是在索引建立完成后才执行。</span>
<span class="hljs-comment">## 所以如果要记录最后索引执行时间,那么应该在sql_query_post_index中执行。</span>
<span class="hljs-comment"># sql_query_post        =</span>

<span class="hljs-comment">## 参考sql_query_post的说明。</span>
<span class="hljs-comment"># sql_query_post_index  = REPLACE INTO counters ( id, val ) \</span>
<span class="hljs-comment">#   VALUES ( 'max_indexed_id', $maxid )</span>

<span class="hljs-comment">## 命令行获取信息查询。</span>
<span class="hljs-comment">## 什么意思呢?</span>
<span class="hljs-comment">## 我们进行索引一般只会返回主键id,而不会返回表中的所有字段。</span>
<span class="hljs-comment">## 但是在调试的时候,我们一般需要返回表中的字段,那这个时候,就需要使用sql_query_info。</span>
<span class="hljs-comment">## 同时这个字段只在控制台有效,在api中是无效的。</span>
sql_query_info      = SELECT * FROM documents WHERE id=<span class="hljs-variable">$id</span>

<span class="hljs-comment">## 比如有两个索引,一个索引比较旧,一个索引比较新,那么旧索引中就会有数据是旧的。</span>
<span class="hljs-comment">## 当我要对两个索引进行搜索的时候,哪些数据要按照新的索引来进行查询呢。</span>
<span class="hljs-comment">## 这个时候就使用到了这个字段了。</span>
<span class="hljs-comment">## 这里的例子(http://www.coreseek.cn/docs/coreseek_4.1-sphinx_2.0.1-beta.html#conf-sql-query-killlist)给的非常清晰了。</span>
<span class="hljs-comment"># sql_query_killlist    = SELECT id FROM documents WHERE edited&gt;=@last_reindex</span>

<span class="hljs-comment">## 下面几个压缩解压的配置都是为了一个目的:让索引重建的时候不要影响数据库的性能表现。</span>
<span class="hljs-comment">## SQL数据源解压字段设置</span>
<span class="hljs-comment"># unpack_zlib       = zlib_column</span>
<span class="hljs-comment">## MySQL数据源解压字段设置</span>
<span class="hljs-comment"># unpack_mysqlcompress  = compressed_column</span>
<span class="hljs-comment"># unpack_mysqlcompress  = compressed_column_2</span>
<span class="hljs-comment">## MySQL数据源解压缓冲区设置</span>
<span class="hljs-comment"># unpack_mysqlcompress_maxsize  = 16M</span>


<span class="hljs-comment">## xmlpipe的数据源就是一个xml文档</span>
<span class="hljs-comment"># type          = xmlpipe</span>

<span class="hljs-comment">## 读取数据源的命令</span>
<span class="hljs-comment"># xmlpipe_command       = cat /usr/local/sphinx/var/test.xml</span>

<span class="hljs-comment">## 字段</span>
<span class="hljs-comment"># xmlpipe_field     = subject</span>
<span class="hljs-comment"># xmlpipe_field     = content</span>

<span class="hljs-comment">## 属性</span>
<span class="hljs-comment"># xmlpipe_attr_timestamp    = published</span>
<span class="hljs-comment"># xmlpipe_attr_uint = author_id</span>

<span class="hljs-comment">## UTF-8修复设置</span>
<span class="hljs-comment">## 只适用xmlpipe2数据源,数据源中有可能有非utf-8的字符,这个时候解析就有可能出现问题</span>
<span class="hljs-comment">## 如果设置了这个字段,非utf-8序列就会全部被替换为空格。</span>
<span class="hljs-comment"># xmlpipe_fixup_utf8    = 1</span>

}

<span class="hljs-comment">## sphinx的source是有继承这么一种属性的,意思就是除了父source之外,这个source还有这个特性</span>
<span class="hljs-built_in">source</span> src1throttled : src1
{

sql_ranged_throttle = 100

}

<span class="hljs-comment">## 索引test1</span>
index <span class="hljs-built_in">test</span>1
{

<span class="hljs-comment">## 索引类型,包括有plain,distributed和rt。分别是普通索引/分布式索引/增量索引。默认是plain。</span>
<span class="hljs-comment"># type          = plain</span>

<span class="hljs-comment">## 索引数据源</span>
<span class="hljs-built_in">source</span>          = src1
<span class="hljs-comment">## 索引文件存放路径</span>
path            = /usr/<span class="hljs-built_in">local</span>/sphinx/var/data/<span class="hljs-built_in">test</span>1

<span class="hljs-comment">## 文档信息的存储模式,包括有none,extern,inline。默认是extern。</span>
<span class="hljs-comment">## docinfo指的就是数据的所有属性(field)构成的一个集合。</span>
<span class="hljs-comment">## 首先文档id是存储在一个文件中的(spa)</span>
<span class="hljs-comment">## 当使用inline的时候,文档的属性和文件的id都是存放在spa中的,所以进行查询过滤的时候,不需要进行额外操作。</span>
<span class="hljs-comment">## 当使用extern的时候,文档的属性是存放在另外一个文件(spd)中的,但是当启动searchd的时候,会把这个文件加载到内存中。</span>
<span class="hljs-comment">## extern就意味着每次做查询过滤的时候,除了查找文档id之外,还需要去内存中根据属性进行过滤。</span>
<span class="hljs-comment">## 但是即使这样,extern由于文件大小小,效率也不低。所以不是有特殊要求,一般都是使用extern</span>
docinfo         = extern

<span class="hljs-comment">## 缓冲内存锁定。</span>
<span class="hljs-comment">## searchd会讲spa和spi预读取到内存中。但是如果这部分内存数据长时间没有访问,则它会被交换到磁盘上。</span>
<span class="hljs-comment">## 设置了mlock就不会出现这个问题,这部分数据会一直存放在内存中的。</span>
mlock           = 0

<span class="hljs-comment">## 词形处理器</span>
<span class="hljs-comment">## 词形处理是什么意思呢?比如在英语中,dogs是dog的复数,所以dog是dogs的词干,这两个实际上是同一个词。</span>
<span class="hljs-comment">## 所以英语的词形处理器会讲dogs当做dog来进行处理。</span>
morphology      = none

<span class="hljs-comment">## 词形处理有的时候会有问题,比如将gps处理成gp,这个设置可以允许根据词的长度来决定是否要使用词形处理器。</span>
<span class="hljs-comment"># min_stemming_len  = 1</span>

<span class="hljs-comment">## 词形处理后是否还要检索原词?</span>
<span class="hljs-comment"># index_exact_words = 1</span>

<span class="hljs-comment">## 停止词,停止词是不被索引的词。</span>
<span class="hljs-comment"># stopwords     = /usr/local/sphinx/var/data/stopwords.txt</span>

<span class="hljs-comment">## 自定义词形字典</span>
<span class="hljs-comment"># wordforms     = /usr/local/sphinx/var/data/wordforms.txt</span>

<span class="hljs-comment">## 词汇特殊处理。</span>
<span class="hljs-comment">## 有的一些特殊词我们希望把它当成另外一个词来处理。比如,c++ =&gt; cplusplus来处理。</span>
<span class="hljs-comment"># exceptions        = /usr/local/sphinx/var/data/exceptions.txt</span>

<span class="hljs-comment">## 最小索引词长度,小于这个长度的词不会被索引。</span>
min_word_len        = 1

<span class="hljs-comment">## 字符集编码类型,可以为sbcs,utf-8。对于Coreseek,还可以有zh_cn.utf-8,zh_ch.gbk,zh_ch.big5</span>
charset_<span class="hljs-built_in">type</span>        = sbcs

<span class="hljs-comment">## 字符表和大小写转换规则。对于Coreseek,这个字段无效。</span>
<span class="hljs-comment"># 'sbcs' default value is</span>
<span class="hljs-comment"># charset_table     = 0..9, A..Z-&gt;a..z, _, a..z, U+A8-&gt;U+B8, U+B8, U+C0..U+DF-&gt;U+E0..U+FF, U+E0..U+FF</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># 'utf-8' default value is</span>
<span class="hljs-comment"># charset_table     = 0..9, A..Z-&gt;a..z, _, a..z, U+410..U+42F-&gt;U+430..U+44F, U+430..U+44F</span>

<span class="hljs-comment">## 忽略字符表。在忽略字符表中的前后词会被连起来当做一个单独关键词处理。</span>
 ignore_chars      = U+00AD

<span class="hljs-comment">## 是否启用通配符,默认为0,不启用</span>
<span class="hljs-comment"># enable_star       = 1</span>

<span class="hljs-comment">## min_prefix_len,min_infix_len,prefix_fields,infix_fields都是在enable_star开启的时候才有效果。</span>
<span class="hljs-comment">## 最小前缀索引长度</span>
<span class="hljs-comment">## 为什么要有这个配置项呢?</span>
<span class="hljs-comment">## 首先这个是当启用通配符配置启用的前提下说的,前缀索引使得一个关键词产生了多个索引项,导致索引文件体积和搜索时间增加巨大。</span>
<span class="hljs-comment">## 那么我们就有必要限制下前缀索引的前缀长度,比如example,当前缀索引长度设置为5的时候,它只会分解为exampl,example了。</span>
<span class="hljs-comment"># min_prefix_len        = 0</span>
<span class="hljs-comment">## 最小索引中缀长度。理解同上。</span>
<span class="hljs-comment"># min_infix_len     = 0</span>

<span class="hljs-comment">## 前缀索引和中缀索引字段列表。并不是所有的字段都需要进行前缀和中缀索引。</span>
<span class="hljs-comment"># prefix_fields     = filename</span>
<span class="hljs-comment"># infix_fields      = url, domain</span>

<span class="hljs-comment">## 词汇展开</span>
<span class="hljs-comment">## 是否尽可能展开关键字的精确格式或者型号形式</span>
<span class="hljs-comment"># expand_keywords       = 1</span>

<span class="hljs-comment">## N-Gram索引的分词技术</span>
<span class="hljs-comment">## N-Gram是指不按照词典,而是按照字长来分词,这个主要是针对非英文体系的一些语言来做的(中文、韩文、日文)</span>
<span class="hljs-comment">## 对coreseek来说,这两个配置项可以忽略。</span>
<span class="hljs-comment"># ngram_len     = 1</span>
<span class="hljs-comment"># ngram_chars       = U+3000..U+2FA1F</span>

<span class="hljs-comment">## 词组边界符列表和步长</span>
<span class="hljs-comment">## 哪些字符被看做分隔不同词组的边界。</span>
<span class="hljs-comment"># phrase_boundary       = ., ?, !, U+2026 # horizontal ellipsis</span>
<span class="hljs-comment"># phrase_boundary_step  = 100</span>

<span class="hljs-comment">## 混合字符列表</span>
<span class="hljs-comment"># blend_chars       = +, &amp;, U+23</span>
<span class="hljs-comment"># blend_mode        = trim_tail, skip_pure</span>

<span class="hljs-comment">## html标记清理,是否从输出全文数据中去除HTML标记。</span>
html_strip      = 0

<span class="hljs-comment">## HTML标记属性索引设置。</span>
<span class="hljs-comment"># html_index_attrs  = img=alt,title; a=title;</span>

<span class="hljs-comment">## 需要清理的html元素</span>
<span class="hljs-comment"># html_remove_elements  = style, script</span>

<span class="hljs-comment">## searchd是预先打开全部索引还是每次查询再打开索引。</span>
<span class="hljs-comment"># preopen           = 1</span>

<span class="hljs-comment">## 字典文件是保持在磁盘上还是将他预先缓冲在内存中。</span>
<span class="hljs-comment"># ondisk_dict       = 1</span>

<span class="hljs-comment">## 由于在索引建立的时候,需要建立临时文件和和副本,还有旧的索引</span>
<span class="hljs-comment">## 这个时候磁盘使用量会暴增,于是有个方法是临时文件重复利用</span>
<span class="hljs-comment">## 这个配置会极大减少建立索引时候的磁盘压力,代价是索引建立速度变慢。</span>
<span class="hljs-comment"># inplace_enable        = 1</span>
<span class="hljs-comment"># inplace_hit_gap       = 0 # preallocated hitlist gap size</span>
<span class="hljs-comment"># inplace_docinfo_gap   = 0 # preallocated docinfo gap size</span>
<span class="hljs-comment"># inplace_reloc_factor  = 0.1 # relocation buffer size within arena</span>
<span class="hljs-comment"># inplace_write_factor  = 0.1 # write buffer size within arena</span>

<span class="hljs-comment">## 在经过过短的位置后增加位置值</span>
<span class="hljs-comment"># overshort_step        = 1</span>

<span class="hljs-comment">## 在经过 停用词 处后增加位置值</span>
<span class="hljs-comment"># stopword_step     = 1</span>

<span class="hljs-comment">## 位置忽略词汇列表</span>
<span class="hljs-comment"># hitless_words     = all</span>
<span class="hljs-comment"># hitless_words     = hitless.txt</span>

<span class="hljs-comment">## 是否检测并索引句子和段落边界</span>
<span class="hljs-comment"># index_sp          = 1</span>

<span class="hljs-comment">## 字段内需要索引的HTML/XML区域的标签列表</span>
<span class="hljs-comment"># index_zones       = title, h*, th</span>

}

index <span class="hljs-built_in">test</span>1stemmed : <span class="hljs-built_in">test</span>1
{

path            = /usr/<span class="hljs-built_in">local</span>/sphinx/var/data/<span class="hljs-built_in">test</span>1stemmed
morphology      = stem_en

}

index dist1
{

<span class="hljs-built_in">type</span>            = distributed

<span class="hljs-built_in">local</span>           = <span class="hljs-built_in">test</span>1
<span class="hljs-built_in">local</span>           = <span class="hljs-built_in">test</span>1stemmed

<span class="hljs-comment">## 分布式索引(distributed index)中的远程代理和索引声明</span>
agent           = localhost:9313:remote1
agent           = localhost:9314:remote2,remote3
<span class="hljs-comment"># agent         = /var/run/searchd.sock:remote4</span>

<span class="hljs-comment">## 分布式索引( distributed index)中声明远程黑洞代理</span>
<span class="hljs-comment"># agent_blackhole       = testbox:9312:testindex1,testindex2</span>

<span class="hljs-comment">## 远程代理的连接超时时间</span>
agent_connect_timeout   = 1000

<span class="hljs-comment">## 远程查询超时时间</span>
agent_query_timeout = 3000

}

index rt
{

<span class="hljs-built_in">type</span>            = rt
path            = /usr/<span class="hljs-built_in">local</span>/sphinx/var/data/rt
<span class="hljs-comment">## RT索引内存限制</span>
<span class="hljs-comment"># rt_mem_limit      = 512M</span>
<span class="hljs-comment">## 全文字段定义</span>
rt_field        = title
rt_field        = content
<span class="hljs-comment">## 无符号整数属性定义</span>
rt_attr_uint        = gid
<span class="hljs-comment">## 各种属性定义</span>
<span class="hljs-comment"># rt_attr_bigint        = guid</span>
<span class="hljs-comment"># rt_attr_float     = gpa</span>
<span class="hljs-comment"># rt_attr_timestamp = ts_added</span>
<span class="hljs-comment"># rt_attr_string        = author</span>

}

indexer
{

<span class="hljs-comment">## 建立索引的时候,索引内存限制</span>
mem_<span class="hljs-built_in">limit</span>       = 32M

<span class="hljs-comment">## 每秒最大I/O操作次数,用于限制I/O操作</span>
<span class="hljs-comment"># max_iops      = 40</span>

<span class="hljs-comment">## 最大允许的I/O操作大小,以字节为单位,用于I/O节流</span>
<span class="hljs-comment"># max_iosize        = 1048576</span>

<span class="hljs-comment">## 对于XMLLpipe2数据源允许的最大的字段大小,以字节为单位</span>
<span class="hljs-comment"># max_xmlpipe2_field    = 4M</span>

<span class="hljs-comment">## 写缓冲区的大小,单位是字节</span>
<span class="hljs-comment"># write_buffer      = 1M</span>

<span class="hljs-comment">## 文件字段可用的最大缓冲区大小,字节为单位</span>
<span class="hljs-comment"># max_file_field_buffer = 32M</span>

}

<span class="hljs-comment">## 搜索服务配置</span>
searchd
{

<span class="hljs-comment"># listen            = 127.0.0.1</span>
<span class="hljs-comment"># listen            = 192.168.0.1:9312</span>
<span class="hljs-comment"># listen            = 9312</span>
<span class="hljs-comment"># listen            = /var/run/searchd.sock</span>

<span class="hljs-comment">## 监听端口</span>
listen          = 9312
listen          = 9306:mysql41

<span class="hljs-comment">## 监听日志</span>
<span class="hljs-built_in">log</span>         = /usr/<span class="hljs-built_in">local</span>/sphinx/var/<span class="hljs-built_in">log</span>/searchd.log

<span class="hljs-comment">## 查询日志</span>
query_<span class="hljs-built_in">log</span>       = /usr/<span class="hljs-built_in">local</span>/sphinx/var/<span class="hljs-built_in">log</span>/query.log

<span class="hljs-comment">## 客户端读超时时间 </span>
<span class="hljs-built_in">read</span>_timeout        = 5

<span class="hljs-comment">## 客户端持久连接超时时间,即客户端读一次以后,持久连接,然后再读一次。中间这个持久连接的时间。</span>
client_timeout      = 300

<span class="hljs-comment">## 并行执行搜索的数目</span>
max_children        = 30

<span class="hljs-comment">## 进程id文件</span>
pid_file        = /usr/<span class="hljs-built_in">local</span>/sphinx/var/<span class="hljs-built_in">log</span>/searchd.pid

<span class="hljs-comment">## 守护进程在内存中为每个索引所保持并返回给客户端的匹配数目的最大值</span>
max_matches     = 1000

<span class="hljs-comment">## 无缝轮转。防止 searchd 轮换在需要预取大量数据的索引时停止响应</span>
<span class="hljs-comment">## 当进行索引轮换的时候,可能需要消耗大量的时间在轮换索引上。</span>
<span class="hljs-comment">## 但是启动了无缝轮转,就以消耗内存为代价减少轮转的时间</span>
seamless_rotate     = 1

<span class="hljs-comment">## 索引预开启,是否强制重新打开所有索引文件</span>
preopen_indexes     = 1

<span class="hljs-comment">## 索引轮换成功之后,是否删除以.old为扩展名的索引拷贝</span>
unlink_old      = 1

<span class="hljs-comment">## 属性刷新周期</span>
<span class="hljs-comment">## 就是使用UpdateAttributes()更新的文档属性每隔多少时间写回到磁盘中。</span>
<span class="hljs-comment"># attr_flush_period = 900</span>

<span class="hljs-comment">## 索引字典存储方式</span>
<span class="hljs-comment"># ondisk_dict_default   = 1</span>

<span class="hljs-comment">## 用于多值属性MVA更新的存储空间的内存共享池大小</span>
mva_updates_pool    = 1M

<span class="hljs-comment">## 网络通讯时允许的最大的包的大小</span>
max_packet_size     = 8M

<span class="hljs-comment">## 崩溃日志文件</span>
<span class="hljs-comment"># crash_log_path        = /usr/local/sphinx/var/log/crash</span>

<span class="hljs-comment">## 每次查询允许设置的过滤器的最大个数</span>
max_filters     = 256

<span class="hljs-comment">## 单个过滤器允许的值的最大个数</span>
max_filter_values   = 4096

<span class="hljs-comment">## TCP监听待处理队列长度</span>
<span class="hljs-comment"># listen_backlog        = 5</span>

<span class="hljs-comment">## 每个关键字的读缓冲区的大小</span>
<span class="hljs-comment"># read_buffer       = 256K</span>

<span class="hljs-comment">## 无匹配时读操作的大小</span>
<span class="hljs-comment"># read_unhinted     = 32K</span>

<span class="hljs-comment">## 每次批量查询的查询数限制</span>
max_batch_queries   = 32

<span class="hljs-comment">## 每个查询的公共子树文档缓存大小</span>
<span class="hljs-comment"># subtree_docs_cache    = 4M</span>

<span class="hljs-comment">## 每个查询的公共子树命中缓存大小</span>
<span class="hljs-comment"># subtree_hits_cache    = 8M</span>

<span class="hljs-comment">## 多处理模式(MPM)。 可选项;可用值为none、fork、prefork,以及threads。 默认在Unix类系统为form,Windows系统为threads。</span>
workers         = threads <span class="hljs-comment"># for RT to work</span>

<span class="hljs-comment">## 并发查询线程数</span>
<span class="hljs-comment"># dist_threads      = 4</span>

<span class="hljs-comment">## 二进制日志路径</span>
<span class="hljs-comment"># binlog_path       = # disable logging</span>
<span class="hljs-comment"># binlog_path       = /usr/local/sphinx/var/data # binlog.001 etc will be created there</span>

<span class="hljs-comment">## 二进制日志刷新</span>
<span class="hljs-comment"># binlog_flush      = 2</span>

<span class="hljs-comment">## 二进制日志大小限制</span>
<span class="hljs-comment"># binlog_max_log_size   = 256M</span>

<span class="hljs-comment">## 线程堆栈</span>
<span class="hljs-comment"># thread_stack          = 128K</span>

<span class="hljs-comment">## 关键字展开限制</span>
<span class="hljs-comment"># expansion_limit       = 1000</span>

<span class="hljs-comment">## RT索引刷新周期 </span>
<span class="hljs-comment"># rt_flush_period       = 900</span>

<span class="hljs-comment">## 查询日志格式</span>
<span class="hljs-comment">## 可选项,可用值为plain、sphinxql,默认为plain。 </span>
<span class="hljs-comment"># query_log_format      = sphinxql</span>

<span class="hljs-comment">## MySQL版本设置</span>
<span class="hljs-comment"># mysql_version_string  = 5.0.37</span>

<span class="hljs-comment">## 插件目录</span>
<span class="hljs-comment"># plugin_dir            = /usr/local/sphinx/lib</span>

<span class="hljs-comment">## 服务端默认字符集</span>
<span class="hljs-comment"># collation_server      = utf8_general_ci</span>
<span class="hljs-comment">## 服务端libc字符集</span>
<span class="hljs-comment"># collation_libc_locale = ru_RU.UTF-8</span>

<span class="hljs-comment">## 线程服务看守</span>
<span class="hljs-comment"># watchdog              = 1</span>
<span class="hljs-comment">## 兼容模式</span>
<span class="hljs-comment"># compat_sphinxql_magics    = 1</span>

}</pre><p>
</p><p>
</p>

coreseek/php-sphinx拓展安装

<h3>安装coreseek</h3><p>官网coreseek.cn 现在已打不开。。。。</p><p>Coreseek是现在用的最多的sphinx中文全文检索,它提供了为Sphinx设计的中文分词包LibMMSeg 。并提供了多个系统的二进制发行版,其中有rpm,deb及windows下的二进制包</p><p>PDF手册地址<a href="https://soft.thinkask.cn/sphinx/CoreSeekSphinx.pdf" target="_blank">:https://soft.thinkask.cn/sphinx/CoreSeekSphinx.pdf</a></p><pre><code class="hljs coffeescript" codemark="1">wget https:<span class="hljs-regexp">//</span>soft.thinkask.cn/sphinx/coreseek<span class="hljs-number">-4.1</span>-beta.tar.gz
tar zvxf coreseek<span class="hljs-number">-4.1</span>-beta.tar.gz
<span class="hljs-comment">##解压里有2个文件夹 一个是mmseg中文分词包 还有一个是csft(其实就是sphinx)包 都要安装</span>
<span class="hljs-comment">##先安装mmseg</span>
cd coreseek<span class="hljs-number">-4.1</span>-beta<span class="hljs-regexp">/mmseg-3.2.14/</span>
./bootstrap <span class="hljs-comment">#输出的warning信息可以忽略,如果出现error则需要解决</span>
./configure --prefix=/usr/local/mmseg3 <span class="hljs-comment">#配置</span>
make &&make install
<span class="hljs-comment">##安装csft</span>
cd coreseek<span class="hljs-number">-4.1</span>-beta<span class="hljs-regexp">/csft-4.1/</span>
sh buildconf.sh <span class="hljs-comment">#输出的warning信息可以忽略,如果出现error则需要解决</span>
.<span class="hljs-regexp">/configure --prefix=/usr/local/coreseek --without-python --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/</span> --with-mmseg-libs=<span class="hljs-regexp">/usr/local/mmseg3/lib/</span> --with-mysql <span class="hljs-comment">#配置</span>
make && make install

报错。。。额
sphinxexpr.cpp:<span class="hljs-number">1080</span>:<span class="hljs-number">43</span>: error: ‘ExprEval’ was <span class="hljs-keyword">not</span> declared <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span> scope, <span class="hljs-keyword">and</span> <span class="hljs-literal">no</span> declarations were found <span class="hljs-keyword">by</span> argument-dependent lookup at the point <span class="hljs-keyword">of</span> instantiation [-fpermissive]
T val = ExprEval ( <span class="hljs-keyword">this</span>->m_pArg, tMatch ); <span class="hljs-regexp">//</span> <span class="hljs-string">'this'</span> fixes gcc braindamage
<span class="hljs-comment">#这个问题是因为 gcc 版本高于 4.7 造成的</span>
找到csft<span class="hljs-number">-4.1</span>/src/sphinxexpr.cpp 的<span class="hljs-number">1823</span>/<span class="hljs-number">1746</span>/<span class="hljs-number">1777</span>行,将ExprEval修改为<span class="hljs-keyword">this</span>->ExprEval之后重新执行 make && make install 即可

安装完毕后 注意 coreseek 中的配置文件也是csft.conf 而不是 sphinx.conf
cd /usr/local/coreseek/etc
cp sphinx.conf.dist csft.conf
vim csft.conf<span class="hljs-comment">#修改配置csft.conf,增加对中文支持,在index test1 段下面,增加</span>
charset_type = zh_cn.utf<span class="hljs-number">-8</span><span class="hljs-comment">#如果系统locale预先设置好字符集为zh_CN.UTF-8,不要此项,会报错。 </span>
charset_dictpath =<span class="hljs-regexp">/usr/local/mmseg/etc/</span>
</code></pre><h3>测试</h3><pre><code class="hljs sql" codemark="1">
在vim下搜索 /sql_host (告诉sphinx mysql链接信息)

    sql_host                = localhost     //服务器名
    sql_user                = &amp;nbsp;&amp;nbsp;&amp;nbsp; //数据库账户
    sql_pass                = &amp;nbsp;&amp;nbsp;&amp;nbsp; //数据库密码
    sql_db                  = test          //使用sphinx 库名
    sql_port                = 3306  # optional, default is 3306

 在vim下搜索   /sql_query_pre
 打开下面配置的注释
 sql_query_pre          = &lt;span class=&quot;hljs-keyword&quot;&gt;SET&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;NAMES&lt;/span&gt; utf8

 在vim下搜索 /sql_query   找到下面内容在每行前面加#注释掉
 sql_query                              = \
 &lt;span class=&quot;hljs-keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;id&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;group_id&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;UNIX_TIMESTAMP&lt;/span&gt;(date_added) &lt;span class=&quot;hljs-keyword&quot;&gt;AS&lt;/span&gt; date_added, title, &lt;span class=&quot;hljs-keyword&quot;&gt;content&lt;/span&gt; \
            &lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; documents
 
 在上面内容改成下面添加个人数据表
 &lt;span class=&quot;hljs-keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;id&lt;/span&gt;,title,&lt;span class=&quot;hljs-keyword&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; sphinx

 搜索/charset_type 修改成:
 charset_type            = zh_cn.utf&lt;span class=&quot;hljs-number&quot;&gt;-8&lt;/span&gt;
 在上面内容下面加上词典目录
 charset_dictpath        = /usr/&lt;span class=&quot;hljs-keyword&quot;&gt;local&lt;/span&gt;/mmseg3/etc/

 /_info   搜索_info找到
  sql_query_info          = &lt;span class=&quot;hljs-keyword&quot;&gt;SELECT&lt;/span&gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; documents &lt;span class=&quot;hljs-keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;id&lt;/span&gt;=$&lt;span class=&quot;hljs-keyword&quot;&gt;id&lt;/span&gt;
 修改成:
  sql_query_info          = &lt;span class=&quot;hljs-keyword&quot;&gt;SELECT&lt;/span&gt; * &lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; sphinx_test &lt;span class=&quot;hljs-keyword&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;id&lt;/span&gt;=$&lt;span class=&quot;hljs-keyword&quot;&gt;id&lt;/span&gt;

建立索引
cd /usr/<span class="hljs-keyword">local</span>/coreseek/<span class="hljs-keyword">bin</span>
./indexer <span class="hljs-comment">--all</span>
./<span class="hljs-keyword">search</span> 我是中国人
Copyright (c) <span class="hljs-number">2007</span><span class="hljs-number">-2011</span>,
Beijing Choice Software Technologies Inc (<span class="hljs-keyword">http</span>://www.coreseek.com)

<span class="hljs-keyword">using</span> config <span class="hljs-keyword">file</span> <span class="hljs-string">'/usr/local/coreseek/etc/csft.conf'</span>...
<span class="hljs-keyword">index</span> <span class="hljs-string">'test1'</span>: <span class="hljs-keyword">query</span> <span class="hljs-string">'我是中国人 '</span>: returned <span class="hljs-number">0</span> matches <span class="hljs-keyword">of</span> <span class="hljs-number">0</span> total <span class="hljs-keyword">in</span> <span class="hljs-number">0.000</span> sec

words:
<span class="hljs-number">1.</span> <span class="hljs-string">'我'</span>: <span class="hljs-number">0</span> documents, <span class="hljs-number">0</span> hits
<span class="hljs-number">2.</span> <span class="hljs-string">'是'</span>: <span class="hljs-number">0</span> documents, <span class="hljs-number">0</span> hits
<span class="hljs-number">3.</span> <span class="hljs-string">'中国人'</span>: <span class="hljs-number">0</span> documents, <span class="hljs-number">0</span> hits

<span class="hljs-keyword">index</span> <span class="hljs-string">'test1stemmed'</span>: <span class="hljs-keyword">query</span> <span class="hljs-string">'我是中国人 '</span>: returned <span class="hljs-number">0</span> matches <span class="hljs-keyword">of</span> <span class="hljs-number">0</span> total <span class="hljs-keyword">in</span> <span class="hljs-number">0.000</span> sec

words:
<span class="hljs-number">1.</span> <span class="hljs-string">'我'</span>: <span class="hljs-number">0</span> documents, <span class="hljs-number">0</span> hits
<span class="hljs-number">2.</span> <span class="hljs-string">'是'</span>: <span class="hljs-number">0</span> documents, <span class="hljs-number">0</span> hits
<span class="hljs-number">3.</span> <span class="hljs-string">'中国人'</span>: <span class="hljs-number">0</span> documents, <span class="hljs-number">0</span> hits

看看是不是已经出来效果了呢 (备注,原始测试的<span class="hljs-keyword">sql</span>,都是英文,需要自己添加一些中文的记录哦)。</code></pre><h3>安装libsphinxclient</h3><pre><code class="hljs bash" codemark="1"><span class="hljs-built_in">cd</span> coreseek-4.1-beta/csft-4.1/api/libsphinxclient
sh buildconf.sh
./configure --prefix=/usr/<span class="hljs-built_in">local</span>/sphinxclient
make && make install</code></pre><h3>安装php拓展</h3><pre><code class="hljs ruby" codemark="1"><span class="hljs-comment">##我WGET好像有问题,我是用WINDOW下载了,传到服务器的。</span>
<span class="hljs-comment">##此扩展是PHP7的包,其它包请百度查找</span>
wget <span class="hljs-symbol">http:</span>/<span class="hljs-regexp">/git.php.net/</span><span class="hljs-string">?p</span>=pecl/search_engine/sphinx.git;a=snapshot;h=<span class="hljs-number">9</span>a3d08c67af0cad216aa0d38d39be71362667738;sf=tgz
<span class="hljs-comment"># tar zxvf sphinx-9a3d08c.tar.gz</span>
<span class="hljs-comment"># cd cd sphinx-9a3d08c</span>
<span class="hljs-comment">#(此处为当前使用的PHP目录)</span>
/www/wdlinux/apache_php/bin/phpize
./configure --with-php-config=<span class="hljs-regexp">/www/wdlinux</span><span class="hljs-regexp">/apache_php/bin</span><span class="hljs-regexp">/php-config --with-sphinx=/usr</span><span class="hljs-regexp">/local/sphinxclient</span>
make && make install
安装后,在/www/wdlinux/apache_php-<span class="hljs-number">7.0</span>.<span class="hljs-number">6</span>/lib/php/extensions/no-debug-non-zts-<span class="hljs-number">20151012</span>/目录下生成sphinx.so扩展 PHP目录不一样,生成文件目录也不一样。</code></pre><h3>在php.ini中加入</h3><pre><code class="hljs ini" codemark="1"><span class="hljs-section">[sphinx]</span>
<span class="hljs-attr">extension_dir</span>=<span>/www/</span>wdlinux/apache_php<span>-<span class="hljs-number">7.0</span></span><span>.<span class="hljs-number">6</span></span>/lib/php/extensions/<span class="hljs-literal">no</span>-debug-non-zts<span>-<span class="hljs-number">20151012</span></span>/
<span class="hljs-attr">extension</span>=sphinx.so</code></pre><p>查看phpinfo();</p><p><img src="https://imgs.jerryblog.cn/2018051815266367056257.png" alt="QQ截图20180518174401"></p><p>到处完成安装</p><pre style="max-width: 100%;"><code class="sql hljs" codemark="1">##开启coreseek
/usr/local/coreseek/bin/searchd -c /usr/local/coreseek/etc/csft.conf

建立索引:

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

重建索引

/usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/csft.conf --all --rotate</code></pre><pre style="max-width: 100%;"><code class="php hljs" codemark="1">#php 调用
$cl = new \SphinxClient();
$cl->SetServer('localhost',9312);
$cl->SetMatchMode(SPH_MATCH_ALL);
$cl->SetArrayResult(true);
$res = $cl->Query("我是中国人","*");
var_dump($res);
</code></pre><p><br></p>

Coreseek 4.1参考手册 / Sphinx 2.0.1-beta

<h1>Sphinx–强大的开源全文检索引擎,Coreseek–免费开源的中文全文检索引擎</h1><p>版权 © 2001-2011 Andrew Aksyonoff</p><p>版权 © 2008-2011 Sphinx Technologies Inc, http://sphinxsearch.com</p><p>版权 © 2006-2011 选择软件(Coreseek), nzinfo, <li.monan(at)gmail.com>, HonestQiao, <honestqiao(at)gmail.com></p>
目录<dl><dt>

    <a href="#intro">1. 简介</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#about">1.1. 什么是CoreSeek/Sphinx</a> 
     </dt><dt> 
      <a href="#features">1.2. CoreSeek/Sphinx 的特性</a> 
     </dt><dt> 
      <a href="#getting">1.3. 如何得到CoreSeek/Sphinx</a> 
     </dt><dt> 
      <a href="#license">1.4. 许可协议</a> 
     </dt><dt> 
      <a href="#credits">1.5. 作者和贡献者</a> 
     </dt><dt> 
      <a href="#history">1.6. 历史</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#installation">2. 安装</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#supported-system">2.1. 支持的操作系统</a> 
     </dt><dt> 
      <a href="#required-tools">2.2. 需要的工具</a> 
     </dt><dt> 
      <a href="#installing">2.3. 在Linux、BSD上安装CoreSeek/Sphinx</a> 
     </dt><dt> 
      <a href="#installing-windows">2.4. 在Windows上安装CoreSeek/Sphinx</a> 
     </dt><dt> 
      <a href="#install-problems">2.5. 已知的安装问题和解决办法</a> 
     </dt><dt> 
      <a href="#quick-tour">2.6. CoreSeek/Sphinx快速入门教程</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#indexing">3. 建立索引</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#sources">3.1. 数据源</a> 
     </dt><dt> 
      <a href="#attributes">3.2. 属性</a> 
     </dt><dt> 
      <a href="#mva">3.3. MVA (多值属性)</a> 
     </dt><dt> 
      <a href="#indexes">3.4. 索引</a> 
     </dt><dt> 
      <a href="#data-restrictions">3.5. 源数据的限制</a> 
     </dt><dt> 
      <a href="#charsets">3.6. 字符集、大小写转换和转换表</a> 
     </dt><dt> 
      <a href="#sql">3.7. SQL 数据源 (MySQL, PostgreSQL)</a> 
     </dt><dt> 
      <a href="#xmlpipe">3.8. xmlpipe 数据源</a> 
     </dt><dt> 
      <a href="#xmlpipe2">3.9. xmlpipe2 数据源</a> 
     </dt><dt> 
      <a href="#pysource">3.10. Python 数据源</a> 
     </dt><dt> 
      <a href="#live-updates">3.11. 实时索引更新</a> 
     </dt><dt> 
      <a href="#delta-updates">3.12. 增量索引更新</a> 
     </dt><dt> 
      <a href="#index-merging">3.13. 索引合并</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#rt-indexes">4. RT实时索引</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#rt-overview">4.1. RT实时索引概览</a> 
     </dt><dt> 
      <a href="#rt-caveats">4.2. RT实时索引使用注意事项</a> 
     </dt><dt> 
      <a href="#rt-internals">4.3. RT实时索引原理</a> 
     </dt><dt> 
      <a href="#rt-binlog">4.4. 二进制日志</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#searching">5. 搜索</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#matching-modes">5.1. 匹配模式</a> 
     </dt><dt> 
      <a href="#boolean-syntax">5.2. 布尔查询语法</a> 
     </dt><dt> 
      <a href="#extended-syntax">5.3. 扩展查询语法</a> 
     </dt><dt> 
      <a href="#weighting">5.4. 权值计算</a> 
     </dt><dt> 
      <a href="#expressions">5.5. 表达式,函数,运算符</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#operators">5.5.1. 运算符</a> 
       </dt><dt> 
        <a href="#numeric-functions">5.5.2. 数值函数</a> 
       </dt><dt> 
        <a href="#date-time-functions">5.5.3. 日期和时间函数</a> 
       </dt><dt> 
        <a href="#type-conversion-functions">5.5.4. 类型转换函数</a> 
       </dt><dt> 
        <a href="#comparison-functions">5.5.5. 比较函数</a> 
       </dt><dt> 
        <a href="#misc-functions">5.5.6. 其它函数</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#sorting-modes">5.6. 排序模式</a> 
     </dt><dt> 
      <a href="#clustering">5.7. 结果分组(聚类)</a> 
     </dt><dt> 
      <a href="#distributed">5.8. 分布式搜索</a> 
     </dt><dt> 
      <a href="#query-log-format">5.9. 搜索服务(<code>searchd</code>) 查询日志格式</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#plain-log-format">5.9.1. 纯文本日志格式</a> 
       </dt><dt> 
        <a href="#sphinxql-log-format">5.9.2. SphinxQL 日志格式</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#sphinxql">5.10. MySQL 协议支持与 SphinxQL</a> 
     </dt><dt> 
      <a href="#multi-queries">5.11. 批量查询</a> 
     </dt><dt> 
      <a href="#collations">5.12. 字符串排序规则</a> 
     </dt><dt> 
      <a href="#udf">5.13. 用户自定义函数 (UDF)</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#command-line-tools">6. 命令行工具参考</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#ref-indexer">6.1.&nbsp;<code>indexer</code>:索引命令参考</a> 
     </dt><dt> 
      <a href="#ref-searchd">6.2.&nbsp;<code>searchd</code>:搜索服务端命令参考</a> 
     </dt><dt> 
      <a href="#ref-search">6.3.&nbsp;<code>search</code>:命令行搜索命令参考</a> 
     </dt><dt> 
      <a href="#ref-spelldump">6.4.&nbsp;<code>spelldump</code>:拼写信息导出命令参考</a> 
     </dt><dt> 
      <a href="#ref-indextool">6.5.&nbsp;<code>indextool</code>:索引信息导出命令参考</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#sphinxql-reference">7. SphinxQL 指南</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#sphinxql-select">7.1. SELECT(搜索查询)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-show-meta">7.2. SHOW META(显示查询状态信息)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-show-warnings">7.3. SHOW WARNINGS(显示查询警告信息)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-show-status">7.4. SHOW STATUS(显示服务端状态信息)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-insert">7.5. INSERT 和 REPLACE(数据插入和替换)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-delete">7.6. DELETE(数据删除)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-set">7.7. SET(设置服务端变量)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-commit">7.8. BEGIN, COMMIT, 以及 ROLLBACK(事务处理)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-call-snippets">7.9. CALL SNIPPETS(摘要生成)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-call-keywords">7.10. CALL KEYWORDS(关键词生成)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-show-tables">7.11. SHOW TABLES(显示当前提供搜索服务的索引列表)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-describe">7.12. DESCRIBE(显示指定搜索服务索引的字段信息)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-create-function">7.13. CREATE FUNCTION(添加自定义函数)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-drop-function">7.14. DROP FUNCTION(删除自定义函数)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-show-variables">7.15. SHOW VARIABLES(显示服务器端变量)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-show-variables">7.16. SHOW COLLATION(显示字符集校对)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-update">7.17. UPDATE(数据更新)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-multi-queries">7.18. 多结果集查询(批量查询)</a> 
     </dt><dt> 
      <a href="#sphinxql-comment-syntax">7.19. COMMIT(注释)语法</a> 
     </dt><dt> 
      <a href="#sphinxql-reserved-keywords">7.20. SphinxQL 保留关键字列表</a> 
     </dt><dt> 
      <a href="#sphinxql-upgrading-magics">7.21. SphinxQL 升级备注, version 2.0.1-beta</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#api-reference">8. API参考</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#api-funcgroup-general">8.1. 通用API方法</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-getlasterror">8.1.1. GetLastError (错误信息)</a> 
       </dt><dt> 
        <a href="#api-func-getlastwarning">8.1.2. GetLastWarning (告警信息)</a> 
       </dt><dt> 
        <a href="#api-func-setserver">8.1.3. SetServer (设置搜索服务)</a> 
       </dt><dt> 
        <a href="#api-func-setretries">8.1.4. SetRetries (设置失败重试)</a> 
       </dt><dt> 
        <a href="#api-func-setconnecttimeout">8.1.5. SetConnectTimeout (设置超时时间)</a> 
       </dt><dt> 
        <a href="#api-func-setarrayresult">8.1.6. SetArrayResult (设置结果返回格式)</a> 
       </dt><dt> 
        <a href="#api-func-isconnecterror">8.1.7. IsConnectError (检查链接错误)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-general-query-settings">8.2. 通用搜索设置</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-setlimits">8.2.1. SetLimits (设置结果集偏移量)</a> 
       </dt><dt> 
        <a href="#api-func-setmaxquerytime">8.2.2. SetMaxQueryTime (设置最大搜索时间)</a> 
       </dt><dt> 
        <a href="#api-func-setoverride">8.2.3. SetOverride (设置临时属性值覆盖)</a> 
       </dt><dt> 
        <a href="#api-func-setselect">8.2.4. SetSelect (设置返回信息的内容)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-fulltext-query-settings">8.3. 全文搜索设置</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-setmatchmode">8.3.1. SetMatchMode (设置匹配模式)</a> 
       </dt><dt> 
        <a href="#api-func-setrankingmode">8.3.2. SetRankingMode (设置评分模式)</a> 
       </dt><dt> 
        <a href="#api-func-setsortmode">8.3.3. SetSortMode (设置排序模式)</a> 
       </dt><dt> 
        <a href="#api-func-setweights">8.3.4. SetWeights (设置权重)</a> 
       </dt><dt> 
        <a href="#api-func-setfieldweights">8.3.5. SetFieldWeights (设置字段权重)</a> 
       </dt><dt> 
        <a href="#api-func-setindexweights">8.3.6. SetIndexWeights (设置索引权重)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-filtering">8.4. 结果集过滤设置</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-setidrange">8.4.1. SetIDRange (设置查询ID范围)</a> 
       </dt><dt> 
        <a href="#api-func-setfilter">8.4.2. SetFilter (设置属性过滤)</a> 
       </dt><dt> 
        <a href="#api-func-setfilterrange">8.4.3. SetFilterRange (设置属性范围)</a> 
       </dt><dt> 
        <a href="#api-func-setfilterfloatrange">8.4.4. SetFilterFloatRange (设置浮点数范围)</a> 
       </dt><dt> 
        <a href="#api-func-setgeoanchor">8.4.5. SetGeoAnchor (设置地表距离锚点)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-groupby">8.5. 分组设置</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-setgroupby">8.5.1. SetGroupBy (设置分组的属性)</a> 
       </dt><dt> 
        <a href="#api-func-setgroupdistinct">8.5.2. SetGroupDistinct (设置分组计算不同值的属性)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-querying">8.6. 搜索数据</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-query">8.6.1. Query (查询)</a> 
       </dt><dt> 
        <a href="#api-func-addquery">8.6.2. AddQuery (增加批量查询)</a> 
       </dt><dt> 
        <a href="#api-func-runqueries">8.6.3. RunQueries (执行批量查询)</a> 
       </dt><dt> 
        <a href="#api-func-resetfilters">8.6.4. ResetFilters (清除当前设置的过滤器)</a> 
       </dt><dt> 
        <a href="#api-func-resetgroupby">8.6.5. ResetGroupBy (清除现有的分组设置)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-additional-functionality">8.7. 附加方法</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-buildexcerpts">8.7.1. BuildExcerpts (产生文本摘要和高亮)</a> 
       </dt><dt> 
        <a href="#api-func-updateatttributes">8.7.2. UpdateAttributes (更新属性)</a> 
       </dt><dt> 
        <a href="#api-func-buildkeywords">8.7.3. BuildKeywords (获取分词结果)</a> 
       </dt><dt> 
        <a href="#api-func-escapestring">8.7.4. EscapeString (转义特殊字符)</a> 
       </dt><dt> 
        <a href="#api-func-status">8.7.5. Status (查询服务状态)</a> 
       </dt><dt> 
        <a href="#api-func-flushattributes">8.7.6. FlushAttributes (强制更新属性到磁盘)</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#api-funcgroup-pconn">8.8. 持久连接</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#api-func-open">8.8.1. Open (打开连接)</a> 
       </dt><dt> 
        <a href="#api-func-close">8.8.2. Close (关闭连接)</a> 
       </dt></dl> 
     </dd></dl> 
   </dd><dt> 
    <a href="#sphinxse">9. MySQL 存储引擎 (SphinxSE)</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#sphinxse-overview">9.1. SphinxSE 概览</a> 
     </dt><dt> 
      <a href="#sphinxse-installing">9.2. 安装 SphinxSE</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#sphinxse-mysql50">9.2.1. 编译支持SphinxSE的MySQL 5.0.x</a> 
       </dt><dt> 
        <a href="#sphinxse-mysql51">9.2.2. 编译支持SphinxSE的MySQL 5.1.x</a> 
       </dt><dt> 
        <a href="#sphinxse-checking">9.2.3. 检查SphinxSE安装与否</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#sphinxse-using">9.3. 使用 SphinxSE</a> 
     </dt><dt> 
      <a href="#sphinxse-snippets">9.4. 通过 MySQL 生成片段 (摘要)</a> 
     </dt></dl> 
   </dd><dt> 
    <a href="#reporting-bugs">10. 报告BUG</a> 
   </dt><dt> 
    <a href="#conf-reference">11.&nbsp;<code>sphinx.conf/csft.conf</code>&nbsp;配置选项参考</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#confgroup-source">11.1. 数据源配置选项</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#conf-source-type">11.1.1. type:数据源类型</a> 
       </dt><dt> 
        <a href="#conf-sql-host">11.1.2. sql_host:数据库服务器</a> 
       </dt><dt> 
        <a href="#conf-sql-port">11.1.3. sql_port:数据库端口</a> 
       </dt><dt> 
        <a href="#conf-sql-user">11.1.4. sql_user:数据库用户名</a> 
       </dt><dt> 
        <a href="#conf-sql-pass">11.1.5. sql_pass:数据库密码</a> 
       </dt><dt> 
        <a href="#conf-sql-db">11.1.6. sql_db:数据库名称</a> 
       </dt><dt> 
        <a href="#conf-sql-sock">11.1.7. sql_sock:数据库Socket文件</a> 
       </dt><dt> 
        <a href="#conf-mysql-connect-flags">11.1.8. mysql_connect_flags:MySQL连接参数</a> 
       </dt><dt> 
        <a href="#conf-mysql-ssl">11.1.9. mysql_ssl_cert, mysql_ssl_key, mysql_ssl_ca:MySQL的SSL连接</a> 
       </dt><dt> 
        <a href="#conf-odbc-dsn">11.1.10. odbc_dsn:ODBC连接字符串(DSN)</a> 
       </dt><dt> 
        <a href="#conf-sql-query-pre">11.1.11. sql_query_pre:待索引数据获取前查询</a> 
       </dt><dt> 
        <a href="#conf-sql-query">11.1.12. sql_query:获取待索引数据查询</a> 
       </dt><dt> 
        <a href="#conf-sql-joined-field">11.1.13. sql_joined_field:SQL连接字段设置</a> 
       </dt><dt> 
        <a href="#conf-sql-query-range">11.1.14. sql_query_range:分区查询范围</a> 
       </dt><dt> 
        <a href="#conf-sql-range-step">11.1.15. sql_range_step:分区查询步进值</a> 
       </dt><dt> 
        <a href="#conf-sql-query-killlist">11.1.16. sql_query_killlist:Kill-list查询</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-uint">11.1.17. sql_attr_uint:整数属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-bool">11.1.18. sql_attr_bool:布尔属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-bigint">11.1.19. sql_attr_bigint:长整型属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-timestamp">11.1.20. sql_attr_timestamp:UNIX时间戳属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-str2ordinal">11.1.21. sql_attr_str2ordinal:字符串序数排序属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-float">11.1.22. sql_attr_float:浮点数属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-multi">11.1.23. sql_attr_multi:多值属性(MVA)属性</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-string">11.1.24. sql_attr_string:字符串属性(可返回原始文本信息)</a> 
       </dt><dt> 
        <a href="#conf-sql-attr-str2wordcount">11.1.25. sql_attr_str2wordcount:文档词汇数记录属性</a> 
       </dt><dt> 
        <a href="#conf-sql-column-buffers">11.1.26. sql_column_buffers:结果行缓冲大小</a> 
       </dt><dt> 
        <a href="#conf-sql-field-string">11.1.27. sql_field_string:字符串字段(可全文搜索,可返回原始文本信息)</a> 
       </dt><dt> 
        <a href="#conf-sql-field-str2wordcount">11.1.28. sql_field_str2wordcount:文档词汇数记录字段(可全文搜索,可返回原始信息)</a> 
       </dt><dt> 
        <a href="#conf-sql-file-field">11.1.29. sql_file_field:外部文件字段</a> 
       </dt><dt> 
        <a href="#conf-sql-query-post">11.1.30. sql_query_post:数据获取后查询</a> 
       </dt><dt> 
        <a href="#conf-sql-query-post-index">11.1.31. sql_query_post_index:数据索引后查询</a> 
       </dt><dt> 
        <a href="#conf-sql-ranged-throttle">11.1.32. sql_ranged_throttle:分区查询间隔时间</a> 
       </dt><dt> 
        <a href="#conf-sql-query-info-pre">11.1.33. sql_query_info_pre:命令行信息获取前查询</a> 
       </dt><dt> 
        <a href="#conf-sql-query-info">11.1.34. sql_query_info:命令行信息获取查询</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-command">11.1.35. xmlpipe_command:数据获取命令</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-field">11.1.36. xmlpipe_field:字段设置</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-field-string">11.1.37. xmlpipe_field_string:字符串字段</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-field-wordcount">11.1.38. xmlpipe_field_wordcount:词汇数存储字段</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-uint">11.1.39. xmlpipe_attr_uint:整数属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-bool">11.1.40. xmlpipe_attr_bool:布尔属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-timestamp">11.1.41. xmlpipe_attr_timestamp:UNIX时间戳属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-str2ordinal">11.1.42. xmlpipe_attr_str2ordinal:字符串序列属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-float">11.1.43. xmlpipe_attr_float:浮点数属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-multi">11.1.44. xmlpipe_attr_multi:多值属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-attr-string">11.1.45. xmlpipe_attr_string:字符串属性</a> 
       </dt><dt> 
        <a href="#conf-xmlpipe-fixup-utf8">11.1.46. xmlpipe_fixup_utf8:UTF-8修复设置</a> 
       </dt><dt> 
        <a href="#conf-mssql-winauth">11.1.47. mssql_winauth:Windows集成认证</a> 
       </dt><dt> 
        <a href="#conf-mssql-unicode">11.1.48. mssql_unicode:Unicode设置</a> 
       </dt><dt> 
        <a href="#conf-unpack-zlib">11.1.49. unpack_zlib:SQL数据源解压字段设置</a> 
       </dt><dt> 
        <a href="#conf-unpack-mysqlcompress">11.1.50. unpack_mysqlcompress:MySQL数据源解压字段设置</a> 
       </dt><dt> 
        <a href="#conf-unpack-mysqlcompress-maxsize">11.1.51. unpack_mysqlcompress_maxsize:MySQL数据源解压缓冲区设置</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#confgroup-index">11.2. 索引配置选项</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#conf-index-type">11.2.1. type:索引类型设置</a> 
       </dt><dt> 
        <a href="#conf-source">11.2.2. source:文档源</a> 
       </dt><dt> 
        <a href="#conf-path">11.2.3. path:索引文件路径</a> 
       </dt><dt> 
        <a href="#conf-docinfo">11.2.4. docinfo:文档信息存储模式</a> 
       </dt><dt> 
        <a href="#conf-mlock">11.2.5. mlock:缓冲数据内存锁定</a> 
       </dt><dt> 
        <a href="#conf-morphology">11.2.6. morphology:词形处理</a> 
       </dt><dt> 
        <a href="#conf-dict">11.2.7. dict:关键字词典类型</a> 
       </dt><dt> 
        <a href="#conf-index-sp">11.2.8. index_sp:索引句子和段落信息</a> 
       </dt><dt> 
        <a href="#conf-index-zones">11.2.9. index_zones:索引标签区域信息</a> 
       </dt><dt> 
        <a href="#conf-min-stemming-len">11.2.10. min_stemming_len:词干化最小词长</a> 
       </dt><dt> 
        <a href="#conf-stopwords">11.2.11. stopwords:停止词</a> 
       </dt><dt> 
        <a href="#conf-wordforms">11.2.12. wordforms:词形字典</a> 
       </dt><dt> 
        <a href="#conf-exceptions">11.2.13. exceptions:词汇特例处理</a> 
       </dt><dt> 
        <a href="#conf-min-word-len">11.2.14. min_word_len:最小索引词汇长度</a> 
       </dt><dt> 
        <a href="#conf-charset-type">11.2.15. charset_type:字符集编码</a> 
       </dt><dt> 
        <a href="#conf-charset-table">11.2.16. charset_table:字符表和大小写转换规则</a> 
       </dt><dt> 
        <a href="#conf-ignore-chars">11.2.17. ignore_chars:忽略字符表</a> 
       </dt><dt> 
        <a href="#conf-min-prefix-len">11.2.18. min_prefix_len:最小索引前缀长度</a> 
       </dt><dt> 
        <a href="#conf-min-infix-len">11.2.19. min_infix_len:最小索引中缀长度</a> 
       </dt><dt> 
        <a href="#conf-prefix-fields">11.2.20. prefix_fields:前缀索引字段列表</a> 
       </dt><dt> 
        <a href="#conf-infix-fields">11.2.21. infix_fields:中缀索引字段列表</a> 
       </dt><dt> 
        <a href="#conf-enable-star">11.2.22. enable_star:星号语法</a> 
       </dt><dt> 
        <a href="#conf-ngram-len">11.2.23. ngram_len:N-gram长度</a> 
       </dt><dt> 
        <a href="#conf-ngram-chars">11.2.24. ngram_chars:N-gram字符列表</a> 
       </dt><dt> 
        <a href="#conf-phrase-boundary">11.2.25. phrase_boundary:词组边界符列表</a> 
       </dt><dt> 
        <a href="#conf-phrase-boundary-step">11.2.26. phrase_boundary_step:词组边界位置增量</a> 
       </dt><dt> 
        <a href="#conf-html-strip">11.2.27. html_strip:HTMl标记清理</a> 
       </dt><dt> 
        <a href="#conf-html-index-attrs">11.2.28. html_index_attrs:HTML标签属性索引设置</a> 
       </dt><dt> 
        <a href="#conf-html-remove-elements">11.2.29. html_remove_elements:HTML元素清理</a> 
       </dt><dt> 
        <a href="#conf-local">11.2.30. local:本地索引声明</a> 
       </dt><dt> 
        <a href="#conf-agent">11.2.31. agent:远程索引声明</a> 
       </dt><dt> 
        <a href="#conf-agent-blackhole">11.2.32. agent_blackhole:远程黑洞代理</a> 
       </dt><dt> 
        <a href="#conf-agent-connect-timeout">11.2.33. agent_connect_timeout:远程查询时间</a> 
       </dt><dt> 
        <a href="#conf-agent-query-timeout">11.2.34. agent_query_timeout:远程查询超时时间</a> 
       </dt><dt> 
        <a href="#conf-preopen">11.2.35. preopen:索引文件预开启</a> 
       </dt><dt> 
        <a href="#conf-ondisk-dict">11.2.36. ondisk_dict:字典文件保持设置</a> 
       </dt><dt> 
        <a href="#conf-inplace-enable">11.2.37. inplace_enable:原地索引倒转设置</a> 
       </dt><dt> 
        <a href="#conf-inplace-hit-gap">11.2.38. inplace_hit_gap:原地索引倒转匹配点空隙设置</a> 
       </dt><dt> 
        <a href="#conf-inplace-docinfo-gap">11.2.39. inplace_docinfo_gap:原地索引倒转文档信息空隙设置</a> 
       </dt><dt> 
        <a href="#conf-inplace-reloc-factor">11.2.40. inplace_reloc_factor:原地索引倒转重定位内存设置</a> 
       </dt><dt> 
        <a href="#conf-inplace-write-factor">11.2.41. inplace_write_factor:原地索引倒转写缓冲内存设置</a> 
       </dt><dt> 
        <a href="#conf-index-exact-words">11.2.42. index_exact_words:词干化后原词索引</a> 
       </dt><dt> 
        <a href="#conf-overshort-step">11.2.43. overshort_step:短词位置增量</a> 
       </dt><dt> 
        <a href="#conf-stopword-step">11.2.44. stopword_step:通用词位置增量</a> 
       </dt><dt> 
        <a href="#conf-hitless-words">11.2.45. hitless_words:位置忽略词汇列表</a> 
       </dt><dt> 
        <a href="#conf-expand-keywords">11.2.46. expand_keywords:词汇展开</a> 
       </dt><dt> 
        <a href="#conf-blend-chars">11.2.47. blend_chars:混合字符列表</a> 
       </dt><dt> 
        <a href="#conf-blend-mode">11.2.48. blend_mode:混合类型</a> 
       </dt><dt> 
        <a href="#conf-rt-mem-limit">11.2.49. rt_mem_limit:RT索引内存限制</a> 
       </dt><dt> 
        <a href="#conf-rt-field">11.2.50. rt_field:字段设置</a> 
       </dt><dt> 
        <a href="#conf-rt-attr-uint">11.2.51. rt_attr_uint:整数属性</a> 
       </dt><dt> 
        <a href="#conf-rt-attr-bigint">11.2.52. rt_attr_bigint:长整数属性</a> 
       </dt><dt> 
        <a href="#conf-rt-attr-float">11.2.53. rt_attr_float:浮点数属性</a> 
       </dt><dt> 
        <a href="#conf-rt-attr-timestamp">11.2.54. rt_attr_timestamp:UNIX时间戳属性</a> 
       </dt><dt> 
        <a href="#conf-rt-attr-string">11.2.55. rt_attr_string:字符串属性</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#confgroup-indexer">11.3.&nbsp;<code>indexer</code>&nbsp;程序配置选项</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#conf-mem-limit">11.3.1. mem_limit:索引内存限制</a> 
       </dt><dt> 
        <a href="#conf-max-iops">11.3.2. max_iops:每秒IO操作限制</a> 
       </dt><dt> 
        <a href="#conf-max-iosize">11.3.3. max_iosize:最大IO操作限制</a> 
       </dt><dt> 
        <a href="#conf-max-xmlpipe2-field">11.3.4. max_xmlpipe2_field:最大字段大小</a> 
       </dt><dt> 
        <a href="#conf-write-buffer">11.3.5. write_buffer:写缓冲大小</a> 
       </dt><dt> 
        <a href="#conf-max-file-field-buffer">11.3.6. max_file_field_buffer:外部文件缓冲大小</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#confgroup-searchd">11.4.&nbsp;<code>searchd</code>&nbsp;程序配置选项</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#conf-listen">11.4.1. listen:监听设置</a> 
       </dt><dt> 
        <a href="#conf-address">11.4.2. address:监听地址</a> 
       </dt><dt> 
        <a href="#conf-port">11.4.3. port:监听端口</a> 
       </dt><dt> 
        <a href="#conf-log">11.4.4. log:搜索系统日志</a> 
       </dt><dt> 
        <a href="#conf-query-log">11.4.5. query_log:搜索查询日志</a> 
       </dt><dt> 
        <a href="#conf-query-log-format">11.4.6. query_log_format:查询日志格式</a> 
       </dt><dt> 
        <a href="#conf-read-timeout">11.4.7. read_timeout:远程读取超时时间</a> 
       </dt><dt> 
        <a href="#conf-client-timeout">11.4.8. client_timeout:客户端超时时间</a> 
       </dt><dt> 
        <a href="#conf-max-children">11.4.9. max_children:子进程数目限制</a> 
       </dt><dt> 
        <a href="#conf-pid-file">11.4.10. pid_file:PID文件</a> 
       </dt><dt> 
        <a href="#conf-max-matches">11.4.11. max_matches:最大返回匹配数</a> 
       </dt><dt> 
        <a href="#conf-seamless-rotate">11.4.12. seamless_rotate:无缝轮换</a> 
       </dt><dt> 
        <a href="#conf-preopen-indexes">11.4.13. preopen_indexes:索引预开启</a> 
       </dt><dt> 
        <a href="#conf-unlink-old">11.4.14. unlink_old:旧索引清理</a> 
       </dt><dt> 
        <a href="#conf-attr-flush-period">11.4.15. attr_flush_period:属性刷新周期</a> 
       </dt><dt> 
        <a href="#conf-ondisk-dict-default">11.4.16. ondisk_dict_default:索引字典存储方式</a> 
       </dt><dt> 
        <a href="#conf-max-packet-size">11.4.17. max_packet_size:最大包大小</a> 
       </dt><dt> 
        <a href="#conf-mva-updates-pool">11.4.18. mva_updates_pool:MVA更新共享内存</a> 
       </dt><dt> 
        <a href="#conf-crash-log-path">11.4.19. crash_log_path:崩溃日志</a> 
       </dt><dt> 
        <a href="#conf-max-filters">11.4.20. max_filters:最大过滤器数目</a> 
       </dt><dt> 
        <a href="#conf-max-filter-values">11.4.21. max_filter_values:单个过滤器最大过滤值数目</a> 
       </dt><dt> 
        <a href="#conf-listen-backlog">11.4.22. listen_backlog:带处理监听队列</a> 
       </dt><dt> 
        <a href="#conf-read-buffer">11.4.23. read_buffer:读缓冲区</a> 
       </dt><dt> 
        <a href="#conf-read-unhinted">11.4.24. read_unhinted:无匹配时读取大小</a> 
       </dt><dt> 
        <a href="#conf-max-batch-queries">11.4.25. max_batch_queries:最大批量查询</a> 
       </dt><dt> 
        <a href="#conf-subtree-docs-cache">11.4.26. subtree_docs_cache:子树优化文档缓存</a> 
       </dt><dt> 
        <a href="#conf-subtree-hits-cache">11.4.27. subtree_hits_cache:子树优化命中缓存</a> 
       </dt><dt> 
        <a href="#conf-workers">11.4.28. workers:MPM模式</a> 
       </dt><dt> 
        <a href="#conf-dist-threads">11.4.29. dist_threads:并发查询线程数</a> 
       </dt><dt> 
        <a href="#conf-binlog-path">11.4.30. binlog_path:二进制日志路径</a> 
       </dt><dt> 
        <a href="#conf-binlog-flush">11.4.31. binlog_flush:二进制日志刷新</a> 
       </dt><dt> 
        <a href="#conf-binlog-max-log-size">11.4.32. binlog_max_log_size:二进制日志大小限制</a> 
       </dt><dt> 
        <a href="#conf-collation-server">11.4.33. collation_server:服务端默认字符集</a> 
       </dt><dt> 
        <a href="#conf-collation-libc-locale">11.4.34. collation_libc_locale:服务端libc字符集</a> 
       </dt><dt> 
        <a href="#conf-plugin-dir">11.4.35. plugin_dir:插件目录</a> 
       </dt><dt> 
        <a href="#conf-mysql-version-string">11.4.36. mysql_version_string:MySQL版本设置</a> 
       </dt><dt> 
        <a href="#conf-rt-flush-period">11.4.37. rt_flush_period:RT索引刷新周期</a> 
       </dt><dt> 
        <a href="#conf-thread-stack">11.4.38. thread_stack:线程堆栈</a> 
       </dt><dt> 
        <a href="#conf-expansion-limit">11.4.39. expansion_limit:关键字展开限制</a> 
       </dt><dt> 
        <a href="#conf-compat-sphinxql-magics">11.4.40. compat_sphinxql_magics</a> 
       </dt><dt> 
        <a href="#conf-watchdog">11.4.41. watchdog</a> 
       </dt></dl> 
     </dd></dl> 
   </dd><dt> 
    <a href="#coreseek-conf-reference">12.&nbsp;<code>Coreseek</code>配置选项参考</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#coreseek-confgroup-chinese">12.1. 中文分词核心配置</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#coreseek-conf-chinese-charset_dictpath">12.1.1. charset_dictpath</a> 
       </dt><dt> 
        <a href="#coreseek-conf-chinese-charset_type">12.1.2. charset_type</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#coreseek-confgroup-mmseg">12.2. MMSEG分词配置选项</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#coreseek-conf-mmseg-merge_number_and_ascii">12.2.1. merge_number_and_ascii</a> 
       </dt><dt> 
        <a href="#coreseek-conf-mmseg-number_and_ascii_joint">12.2.2. number_and_ascii_joint</a> 
       </dt><dt> 
        <a href="#coreseek-conf-mmseg-compress_space">12.2.3. compress_space</a> 
       </dt><dt> 
        <a href="#coreseek-conf-mmseg-seperate_number_ascii">12.2.4. seperate_number_ascii</a> 
       </dt></dl> 
     </dd><dt> 
      <a href="#coreseek-confgroup-pysource">12.3. Python数据源程序接口</a> 
     </dt><dd> 
      <dl><dt> 
        <a href="#coreseek-conf-pysource-GetScheme">12.3.1. GetScheme() (设置检索字段的属性)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-GetKillList">12.3.2. GetKillList() (设置不参与检索的文档编号)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-GetFieldOrder">12.3.3. GetFieldOrder() (设置字段的顺序)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-Connected">12.3.4. Connected() (获取数据前的连接处理)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-OnBeforeIndex">12.3.5. OnBeforeIndex() (数据获取前处理)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-NextDocument">12.3.6. NextDocument() (文档获取处理)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-OnAfterIndex">12.3.7. OnAfterIndex() (数据获取后处理)</a> 
       </dt><dt> 
        <a href="#coreseek-conf-pysource-OnIndexFinished">12.3.8. OnIndexFinished() (索引完成时处理)</a> 
       </dt></dl> 
     </dd></dl> 
   </dd><dt> 
    <a href="#changelog">A. Sphinx revision history</a> 
   </dt><dd> 
    <dl><dt> 
      <a href="#rel111">A.1. Version 2.0.1-beta, 22 apr 2011</a> 
     </dt><dt> 
      <a href="#rel110">A.2. Version 1.10-beta, 19 jul 2010</a> 
     </dt><dt> 
      <a href="#rel099">A.3. Version 0.9.9-release, 02 dec 2009</a> 
     </dt><dt> 
      <a href="#rel099rc2">A.4. Version 0.9.9-rc2, 08 apr 2009</a> 
     </dt><dt> 
      <a href="#rel099rc1">A.5. Version 0.9.9-rc1, 17 nov 2008</a> 
     </dt><dt> 
      <a href="#rel0981">A.6. Version 0.9.8.1, 30 oct 2008</a> 
     </dt><dt> 
      <a href="#rel098">A.7. Version 0.9.8, 14 jul 2008</a> 
     </dt><dt> 
      <a href="#rel097">A.8. Version 0.9.7, 02 apr 2007</a> 
     </dt><dt> 
      <a href="#rel097rc2">A.9. Version 0.9.7-rc2, 15 dec 2006</a> 
     </dt><dt> 
      <a href="#rel097rc">A.10. Version 0.9.7-rc1, 26 oct 2006</a> 
     </dt><dt> 
      <a href="#rel096">A.11. Version 0.9.6, 24 jul 2006</a> 
     </dt><dt> 
      <a href="#rel096rc1">A.12. Version 0.9.6-rc1, 26 jun 2006</a> 
     </dt></dl> 
   </dd></dl><p>范例清单</p><dl><dt>
     3.1.&nbsp; 
    <a href="#ex-ranged-queries">范围查询用法举例</a> 
   </dt><dt>
     3.2.&nbsp; 
    <a href="#ex-xmlpipe-document">XMLpipe 文档数据流</a> 
   </dt><dt>
     3.3.&nbsp; 
    <a href="#ex-xmlpipe2-document">xmlpipe2 文档数据流</a> 
   </dt><dt>
     3.4.&nbsp; 
    <a href="#ex-live-updates">完全自动化的实时索引</a> 
   </dt><dt>
     4.1.&nbsp; 
    <a href="#ex-rt-updates">RT实时索引定义</a> 
   </dt><dt>
     5.1.&nbsp; 
    <a href="#ex-boolean-query">布尔查询例子</a> 
   </dt><dt>
     5.2.&nbsp; 
    <a href="#ex-extended-query">扩展匹配模式:查询例子</a> 
   </dt></dl><h2>第&nbsp;1&nbsp;章&nbsp;简介</h2><p>目录</p><dl><dt> 
     <a href="#about">1.1. 什么是CoreSeek/Sphinx</a> 
    </dt><dt> 
     <a href="#features">1.2. CoreSeek/Sphinx 的特性</a> 
    </dt><dt> 
     <a href="#getting">1.3. 如何得到CoreSeek/Sphinx</a> 
    </dt><dt> 
     <a href="#license">1.4. 许可协议</a> 
    </dt><dt> 
     <a href="#credits">1.5. 作者和贡献者</a> 
    </dt><dt> 
     <a href="#history">1.6. 历史</a> 
    </dt></dl><h2>1.1.&nbsp;什么是CoreSeek/Sphinx</h2><p>Sphinx是一个在GPLv2下分发的全文检索引擎;Coreseek 是一个可供企业使用的、基于Sphinx(可独立于Sphinx原始版本运行)的中文全文检索引擎,按照GPLv2协议发行。商业使用(例如, 嵌入到其他程序中)需要联系我们以获得商业授权。</p><p>一般而言,Sphinx是一个独立的全文搜索引擎;而Coreseek是一个支持中文的全文搜索引擎,意图为其他应用提供高速、低空间占用、高相关度结果的中文全文搜索能力。CoreSeek/Sphinx可以非常容易的与SQL数据库和脚本语言集成。</p><p>应用程序可以通过三种不同的接口方式来与Sphinx搜索服务(searchd)通信: a) 通过原生的搜索 API 

(SphinxAPI), b) 通过Sphinx自身支持的MySQL网络协议 (使用命名为SphinxQL的SQL精简子集), 或者 c)
通过MySQL 服务端的存储插件引擎(SphinxSE)。当然, 还可以通过可以使用 a)、b)、c)
的应用程序来构建webservice来为其他应用程序提供通信</p><p>在Sphinx发行版本中提供的原生搜索API支持PHP、Python、Perl、Rudy和Java。搜索API非常轻量化,可以在几个小时之

内移植到新的语言上。第三方API接口和插件提供了对Perl、C#、Haskell、Ruby-on-Rails支持,以及对其他可能的语言或者框架的
支持。</p><p>从版本1.10-beta开始,Sphinx支持两种不同的索引后端:“磁盘(disk)”索引后端和“实时索引(realtime)”(RT)索

引后端。磁盘索引支持在线全文索引重建,但是仅支持非文本(属性)数据的在线更新。RT实时索引在此基础上,又增加了在线的全文索引更新。在此之前的版本
仅支持磁盘索引。</p><p>使用命名为数据源的接口,数据可以被加载到磁盘索引。当前系统内置MySQL和PostgreSQL以及ODBC兼容(MS
SQL、Oracle等)
数据库数据源的支持,也支持从管道标准输入读取特定格式的XML数据。通过适当修改源代码,用户可以自行增加新的数据源驱动(例如:对其他类型的DBMS

的原生支持)。在Coreseek发行的版本中,用户还可以使用Python脚本作为数据源来获取任何已知世界和未知世界的数据,这极大的扩展了数据源的
来源。从1.10-beta版本开始的RT实时索引,只能使用MySQL接口通过SphinxQL来操作。</p><p>Sphinx 是SQL Phrase Index的缩写,但不幸的和CMU的Sphinx项目重名。</p><p>Coreseek (http://www.coreseek.cn/) 为Sphinx在中国地区的用户提供支持服务,如果您不希望纠缠与琐碎的技术细节,请直接联系我们。</p><p>本参考手册基于Sphinx 2.0.1-beta最新文档,可能存在潜在的翻译错误,如果您发现本文的翻译错误,请联系我们。</p><p>我们的联系方式: coreseek@gmail.com 李沫南(nzinfo) honestqiao@gmail.com 乔楚(HonestQiao 13581882013)</p><h2>1.2. CoreSeek/Sphinx 的特性</h2><p>Sphinx 的主要特性:</p><ul><li>索引和搜索性能优异;</li><li>先进的索引和查询工具 (灵活且功能丰富的文本分析器,查询语言,以及多种不同的排序方式等等);</li><li>先进的结果集分析处理 (SELECT 可以使用表达式, WHERE, ORDER BY, GROUP BY 等对全文搜索结果集进行过滤);</li><li>实践证实可扩展性支持数十亿文档记录,TB级别的数据,以及每秒数千次查询;</li><li>易于集成SQL和XML数据源,并可使用SphinxAPI、SphinxQL或者SphinxSE搜索接口</li><li>易于通过分布式搜索进行扩展</li></ul><p>Sphinx 的详细特性:</p><ul><li>高速的索引建立(在当代CPU上,峰值性能可达到10 ~ 15MB/秒);</li><li>高性能的搜索 (在1.2G文本,100万条文档上进行搜索,支持高达每秒150~250次查询);</li><li>高扩展性 (最大的索引集群超过30亿条文档,最繁忙时刻的查询峰值达到每天5千万次);</li><li>提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;</li><li>支持分布式搜索功能;</li><li>提供文档片段(摘要以及高亮)生成功能;</li><li>内建支持SphinxAPI和SphinxQL搜索箭口,也可作为MySQL的存储引擎提供搜索服务;</li><li>支持布尔、短语、词语相似度等多种检索模式;</li><li>文档支持多个全文检索字段(缺省配置下,最大不超过32个);</li><li>文档支持多个额外的属性信息(例如:分组信息,时间戳等);</li><li>支持查询停止词;</li><li>支持词形学处理;</li><li>支持特殊词汇处理;</li><li>支持单一字节编码和UTF-8编码;</li><li>内建支持英语、俄语、捷克语词干化处理; 对 法语,西班牙语,葡萄牙语,意大利语,罗马尼亚语,德国,荷兰,瑞典,挪威,丹麦,芬兰,匈牙利等语言 的支持可通过第三方的 libstemmer 库建立);</li><li>原生的MySQL支持(同时支持MyISAM 、InnoDB、NDB、Archive等所有类型的数据表 );</li><li>原生的PostgreSQL 支持;</li><li>原生的ODBC兼容数据库支持 (MS SQL, Oracle, 等) ;</li><li>…多达50多项其他功能没有在此一一列出,请参阅API和配置手册!</li></ul><p> </p><h2>1.3. 如何得到CoreSeek/Sphinx</h2><p>Sphinx原始版本可以从Sphinx官方网站 sphinxsearch.com/,Coreseek可以从Coreseek官方网站 www.coreseek.cn/下载。</p><p>目前,CoreSeek/Sphinx的发布包包括如下软件:</p><ul><li>indexer: 用于创建全文索引;</li><li>search: 一个简单的命令行(CLI) 的测试程序,用于测试全文索引;</li><li>searchd: 一个守护进程,其他软件(例如WEB程序)可以通过这个守护进程进行全文检索;</li><li>sphinxapi: 一系列searchd 的客户端API 库,用于流行的Web脚本开发语言(PHP, Python, Perl, Ruby, Java).</li><li>spelldump: 一个简单的命令行工具,用于从 ispell 或者 MySpell (OpenOffice内置绑定) 格式的字典中提取词条。当使用 wordforms时可用这些词条对索引进行定制.</li><li>indextool: 工具程序,用来转储关于索引的多项调试信息。此工具是从版本Coreseek 3.1(Sphinx 0.9.9-rc2)开始加入的。</li><li>mmseg: 工具程序和库,Coreseek用于提供中文分词和词典处理。</li></ul><p> </p><h2>1.4. 许可协议</h2><p>这一程序是自由软件,你可以遵照自由软件基金会出版的GNU通用公共许可证条款来修改和重新发布这一程序。或者用许可证的第二版,或者(根据你的选择)用任何更新的版本。请查看COPYING文件了解详情。</p><p>发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定目的的隐含的担保。更详细的情况请参阅GNU通用公共许可证。</p><p>你应该已经和程序一起收到一份GNU通用公共许可证的副本。如果还没有,写信给: The Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p><p>非GPL许可(为OEM/ ISV的嵌入式应用)也可以安排,国际客户请 联系Sphinx 、中文客户请联系Coreseek以讨论商业授权的可能性与细节。</p><h2>1.5. 作者和贡献者</h2><h3>作者</h3><p>Sphinx 的最初作者 (诞生以来的主要开发者):</p><ul><li>Andrew Aksyonoff, http://shodan.ru</li></ul><p> </p><h3>Sphinx 的团队</h3><p>Sphinx技术公司参与过或正在参与Sphinx开发的工作人员(按照字母排序):</p><ul><li>Alexander Klimenko</li><li>Alexey Dvoichenkov</li><li>Alexey Vinogradov</li><li>Ilya Kuznetsov</li><li>Stanislav Klinov</li></ul><p> </p><h3>Coreseek 的团队</h3><p>Coreseek 参与CoreSeek/Sphinx开发的工作人员:</p><ul><li>nzinfo, <li.monan(at)gmail.com></li><li>HonestQiao, <honestqiao(at)gmail.com></li></ul><h3>贡献者</h3><p>为Sphinx的开发出过力的人员和他们的贡献如下(以下排名不分先后):</p><ul><li>Robert “coredev” Bengtsson (Sweden), 贡献了PostgreSQL数据源的初始版本</li><li>Len Kranendonk, Perl API</li><li>Dmytro Shteflyuk, Ruby API</li><li>blueflycn, sphinx-for-chinese,另一个支持MMSEG中文分词的个人发布版本</li></ul><p> </p><p>此外,还有许多人提出了宝贵的想法、错误报告以及修正。在此一并致谢!对CoreSeek/Sphinx所采用依赖和工具软件的作者,在此也表示由衷的感谢与敬意。</p><h2>1.6. 历史</h2><p>Coreseek
的开发工作类似Sphinx(起始于2001年),可以上溯到2006年(Sphinx于该年开始对外提供),那时我们试图为一个数据库驱动的网站寻找一
个可接受的中文搜索的解决方案,但是当时没有任何方案能够完全而又直接的满足要求。事实上,主要是如下问题:</p><ul><li>搜索质量(例如:类似Google的有效的相关度算法)

       
        
        单纯的统计学方法的效果非常糟糕,特别是在大量的短篇文档的集合上,例如:论坛、博客等等 
        
       </li><li>搜索速度 
       
        
        特别是当搜索的短语包括“停止词”时,表现的尤其明显,例如:英文(”to be or not to be”)、中文(“我的你的他的”) 
        
       </li><li>建立索引时,磁盘IO和CPU消耗需要可控 
       
        
        在共享的主机环境中,这一点的重要性更甚于索引速度 
        
       </li><li>中文搜索的准确性和效率 
       
        
        因为众所周知的原因,只有准确的中文分词才能提高中文搜索的准确性,并大大降低计算量. 
        
       </li></ul><p>&nbsp;</p><p>通过网络,我们还了解到有无数的人存在类似的需求,但是没有一款真真合适的工具来解决这个问题。尔后我们进行了不同途径的探索,尝试了不同的方法,

经过了反复的实践,幸运的是我们找到了Sphinx,最终选择基于Sphinx、结合MMSeg,开发出Coreseek中文全文检索引擎,并按照
GPLv2协议发行,以供企业和个人解决中文搜索问题。</p><p>随着时间的流逝,其他的解决方案有了很多改进,新的方案也不断涌现,但是,我们一致认为仍然没有一种解决方案是足够的好,以至于能让我们抛弃Sphinx将搜索平台迁移过去。</p><p>近年来,CoreSeek/Sphinx的用户给了我们很多正面的反馈和建议,我们也不断改进和提高,提供了新的实时索引,并增加了Python数
据源,将CoreSeek/Sphinx的应用范围从已知世界扩展到未知世界,其应用场景也达到无限种可能;因此,显而易见的,CoreSeek
/Sphinx的开发过程将会继续(也许将持续到世界末日)。</p><h2>第 2 章 安装</h2><p>目录</p><dl><dt>

     <a href="#supported-system">2.1. 支持的操作系统</a> 
    </dt><dt> 
     <a href="#required-tools">2.2. 需要的工具</a> 
    </dt><dt> 
     <a href="#installing">2.3. 在Linux、BSD上安装CoreSeek/Sphinx</a> 
    </dt><dt> 
     <a href="#installing-windows">2.4. 在Windows上安装CoreSeek/Sphinx</a> 
    </dt><dt> 
     <a href="#install-problems">2.5. 已知的安装问题和解决办法</a> 
    </dt><dt> 
     <a href="#quick-tour">2.6. CoreSeek/Sphinx快速入门教程</a> 
    </dt></dl><h2>2.1.&nbsp;支持的操作系统</h2><p>在绝大多数现代的Unix类操作系统(例如Linux、BSD等)上,只需要一个C++编译器和基本的系统工具就可以编译并运行CoreSeek/Sphinx,而不需要对源码进行任何改动。</p><p>目前,CoreSeek/Sphinx可以在以下系统上运行:</p><ul><li>Linux 2.4.x, 2.6.x (包括各种发行版,如Redhat、Centos、Fedora、Gentoo、Debian、Ubuntu、Slackware、OpenSuse、ArchLinux等)</li><li>Windows 2000, 2003, XP, Vista, Windows7, Windows2008</li><li>FreeBSD 4.x, 5.x, 6.x, 7.x,8.x</li><li>NetBSD 1.6, 3.0,4.x,5.x</li><li>Solaris 9, 11</li><li>Mac OS X</li></ul><p>&nbsp;</p><p>支持的CPU种类包括 X86, X86-64, AMD64, SPARC64。目前经过实际测试可以在主流BSD平台、Linux平台和Windows平台运行,详情可以查看<a href="http://www.coreseek.cn/products-install/" target="_top">Coreseek测试运行环境列表</a>。</p><p>我们希望CoreSeek/Sphinx也能够在其他的类Unix操作系统平台上工作,为所有需要解决中文搜索问题的用户服务,如果你运行CoreSeek/Sphinx索使用的操作系统不在上面的名单中,请告诉我们(HonestQiao,&nbsp;&lt;<a href="mailto:honestqiao%28at%29gmail.com">honestqiao(at)gmail.com</a>&gt;)。</p><p>目前的阶段,CoreSeek/Sphinx的Windows版可用于测试、调试和普通生产环境,但不建议用于负载量较大的生产系统。限于

Windows操作系统自身的限制,最突出的两个问题是:1)并发查询的支持不好;2)缺少索引数据热切换的支持。虽然目前已经有用户成功的在生产环境克

服了这两个问题,但是我们仍然不推荐在Windows下运行CoreSeek/Sphinx提供高强度的搜索服务。我们推荐使用Linux或者BSD作为
运行的操作系统平台,并可提供Linux、BSD系统下针对性的系统架构和性能优化支持服务。</p><h2>2.2. 需要的工具</h2><p>在类UNIX操作系统平台上,你需要以下的工具用来编译和安装CoreSeek/Sphinx:</p><ul><li>C++编译器。GNU gcc 就能够干这个活.</li><li>make程序。GNU make 就能够干这个活.</li><li>iconv库。GNU libiconv 就能够提供支持.</li><li>Python2.6(如果启用Python数据源支持)</li></ul><p>在Windows平台上,你需要Microsoft Visual C/C++ Studio .NET 2003 或者 2005
或者 2008。如果你还需要使用Python数据源,推荐安装ActiveState
Python2.6。其他的编译器/开发环境也许也能搞定这件事,但你可能需要自己手工制作他们所需的Makefile或者工程文件。</p><h2>2.3. 在Linux、BSD上安装CoreSeek/Sphinx</h2><ol><li>将你下载的tar包解压,并进入coreseek 子目录: (我们在例子中使用的2.0.1-beta版本;你要根据你所使用的实际版本对指令和路径进行对应的修改)

       
       $&nbsp;tar&nbsp;xzvf&nbsp;sphinx-2.0.1-beta.tar.gz $&nbsp;cd&nbsp;sphinx  
       &nbsp; </li><li>首先安装MMSeg: 
       
       $&nbsp;cd&nbsp;mmseg 
       
       
       $&nbsp;./configure&nbsp;–prefix=/usr/local/mmseg 
       
       
       $&nbsp;make 
       
       
       $&nbsp;make&nbsp;install 
       
       
       $&nbsp;cd&nbsp;.. 
       &nbsp; 运行配置 程序: &nbsp; 
       
       $&nbsp;./configure 
       &nbsp; configure程序有很多运行选项。完整的列表可以通过使用&nbsp;--help&nbsp;开关得到。最重要的如下: 
       
        
        --prefix, 定义将Coreseek安装到何处;比如--prefix=/usr/local/sphinx(以下全部示例都假定Coreseek安装在这个位置) 
        --with-mysql, 当自动检测失败时,需要指出在那里能找到MySQL 头文件和库文件; 
        --with-pgsql指出在那里能找到PostgreSQL头文件和库文件. 
        --with-mmseg, 启用基于MMSeg的中文分词法,并指出在那里能找到MMSeg头文件和库文件. 
        --with-python, 启用Python数据源支持. 需要预先安装Python2.6. 
        
       &nbsp; </li><li>编译源代码生成二进制程序: 
       
       $&nbsp;make 
       &nbsp; </li><li>安装二进制程序到你设定的目录下: (类Unix操作系统下默认为/usr/local/bin/&nbsp;, 但是可以被&nbsp;./configure --prefix修改安装目录) 
       
       $&nbsp;make&nbsp;install 
       &nbsp; </li></ol><h2>2.4.&nbsp;在Windows上安装CoreSeek/Sphinx</h2><p>在Windows上安装通常比在Linux环境下容易一些。要不是为了给代码制作patch,一般安装预先编译好的二进制文件即可,它们可以在网站的下载区找到.</p><ol><li>将你下载的.zip文件解压,比如&nbsp;sphinx-2.0.1-beta-win32.zip, 或者&nbsp;sphinx-2.0.1-beta-win32-pgsql.zip&nbsp;如

果你需要PostgresSQL支持。 (我们在例子中使用的2.0.1-beta版本;你要根据你所使用的实际版本对指令和路径进行对应的修改)
Windows XP及其后续版本都可以直接解压.zip压缩包,用免费的解压缩程序也可,比如
7Zip.在本教程的其余部分,我们假定上述压缩包被解压到C:\Sphinx, 这样 searchd.exe 对应的路径就是 C:\Sphinx\bin\searchd.exe. 如果你打算给安装目录或者配置文件用个不同的路径,请在相应的地方自行修改路径。</li><li>编辑 sphinx.conf.in – 需要修改@CONFDIR@相关项目 – 针对你的系统的实际情况进行修改.</li><li>把 searchd 服务安装成一个Windows服务:C:\Sphinx\bin> C:\Sphinx\bin\searchd --install --config C:\Sphinx\sphinx.conf.in --servicename SphinxSearch</li><li>这样 searchd 服务应该出现在“控制面板->系统管理->服务”的列表中了,但还没有被启动,因为在启动它之前,我们还需要做些配置并用indexer 建立索引 . 这些可以参考 快速入门教程.
在接下来的安装步骤(其中最多涉及到的是类似在Linix环境下运行indexer命令
)中,你可能会得到一个有关libmysql.dll没有找到的错误提示。 如果安装过MySQL,你应该找一个Windows系统目录中,
或者有时在Windows \ System32目录中,或者在MySQL的安装目录中,找到libmysql.dll文件。如果你
确实收到一个这样的错误,请将找到的libmysql.dll拷贝到bin目录中。</li></ol><h2>2.5. 已知的安装问题和解决办法</h2><p>如果 configure 程序没有找到MySQL 的头文件和库文件,, 请试试检查是否安装了 mysql-devel 或者 mysql-client 依赖包. 在有些系统上,默认安装包括这个包. 类似如此,libiconv等也可能会有类似的提示。</p><p>如果 make 程序给出如下错误提示</p><pre><span><span>/bin/</span></span><span><span>sh:</span></span> g++: command not found
make[<span><span>1</span></span>]: * [libsphinx_a-sphinx.o] Error <span><span>127</span></span>
</pre><p>请检查是否安装了gcc-c++ 包.</p><p>如果你在编译时得到如下错误</p><pre>sphinx.cpp:<span><span>67</span></span>: error: invalid application of `<span><span>sizeof</span></span>' to
incomplete type `Private::SizeError<<span><span>false</span></span>>'
</pre><p>这意味着某些编译时的类型检查失败了,一个最有可能的原因是在你的系统上类型off_t的长度小于64bit。一个快速的修复手段是,你可以修改
src/sphinx.h ,将在定义类型SphOffset_t 处,将off_t
替换成DWORD,需要注意,这种改动将使你的全文索引文件不能超过2GB。即便这种修改有用,也请汇报这一问题,在汇报中请包括具体的错误信息以及操作
系统编译器的配置情况。这样,我们可能能够在下一个版本中解决这一问题。</p><p>如何你遇到了其他的任何问题,或者前面的建议对你没有帮助,别犹豫,请立刻联系我们.</p><h2>2.6. CoreSeek/Sphinx快速入门教程</h2><p>以下所有的例子都假设你将CoreSeek/Sphinx安装在目录 /usr/local/sphinx, 并且searchd 对应的路径为 /usr/local/sphinx/bin/searchd.</p><p>为了使用CoreSeek/Sphinx,你需要:</p><ol><li>创建配置文件.缺省的配置文件名为 sphinx.conf. 全部的CoreSeek/Sphinx提供的程序默认都在当前工作的目录下寻找该文件.由configure 程序生成的示例配置文件sphinx.conf.dist 中包括全部选项的注释,复制并编辑这个文件使之适用于你的具体情况: (请确认 CoreSeek/Sphinx 安装在 /usr/local/coreseek/) 

       
       $&nbsp;cd&nbsp;/usr/local/sphinx/etc $&nbsp;cp&nbsp;sphinx.conf.dist&nbsp;sphinx.conf $&nbsp;vi&nbsp;sphinx.conf 
       &nbsp; 在示例配置文件中,将试图对MySQL数据库test中的&nbsp;documents&nbsp;表建立索引;因此在这里还提供了&nbsp;example.sql&nbsp;用于给测试表增加少量数据用于测试: &nbsp; 
       
       $&nbsp;mysql&nbsp;-u&nbsp;test&nbsp;&lt;&nbsp;/usr/local/sphinx/etc/example.sql 
       &nbsp; </li><li>运行indexer&nbsp;为你的数据创建全文索引: 
       
       $&nbsp;cd&nbsp;/usr/local/sphinx/etc $&nbsp;/usr/local/sphinx/bin/indexer&nbsp;--all 
       &nbsp; </li><li>检索你新创建的索引!</li></ol><p>你可以使用search(注意,是search而不是searchd)实用程序从命令行对索引进行检索:</p><p>&nbsp;</p><p>$&nbsp;cd&nbsp;/usr/local/sphinx/etc $&nbsp;/usr/local/sphinx/bin/search&nbsp;test</p><p>&nbsp;</p><p>如果要从PHP脚本检索索引,你需要:</p><ol><li>运行守护进程searchd,PHP脚本需要连接到searchd上进行检索: 
       
       $&nbsp;cd&nbsp;/usr/local/sphinx/etc $&nbsp;/usr/local/sphinx/bin/searchd 
       &nbsp; </li><li>运行PHP API 附带的test 脚本(运行之前请确认searchd守护进程已启动): 
       
       $&nbsp;cd&nbsp;sphinx/api $&nbsp;php&nbsp;test.php&nbsp;test 
       &nbsp; </li><li>将API文件(位于api/sphinxapi.php) 包含进你自己的脚本,开始编程.</li></ol><p>祝你搜索愉快!</p><h2>第&nbsp;3&nbsp;章&nbsp;建立索引</h2><p>目录</p><dl><dt> 
     <a href="#sources">3.1. 数据源</a> 
    </dt><dt> 
     <a href="#attributes">3.2. 属性</a> 
    </dt><dt> 
     <a href="#mva">3.3. MVA (多值属性)</a> 
    </dt><dt> 
     <a href="#indexes">3.4. 索引</a> 
    </dt><dt> 
     <a href="#data-restrictions">3.5. 源数据的限制</a> 
    </dt><dt> 
     <a href="#charsets">3.6. 字符集、大小写转换和转换表</a> 
    </dt><dt> 
     <a href="#sql">3.7. SQL 数据源 (MySQL, PostgreSQL)</a> 
    </dt><dt> 
     <a href="#xmlpipe">3.8. xmlpipe 数据源</a> 
    </dt><dt> 
     <a href="#xmlpipe2">3.9. xmlpipe2 数据源</a> 
    </dt><dt> 
     <a href="#pysource">3.10. Python 数据源</a> 
    </dt><dt> 
     <a href="#live-updates">3.11. 实时索引更新</a> 
    </dt><dt> 
     <a href="#delta-updates">3.12. 增量索引更新</a> 
    </dt><dt> 
     <a href="#index-merging">3.13. 索引合并</a> 
    </dt></dl><h2>3.1.&nbsp;数据源</h2><p>索引的数据可以来自各种各样不同的来源:SQL数据库、纯文本、HTML文件、邮件等等。从CoreSeek/Sphinx的视角看,索引数据是一个结构化的文档的集合,其中每个文档是字段的集合,这种结构更利于SQL数据获取,其中每一行代表一个文档,每一列代表一个字段。</p><p>由于数据来源的不同,需要不同的代码来获取数据、处理数据以供CoreSeek/Sphinx进行索引的建立。这种代码被称之为数据源驱动程序(简称:驱动或数据源)。</p><p>在本文撰写时,CoreSeek/Sphinx中包括MySQL和PostgreSQL数据源的驱动程序,这些驱动使用数据库系统提供的C/C++

原生接口连接到数据库服务器并获取数据。此外,CoreSeek/Sphinx还提供了额外的被称为xmlpipe的数据源驱动,该驱动运行某个具体的命
令,并从该命令的stdout中读入数据。数据的格式在 第 3.8 节 “xmlpipe 数据源” 中有介绍。经过长足的发展,Coreseek还提供了具有特色的Python数据源驱动,可以使用Python编写数据获取脚本自定义数据源,从而得以获取任何已知世界和未知世界的数据。</p><p>如果确有必要,一个索引的数据可以来自多个数据源。这些数据将严格按照配置文件中定义的顺序进行处理。所有从这些数据源获取到的文档将被合并,共同产生一个索引,如同他们来源于同一个数据源一样。</p><h2>3.2. 属性</h2><p>属性是附加在每个文档上的额外的信息(值),可以在搜索的时候用于过滤和排序。</p><p>搜索结果通常不仅仅是进行文档的匹配和相关度的排序,经常还需要根据其他与文档相关联的值,对结果进行额外的处理。例如,用户可能需要对新闻检索结

果依次按日期和相关度排序,检索特定价格范围内的产品,检索某些特定用户的blog日志,或者将检索结果按月分组。为了高效地完成上述工作,Sphinx
允许给文档附加一些额外的属性,并把这些值存储在全文索引中,以便在对全文匹配结果进行过滤、排序或分组时使用。</p><p>属性与字段不同,不会被全文索引。他们仅仅是被存储在索引中,属性进行全文检索式不可能的。如果要对属性进行全文检索,系统将会返回一个错误。</p><p>例如,如果column被设置为属性,就不能使用扩展表达式@column 1去匹配column为1的文档;如果数字字段按照普通的方式被索引,那么就可以这样来匹配。</p><p>属性可用于过滤,或者限制返回的数据,以及排序或者 结果分组; 也有可能是完全基于属性排序的结果, 而没有任何搜索相关功能的参与. 此外, 属性直接从搜索服务程序返回信息, 而被索引的文本内容则没有返回.</p><p>论坛帖子表是一个很好的例子。假设只有帖子的标题和内容这两个字段需要全文检索,但是有时检索结果需要被限制在某个特定的作者的帖子或者属于某个子

论坛的帖子中(也就是说,只检索在SQL表的author_id和forum_id这两个列上有特定值的那些行),或者需要按post_date列对匹配
的结果排序,或者根据post_date列对帖子按月份分组,并对每组中的帖子计数。</p><p>为实现这些功能,可以将上述各列(除了标题和内容列)作为属性做索引,之后即可使用API调用来设置过滤、排序和分组。以下是一个例子:</p><h3>示例: sphinx.conf 片段:</h3><p> </p><pre>...
sql_query = <span><span>SELECT</span></span> <span><span>id</span></span>, title, <span><span>content</span></span>, \
author_id, forum_id, post_date <span><span>FROM</span></span> my_forum_posts
sql_attr_uint = author_id
sql_attr_uint = forum_id
sql_attr_timestamp = post_date
...
</pre><p> </p><h3>示例: 应用程序代码 (使用 PHP):</h3><p> </p><pre><span><span>// 仅搜索ID为123的作者发布的内容</span></span>
$cl->SetFilter ( <span><span>"author_id"</span></span>, <span><span>array</span></span> ( <span><span>123</span></span> ) );

<span><span>// 仅在id为1,3,7的子论坛中搜索</span></span>
$cl->SetFilter ( <span><span>"forum_id"</span></span>, <span><span>array</span></span> ( <span><span>1</span></span>,<span><span>3</span></span>,<span><span>7</span></span> ) );

<span><span>// 按照发布时间倒序排列获取的结果</span></span>
$cl->SetSortMode ( SPH_SORT_ATTR_DESC, <span><span>"post_date"</span></span> );
</pre><p> </p><p>可以通过名字来指示特定的属性,并且这个名字是大小写无关的(注意:直到目前为止,Sphinx还不支持中文作为属性的名称)。属性并不会被全文索引,他们只是按原封不动的存储在索引文件中。目前支持的属性类型如下:</p><ul><li>无符号整数(1-32位宽);</li><li>UNIX 时间戳(timestamps);</li><li>浮点值(32位,IEEE 754单精度);</li><li>字符串序列 (专指尤其计算出来的字符串序列整数值);</li><li>字符串 (版本 1.10-beta 开始支持);</li><li>多值属性 MVA(32位无符号整型值的变长序列).</li></ul><p> </p><p>由各个文档的全部的属性信息构成了一个集合,它也被称为文档信息 docinfo. 文档信息可以按如下两种方式之一存储:</p><ul><li>与全文索引数据分开存储(“外部存储extern”,在.spa文件中存储), 或者</li><li>在全文索引数据中,每出现一次文档ID 就出现相应的文档信息(“内联存储inline”,在.spd文件中存储)、</li></ul><p> </p><p>当采用外部存储方式时,searchd总是在RAM中保持一份.spa文件的拷贝(该文件包含所有文档的所有文档信息)。这是主要是为了提高性能,因为磁盘的随机访问太慢了。相反,内联存储并不需要任何额外的RAM,但代价是索引文件的体积大大地增加了;请注意,全部属性值在文档ID出现的每一处都被复制了一份,而文档ID出现的次数恰是文档中不同关键字的数目。仅当有一个很小的属性集、庞大的文本数据集和受限的RAM时,内联存储才是一个可考虑的选择。在大多数情况下,外部存储可令建立索引和检索的效率都大幅提高。</p><p>检索时,采用外部存储方式产生的的内存需求为 (1+属性总数)文档总数4字节,也就是说,带有两个属性和一个时间戳的1千万篇文档会消耗(1+2+1)10M4 = 160 MB的RAM。这是每个检索的守护进程(PER DAEMON)消耗的量,而不是每次查询,searchd仅在启动时分配160MB的内存,读入数据并在不同的查询之间保持这些数据。子进程并不会对这些数据做额外的拷贝。</p><h2>3.3. MVA (多值属性)</h2><p>多值属性MVA (multi-valued attributes)是文档属性的一种重要的特例,MVA使得向文档附加一系列的值作为属性的想法成为可能。这对文章的tags,产品类别等等非常有用。MVA属性支持过滤和分组(但不支持分组排序)。</p><p>目前MVA列表项的值被限制为32位无符号整数。列表的长度不受限制,只要有足够的RAM,任意个数的值都可以被附加到文档上(包含MVA值的.spm文件会被searchd预缓冲到RAM中)。MVA的源数据来源既可以是一个单独的查询,也可以是文档属性,参考 sql_attr_multi中的来源类型。在第一种情况中,该查询须返回文档ID和MVA值的序对;而在第二种情况中,该字段被分析为整型值。对于多值属性的输入数据的顺序没有任何限制,在索引过程中这些值会自动按文档ID分组(而相同文档ID下的数据也会排序)。</p><p>在过滤过程中,MVA属性中的任何一个值满足过滤条件,则文档与过滤条件匹配(因此通过排他性过滤的文档不会包含任何被禁止的

值)。按MVA属性分组时,一篇文档会被分到与多个不同MVA值对应的多个组。例如,如果文档集只包含一篇文档,它有一个叫做tag的MVA属性,该属性

的值是5、7和11,那么按tag的分组操作会产生三个组,它们的@count都是1,@groupby键值分别是5、7和11。还要注意,按MVA分组
可能会导致结果集中有重复的文档:因为每篇文文档可能属于不同的组,而且它可能在多个组中被选为最佳结果,这会导致重复的ID。由于历史原因,PHP
API对结果集的行进行按文档ID的有序hash,因此用PHP API进行对MVA属性的分组操作时你还需要使用 SetArrayResult().</p><h2>3.4. 索引</h2><p>为了快速地相应响应查询,Sphinx需要从文本数据中建立一种为查询做优化的特殊的数据结构。这种数据结构被称为索引(index);而建立索引的过程也叫做索引或建立索引(indexing)。</p><p>不同的索引类型是为不同的任务设计的。比如,基于磁盘的B-Tree存储结构的索引可以更新起来比较简单(容易向已有的索引插入新的文档),但是搜起来就相当慢。因此Sphinx的程序架构允许轻松实现多种不同的索引类型。</p><p>目前在Sphinx中实现的唯一一种索引类型是为最优化建立索引和检索的速度而设计的。随之而来的代价是更新索引相当的很慢。理论上讲,更新这种索引甚至可能比从头重建索引还要慢。不过大多数情况下这可以靠建立多个索引来解决索引更新慢的问题,细节请参考 第 3.11 节 “实时索引更新”.</p><p>实现更多的索引类型支持,已列入计划;目前已经包括一种可以实时更新的类型。</p><p>每个配置文件都可以按需配置足够多的索引。indexer 工具可以将它们同时重新索引(如果使用了--all选项)或者仅更新明确指出的一个。 searchd工具会为所有被指明的索引提供检索服务,而客户端可以在运行时指定使用那些索引进行检索。</p><h2>3.5. 源数据的限制</h2><p>CoreSeek/Sphinx索引的源数据有一些限制,其中最重要的一条是:</p><p>所有文档的ID必须是唯一的无符号非零整数(根据Sphinx构造时的选项,可能是32位或64位)</p><p>如果不满足这个要求,各种糟糕的情况都可能发生。例如,CoreSeek/Sphinx建立索引时可能在突然崩溃,或者由于冲突的文档ID而在索引结果中产生奇怪的结果。也可能,一只重达一吨的恐龙最后跳出你的电脑,向你扔臭蛋。不要说我没有告诉过你咯!</p><h2>3.6. 字符集、大小写转换和转换表</h2><p>当建立索引时,Sphinx从指定的数据源获得文本文档,将文本分成词的集合,再对每个词做大小写转换,于是“Abc”,“ABC”和“abc”都被当作同一个词(word,或者更学究一点,词项term)</p><p>为了正确完成上述工作,Sphinx需要知道:</p><ul><li>源文本是什么编码的;</li><li>那些字符是字母,哪些不是;</li><li>哪些字符需要被转换,以及被转换成什么.</li></ul><p>这些都可以用 charset_type 和 charset_table 选项为每个索引单独配置. charset_type 指

定文档的编码是单字节的(SBCS)还是UTF-8的。在Coreseek中,如果通过charset_dictpath设置中文词典启动了中文分词模式

后,不仅可以使用UTF-8编码的,还可以使用GBK及BIG5的编码(需要编译时提供iconv支持);但是在内部实现中,仍然是预先转换成UTF-8
编码在进行处理的. charset_table 则指定了字母类字符到它们的大小写转换版本的对应表,没有在这张表中出现的字符被认为是非字母类字符,并且在建立索引和检索时被当作词的分割符来看待。</p><p>注意,尽管默认的转换表并不包含空格符 (ASCII code 0×20, Unicode U+0020) , 但是这么做是 完全合法的。 这在某些情况下可能有用,比如在对tag云构造索引的时候,这样一个用空格分开的词集就可以被当作一个单独的查询项了.</p><p>默认转换表目前包括英文和俄文字符。欢迎提交您为其他语言撰写的转换表!</p><p>在Coreseek中,启用中文分词后,系统会使用MMSeg内置的码表(被硬编码在MMSeg的程序中),因此,charset_table在启用分词后将失效。</p><h2>3.7. SQL 数据源 (MySQL, PostgreSQL)</h2><p>对于所有的基于SQL驱动,建立索引的过程如下:</p><ul><li>连接到数据库;</li><li>执行预查询 (参见 第 11.1.11 节 “sql_query_pre:待索引数据获取前查询”) ,以便完成所有必须的初始设置,比如为MySQL连接设置编码;</li><li>执行主查询 (参见 第 11.1.12 节 “sql_query:获取待索引数据查询”) ,其返回的的数据将被索引;</li><li>执行后查询 (参见 第 11.1.30 节 “sql_query_post:数据获取后查询”) ,以便完成所有必须的清理工作;</li><li>关闭到数据库的连接;</li><li>对短语进行排序 (或者学究一点, 索引类型相关的后处理);</li><li>再次建立到数据库的连接;</li><li>执行索引后查询 (参见 第 11.1.31 节 “sql_query_post_index:数据索引后查询”) ,以便完成所有最终的清理善后工作;</li><li>再次关闭到数据库的连接.</li></ul><p>大多数参数是很直观的,例如数据库的用户名、主机、密码。不过,还有一些细节上的问题需要讨论。</p><h3>区段查询</h3><p>索引系统需要通过主查询来获取全部的文档信息,一种简单的实现是将整个表的数据读入内存,但是这可能导致整个表被锁定并使得其他操作被阻止(例如:
在MyISAM格式上的INSERT操作),同时,将浪费大量内存用于存储查询结果,诸如此类的问题吧。
为了避免出现这种情况,CoreSeek/Sphinx支持一种被称为 区段查询的技术. 首先,CoreSeek/Sphinx从数据库中取出文档ID的最小值和最大值,将由最大值和最小值定义自然数区间分成若干份,一次获取数据,建立索引。现举例如下:</p><p>例 3.1. 范围查询用法举例</p><pre><span><span># in sphinx.conf</span></span>

<span><span>sql_query_range</span></span> = SELECT MIN(id),MAX(id) FROM documents
<span><span>sql_range_step</span></span> = <span><span>1000</span></span>
<span><span>sql_query</span></span> = SELECT * FROM documents WHERE id>=<span><span>$start</span></span> AND id&lt;=<span><span>$end</span></span>
</pre><p>如果这个表(documents)中,字段ID的最小值和最大值分别是1 和2345,则sql_query将执行3次:</p><ol><li>将 $start&nbsp;替换为1,并且将&nbsp;$end 替换为 1000;</li><li>将 $start&nbsp;替换为1001,并且将&nbsp;$end 替换为 2000;</li><li>将 $start&nbsp;替换为2001,并且将&nbsp;$end 替换为 2345.</li></ol><p>显然,这对于只有2000行的表,分区查询与整个读入没有太大区别,但是当表的规模扩大到千万级(特别是对于MyISAM格式的表),分区区段查询将提供一些帮助。</p><h3>后查询(sql_post) 与 索引后查询(sql_post_index)的差异</h3><p>后查询和索引后查询的区别在于,当Sphinx获取到全部文档数据后,立即执行后查询,但是构建索引的过程仍然may因为某种原因失败。在另一方面,当索引后查询被执行时,可以理所当然的认为索引已经成功构造完了。因为构造索引可能是个漫长的过程,因此对与数据库的连接在执行后索引操作后被关闭,在执行索引后操作前被再次打开。</p><h2>3.8. xmlpipe 数据源</h2><p>xmlpipe 数据源是处于让用户能够将现有数据嵌入Sphinx而无需开发新的数据源驱动的目的被设计和提供的。它将每篇文档限制为只能包括两个可全文索引的字段,以及只能包括两个属性。xmlpipe数据源已经被废弃,在第 3.9 节 “xmlpipe2 数据源”中描述了xmlpipe的替代品xmlpipe2数据源。对于新的数据,建议采用xmlpipe2。</p><p>为了使用xmlpipe,需要将配置文件改为类似如下的样子:</p><pre><span><span>source</span></span> example_xmlpipe_<span><span>source</span></span>
{
<span><span>type</span></span> = xmlpipe
xmlpipe_<span><span>command</span></span> = perl /www/mysite.com/bin/sphinxpipe.pl
}
</pre><p>indexer 实用程序将要运行 xmlpipe_command, 所指定的命令,而后读取其向标准输出stdout上输出的数据,并对之进行解析并建立索引。 严格的说,是索引系统打开了一个与指定命令相连的管道,并从这个管道读取数据。</p><p>indexer 实用程序假定在从标准输入读入的XML格式的数据中中存在一个或更多的文档。下面是一个包括两个文档的文档数据流的例子:</p><p>例 3.2. XMLpipe 文档数据流</p><pre><span><span><</span><span><span><span>document</span></span></span><span>></span></span>
<span><span><</span><span><span><span>id</span></span></span><span>></span></span>123<span><span></</span><span><span><span>id</span></span></span><span>></span></span>
<span><span><</span><span><span><span>group</span></span></span><span>></span></span>45<span><span></</span><span><span><span>group</span></span></span><span>></span></span>
<span><span><</span><span><span><span>timestamp</span></span></span><span>></span></span>1132223498<span><span></</span><span><span><span>timestamp</span></span></span><span>></span></span>
<span><span><</span><span><span><span>title</span></span></span><span>></span></span>test title<span><span></</span><span><span><span>title</span></span></span><span>></span></span>
<span><span><</span><span><span><span>body</span></span></span><span>></span></span>
this is my document body
<span><span></</span><span><span><span>body</span></span></span><span>></span></span>
<span><span></</span><span><span><span>document</span></span></span><span>></span></span>

<span><span><</span><span><span><span>document</span></span></span><span>></span></span>
<span><span><</span><span><span><span>id</span></span></span><span>></span></span>124<span><span></</span><span><span><span>id</span></span></span><span>></span></span>
<span><span><</span><span><span><span>group</span></span></span><span>></span></span>46<span><span></</span><span><span><span>group</span></span></span><span>></span></span>
<span><span><</span><span><span><span>timestamp</span></span></span><span>></span></span>1132223498<span><span></</span><span><span><span>timestamp</span></span></span><span>></span></span>
<span><span><</span><span><span><span>title</span></span></span><span>></span></span>another test<span><span></</span><span><span><span>title</span></span></span><span>></span></span>
<span><span><</span><span><span><span>body</span></span></span><span>></span></span>
this is another document
<span><span></</span><span><span><span>body</span></span></span><span>></span></span>
<span><span></</span><span><span><span>document</span></span></span><span>></span></span>
</pre><p> </p><p>遗留的xmlpipe数据驱动使用内置的解析器来解析xml文档,这个解析器的速度非常快,但是并没有提供对XML格式完整支持。这个解析器需要文档中必须包括全部的字段,并且严格按照例子中给出的格式给出,而且字段的出现顺序需要严格按照例子中给出的顺序。仅有一个字段timestamp是可选的,它的缺省值为1。</p><h2>3.9. xmlpipe2 数据源</h2><p>xmlpipe2使你可以用另一种自定义的XML格式向Sphinx传输任意文本数据和属性数据。数据模式(即数据字段的集合或者属性集)可以由XML流本身指定,也可以在配置文件中数据源的配置部分中指定。</p><p>在对xmlpipe2数据源做索引时,索引器运行指定的命令,打开一个连接到前述命令标准输出的管道,并等待接受具有正确格式的XML数据流。以下是一个数据流的样本:</p><p>例 3.3. xmlpipe2 文档数据流</p><pre><span><span><span><span><?</span></span></span><span>xml version=</span><span><span><span>"1.0"</span></span></span><span> encoding=</span><span><span><span>"utf-8"</span></span></span><span><span><span>?></span></span></span></span>
<span><span><</span><span><span><span>sphinx:docset</span></span></span><span>></span></span>

<span><span><</span><span><span><span>sphinx:schema</span></span></span><span>></span></span>
<span><span><</span><span><span><span>sphinx:field</span></span></span><span> </span><span><span><span>name</span></span></span><span>=</span><span><span><span>"subject"</span></span></span><span>/></span></span>
<span><span><</span><span><span><span>sphinx:field</span></span></span><span> </span><span><span><span>name</span></span></span><span>=</span><span><span><span>"content"</span></span></span><span>/></span></span>
<span><span><</span><span><span><span>sphinx:attr</span></span></span><span> </span><span><span><span>name</span></span></span><span>=</span><span><span><span>"published"</span></span></span><span> </span><span><span><span>type</span></span></span><span>=</span><span><span><span>"timestamp"</span></span></span><span>/></span></span>
<span><span><</span><span><span><span>sphinx:attr</span></span></span><span> </span><span><span><span>name</span></span></span><span>=</span><span><span><span>"author_id"</span></span></span><span> </span><span><span><span>type</span></span></span><span>=</span><span><span><span>"int"</span></span></span><span> </span><span><span><span>bits</span></span></span><span>=</span><span><span><span>"16"</span></span></span><span> </span><span><span><span>default</span></span></span><span>=</span><span><span><span>"1"</span></span></span><span>/></span></span>
<span><span></</span><span><span><span>sphinx:schema</span></span></span><span>></span></span>

<span><span><</span><span><span><span>sphinx:document</span></span></span><span> </span><span><span><span>id</span></span></span><span>=</span><span><span><span>"1234"</span></span></span><span>></span></span>
<span><span><</span><span><span><span>content</span></span></span><span>></span></span>this is the main content <![CDATA[[and this <cdata> entry
must be handled properly by xml parser lib]]><span><span></</span><span><span><span>content</span></span></span><span>></span></span>
<span><span><</span><span><span><span>published</span></span></span><span>></span></span>1012325463<span><span></</span><span><span><span>published</span></span></span><span>></span></span>
<span><span><</span><span><span><span>subject</span></span></span><span>></span></span>note how field/attr tags can be
in <span><span><</span><span><span><span>b</span></span></span><span>></span></span>randomized<span><span></</span><span><span><span>b</span></span></span><span>></span></span> order<span><span></</span><span><span><span>subject</span></span></span><span>></span></span>
<span><span><</span><span><span><span>misc</span></span></span><span>></span></span>some undeclared element<span><span></</span><span><span><span>misc</span></span></span><span>></span></span>
<span><span></</span><span><span><span>sphinx:document</span></span></span><span>></span></span>

<span><span><</span><span><span><span>sphinx:document</span></span></span><span> </span><span><span><span>id</span></span></span><span>=</span><span><span><span>"1235"</span></span></span><span>></span></span>
<span><span><</span><span><span><span>subject</span></span></span><span>></span></span>another subject<span><span></</span><span><span><span>subject</span></span></span><span>></span></span>
<span><span><</span><span><span><span>content</span></span></span><span>></span></span>here comes another document, and i am given to understand,
that in-document field order must not matter, sir<span><span></</span><span><span><span>content</span></span></span><span>></span></span>
<span><span><</span><span><span><span>published</span></span></span><span>></span></span>1012325467<span><span></</span><span><span><span>published</span></span></span><span>></span></span>
<span><span></</span><span><span><span>sphinx:document</span></span></span><span>></span></span>

<span><span><!-- ... even more sphinx:document entries here ... --></span></span>

<span><span><</span><span><span><span>sphinx:killlist</span></span></span><span>></span></span>
<span><span><</span><span><span><span>id</span></span></span><span>></span></span>1234<span><span></</span><span><span><span>id</span></span></span><span>></span></span>
<span><span><</span><span><span><span>id</span></span></span><span>></span></span>4567<span><span></</span><span><span><span>id</span></span></span><span>></span></span>
<span><span></</span><span><span><span>sphinx:killlist</span></span></span><span>></span></span>

<span><span></</span><span><span><span>sphinx:docset</span></span></span><span>></span></span></pre><p> </p><p>任意多的数据字段和属性都是允许的。数据字段和属性在同一文档元素中出现的先后顺序没有特别要求。。单一字段数据的最大长度有限制,超过2MB的数据会被截短到2MB(但这个限制可以在配置文件中数据源部分中修改)。</p><p>XML数据模式(Schema),即数据字段和属性的完整列表,必须在任何文档被分析之前就确定。这既可以在配置文件中用xmlpipe_field和xmlpipe_attr_XXX选
项指定,也可以就在数据流中用<sphinx:schema>元素指定。
<sphinx:schema>元素是可选的,但如果出现,就必须是<sphinx:docset>元素的第一个子元素。如果没
有在数据流中内嵌的数据模式定义,配置文件中的相关设置就会生效,否则数据流内嵌的设置被优先采用。</p><p>未知类型的标签(既不是数据字段,也不是属性的标签)会被忽略,但会给出警告。在上面的例子中,<misc>标签会被忽略。所有嵌入在其他标签中的标签及其属性都会被无视(例如上述例子中嵌入在<subject>标签中的<b>标签)</p><p>支持输入数据流的何种字符编码取决于系统中是否安装了iconv. xmlpipe2是用 libexpat解析器解析的,该解析器内置对 US-ASCII, ISO-8859-1, UTF-8 和一些 UTF-16 变体的支持. CoreSeek/Sphinx的configure 脚本也会检查 libiconv 是否存在并使用它来处理其他的字符编码。 libexpat 也隐含的要求在CoreSeek/Sphinx端使用UTF-8,因为它返回的分析过的数据总是UTF-8的。</p><p>xmlpipe2可以识别的XML元素(标签)(以及前述元素可用的属性)如下:</p><dl><dt>

       sphinx:docset 
     </dt><dd>
       顶级元素,用于标明并包括xmlpipe2文档. 
     </dd><dt>
       sphinx:schema 
     </dt><dd>
       可选元素,它要么是sphinx:docset的第一个子元素,要么干脆不出现。声明文档的模式。包括数据字段和属性的声明。若此元素出现,则它会覆盖配置文件中对数据源的设定. 
     </dd><dt>
       sphinx:field 
     </dt><dd>
       可选元素,sphinx:schema的子元素。声明一个全文数据字段. 可用的属性包括: 
      <div> 
       <ul><li>“name”, 它指定了字段的名称,后续数据文档中具有此名称的元素的数据都被当作待检索的全文数据对待.</li><li>“attr”, 用于特别指出将该字段作为字符串或者词汇数统计属性. 可以设置的值为 “string” 或 “wordcount”. 版本 1.10-beta 开始引入.</li></ul> 
      </div> 
     </dd><dt>
       sphinx:attr 
     </dt><dd>
       可选元素,sphinx:schema的子元素。用于声明具体属性。可用的属性包括: 
      <div> 
       <ul><li>“name”, 设定该属性名称,后续文档中具有该名称的元素应被当作一个属性对待.</li><li>“type”, 设定该属性的类型。可能的类型包括 “int”, “timestamp”, “str2ordinal”, “bool”, “float” 和 “multi”.</li><li>“bits”, 设定“int”型属性的宽度,有效值为1到32.</li><li>“default”, 设定该属性的默认值,若后续文档中没有指定这个属性,则使用此默认值.</li></ul> 
      </div> 
     </dd><dt>
       sphinx:document 
     </dt><dd>
       

必须出现的元素,必须是sphinx:docset的子元素。包含任意多的其他元素,这些子元素带有待索引的数据字段和属性值,而这些数据字段或
属性值既可以是用sphinx:field和sphinx:attr元素声明的,也可以在配置文件中声明。唯一的已知属性是“id”,它必须包含一个唯一
的整型的文档ID.

     </dd><dt>
       sphinx:killlist 
     </dt><dd>
       可选元素,必须是sphinx:docset的子元素。 它包含一批“id“元素,其内容是文档编号ID,将被作为当前索引的&nbsp; 
      <a href="#conf-sql-query-killlist">失效名单列表</a>&nbsp;。 
     </dd></dl><p>&nbsp;</p><h2>3.10.&nbsp;Python 数据源</h2><p>Coreseek支持使用Python编写数据源脚本,从而可以很方便的扩展CoreSeek/Sphinx的功能,来轻易的从任何Python可以操作的地方获取需要进行检索的数据。当前,Python几乎支持所有的SQL数据库以及NoSql存储系统,可以查看<a href="http://wiki.python.org/moin/DatabaseInterfaces" target="_top">Python DatabaseInterfaces</a>获得详细列表。</p><pre><code>python <span><span>#用于配置Python数据源程序的PYTHONPATH</span></span>

{
path = /usr/<span><span>local</span></span>/coreseek/etc/pysource
path = /usr/<span><span>local</span></span>/coreseek/etc/pysource/csft_demo
}

<span><span>source</span></span> sourcename
{
<span><span>type</span></span> = python <span><span>#数据类型</span></span>
name = csft_demo.MainSource <span><span>#调用的python的类名称</span></span>
}</pre><p>在以上配置中,对应的Python数据源脚本,为/usr/local/coreseek/etc/pysource/csft_demo/__init__.py,执行索引操作时,将从该脚本获取数据,请查看第 12.3 节 “Python数据源程序接口”了解细节。</p><h2>3.11. 实时索引更新</h2><p>当前主要有两种方法来维护全文索引的内容是最新的。请注意,但是,这两种处理方法 的任务是应对全文数据更新,而不是 属性更新。从版本0.9.8开始支持即时的属性更新。参看 UpdateAttributes()API 调用了解详情。</p><p>方法一,使用基于磁盘的索引,手动分区,然后定期重建较小的分区(被称为“增量”)。通过尽可能的减小重建部分的大小,可以将平均索引滞后时间降低到30~60秒。在0.9.x版本中,这是唯一可用的方法。在一个巨大的文档集上,这可能是最有效的一种方法。参看第 3.12 节 “增量索引更新”了解详情。</p><p>方法二,版本1.x(从版本1.10-beta开始)增加了实时索引(简写为Rt索引)的支持,用于及时更新全文数据。在RT索引上的更新,可以在
1~2毫秒(0.001-0.002秒)内出现在搜索结果中。然而,RT实时索引在处理较大数据量的批量索引上效率并不高。参看 第 4 章 RT实时索引 了解详情。</p><h2>3.12. 增量索引更新</h2><p>有这么一种常见的情况:整个数据集非常大,以至于难于经常性的重建索引,但是每次新增的记录却相当地少。一个典型的例子是:一个论坛有1000000个已经归档的帖子,但每天只有1000个新帖子。</p><p>在这种情况下可以用所谓的“主索引+增量索引”(main+delta)模式来实现“近实时”的索引更新。</p><p>这种方法的基本思路是设置两个数据源和两个索引,对很少更新或根本不更新的数据建立主索引,而对新增文档建立增量索引。在上述例子中,那

1000000个已经归档的帖子放在主索引中,而每天新增的1000个帖子则放在增量索引中。增量索引更新的频率可以非常快,而文档可以在出现几分种内就
可以被检索到。</p><p>确定具体某一文档的分属那个索引的分类工作可以自动完成。一个可选的方案是,建立一个计数表,记录将文档集分成两部分的那个文档ID,而每次重新构建主索引时,这个表都会被更新。</p><p>例 3.4. 完全自动化的实时索引</p><pre><span><span># in MySQL</span></span>
CREATE TABLE sph_counter
(
counter_id INTEGER PRIMARY KEY NOT NULL,
max_doc_id INTEGER NOT NULL
);

<span><span># in sphinx.conf</span></span>
source main
{
<span><span># ...</span></span>
sql_query_pre = SET NAMES utf8
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query = SELECT id, title, body FROM documents \
WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}

source delta : main
{
sql_query_pre = SET NAMES utf8
sql_query = SELECT id, title, body FROM documents \
WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}

index main
{
source = main
path = /path/to/main
<span><span># ... all the other settings</span></span>
}

<span><span># note how all other settings are copied from main,</span></span>
<span><span># but source and path are overridden (they MUST be)</span></span>
index delta : main
{
source = delta
path = /path/to/delta
}
</pre><p> </p><p>请注意,上例中我们显示设置了数据源delta的sql_query_pre选项,覆盖了全局设置。必须显示地覆盖这个选项,否则对delta做索引的时候也会运行那条REPLACE查询,那样会导致delta源中选出的数据为空。可是简单地将delta的sql_query_pre设置成空也不行,因为在继承来的数据源上第一次运行这个指令的时候,继承来的所有值都会被清空,这样编码设置的部分也会丢失。因此需要再次显式调用编码设置查询。</p><h2>3.13. 索引合并</h2><p>合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引对应的数据)。因此indexer有这个选项。合并索引一般比重新索引快,但在大型索引上仍然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还是比重新索引少)</p><p>基本的命令语法如下:</p><pre>indexer <span><span>--merge DSTINDEX SRCINDEX [--rotate]</span></span></pre><p>SRCINDEX的内容被合并到DSTINDEX中,因此只有DSTINDEX索引会被改变。 若DSTINDEX已经被searchd于提供服务,则--rotate参数是必须的。 最初设计的使用模式是,将小量的更新从SRCINDEX合并到DSTINDEX中。 因此,当属性被合并时,一旦出现了重复的文档ID,SRCINDEX中的属性值更优先(会覆盖DSTINDEX中的值)。 不过要注意,“旧的”关键字在这个过程中并不会被自动删除。 例如,在DSTINDEX中有一个叫做“old”的关键字与文档123相关联,而在SRCINDEX中则有关键字“new”与同一个文档相关,那么在合并后用这两个关键字都能找到文档123。 您可以给出一个显式条件来将文档从DSTINDEX中移除,以便应对这种情况,相关的开关是--merge-dst-range:</p><pre>indexer <span><span>--merge main delta --merge-dst-range deleted 0 0</span></span></pre><p>这个开关允许您在合并过程中对目标索引实施过滤。过滤器可以有多个,只有满足全部过滤条件的文档才会在最终合并后的索引中出现。在上述例子中,过滤器只允许“deleted”为0的那些条件通过,而去除所有标记为已删除(“deleted”)的记录(可以通过调用UpdateAttributes()设置文档的属性)。</p><h2>第 4 章 RT实时索引</h2><p>目录</p><dl><dt>

     <a href="#rt-overview">4.1. RT实时索引概览</a> 
    </dt><dt> 
     <a href="#rt-caveats">4.2. RT实时索引使用注意事项</a> 
    </dt><dt> 
     <a href="#rt-internals">4.3. RT实时索引原理</a> 
    </dt><dt> 
     <a href="#rt-binlog">4.4. 二进制日志</a> 
    </dt></dl><p>实时索引(或者简称为RT索引)是一个新的索引后端,你可以实时的插入、更新或者删除文档(行)。RT索引在版本1.10-beta中加入。查询时

可以使用SPhinxAPI、SphinxQL、SphinxSE,不过目前只能使用SphinxQL来更新。详细的SphinxQL参考请查看 第 7 章 SphinxQL 指南.</p><h2>4.1. RT实时索引概览</h2><p>和其他类型的索引类似,RT索引在 sphinx.conf中定义。它与磁盘索引有着明显的差异,a) 数据源设置不需要而且会被忽略,b) 你应该明确的定义所有的文本字段,而不仅仅是属性。下面是例子</p><p>例 4.1. RT实时索引定义</p><pre>index rt
{
type = rt
path = /usr/local/sphinx/data/rt
rt_field = title
rt_field = content
rt_attr_uint = gid
}
</pre><p>RT索引目前还在继续开发完善中(从版本1.10-beta开始)。
因此,他可能缺乏某些特定的功能:例如,前缀/中缀索引,MVA属性等目前尚不支持。但是,所有常规索引功能和搜索功能都已经实现,并且经过了内部的测
试。我们还有一些实际运营生产环境(并非最不重要的部分)已经在使用RT索引,并且取得了较好的效果。</p><p>RT索引可以使用MySQL协议访问,支持INSERT, REPLACE, DELETE, 以及 SELECT等SQL语句. 以下是一个在演示索引上的操作会话例子:</p><pre>$ mysql -h <span><span>127.0</span></span>.<span><span>0</span></span>.<span><span>1</span></span> -P <span><span>9306</span></span>
Welcome to the MySQL monitor. Commands <span><span>end</span></span> with ; <span><span>or</span></span> \g.
Your MySQL connection id is <span><span>1</span></span>
Server <span><span>version:</span></span> <span><span>1.10</span></span>-dev (r2153)

Type <span><span>'help;'</span></span> <span><span>or</span></span> <span><span>'\h'</span></span> <span><span>for</span></span> help. Type <span><span>'\c'</span></span> to clear the buffer.

mysql> INSERT INTO rt VALUES ( <span><span>1</span></span>, <span><span>'first record'</span></span>, <span><span>'test one'</span></span>, <span><span>123</span></span> );
Query OK, <span><span>1</span></span> row affected (<span><span>0</span></span>.<span><span>05</span></span> sec)

mysql> INSERT INTO rt VALUES ( <span><span>2</span></span>, <span><span>'second record'</span></span>, <span><span>'test two'</span></span>, <span><span>234</span></span> );
Query OK, <span><span>1</span></span> row affected (<span><span>0</span></span>.<span><span>00</span></span> sec)

mysql> SELECT * FROM rt;
<span><span>id</span></span> weight <span><span>gid</span></span>
<span><span>1</span></span> <span><span>1</span></span> <span><span>123</span></span>
<span><span>2</span></span> <span><span>1</span></span> <span><span>234</span></span>

<span><span>2</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>02</span></span> sec)

mysql> SELECT * FROM rt WHERE MATCH(<span><span>'test'</span></span>);
<span><span>id</span></span> weight <span><span>gid</span></span>
<span><span>1</span></span> <span><span>1643</span></span> <span><span>123</span></span>
<span><span>2</span></span> <span><span>1643</span></span> <span><span>234</span></span>

<span><span>2</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>01</span></span> sec)

mysql> SELECT * FROM rt WHERE MATCH(<span><span>'@title test'</span></span>);
Empty set (<span><span>0</span></span>.<span><span>00</span></span> sec)
</pre><p>并行和批量INSERT语法都支持,例如:可以先指定一个列的字段,然后同时插入多行。
删除可以使用DELETE语句,但是目前唯一支持的语法是DELETE FROM <index> WHERE
id=<id>。REPLACE也支持,可以用于更新数据。</p><pre>mysql> INSERT INTO rt ( id, title ) VALUES ( <span><span>3</span></span>, <span><span>'third row'</span></span> ), ( <span><span>4</span></span>, <span><span>'fourth entry'</span></span> );
Query OK, <span><span>2</span></span> rows affected (<span><span>0</span></span>.<span><span>01</span></span> sec)

mysql> SELECT * FROM rt;
<span><span>id</span></span> weight <span><span>gid</span></span>
<span><span>1</span></span> <span><span>1</span></span> <span><span>123</span></span>
<span><span>2</span></span> <span><span>1</span></span> <span><span>234</span></span>
<span><span>3</span></span> <span><span>1</span></span> <span><span>0</span></span>
<span><span>4</span></span> <span><span>1</span></span> <span><span>0</span></span>

<span><span>4</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>00</span></span> sec)

mysql> DELETE FROM rt WHERE id=<span><span>2</span></span>;
Query OK, <span><span>0</span></span> rows affected (<span><span>0</span></span>.<span><span>00</span></span> sec)

mysql> SELECT * FROM rt WHERE MATCH(<span><span>'test'</span></span>);
<span><span>id</span></span> weight <span><span>gid</span></span>
<span><span>1</span></span> <span><span>1500</span></span> <span><span>123</span></span>

<span><span>1</span></span> row <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>00</span></span> sec)

mysql> INSERT INTO rt VALUES ( <span><span>1</span></span>, <span><span>'first record on steroids'</span></span>, <span><span>'test one'</span></span>, <span><span>123</span></span> );
ERROR <span><span>1064</span></span> (<span><span>42000</span></span>): duplicate id <span><span>'1'</span></span>

mysql> REPLACE INTO rt VALUES ( <span><span>1</span></span>, <span><span>'first record on steroids'</span></span>, <span><span>'test one'</span></span>, <span><span>123</span></span> );
Query OK, <span><span>1</span></span> row affected (<span><span>0</span></span>.<span><span>01</span></span> sec)

mysql> SELECT * FROM rt WHERE MATCH(<span><span>'steroids'</span></span>);
<span><span>id</span></span> weight <span><span>gid</span></span>
<span><span>1</span></span> <span><span>1500</span></span> <span><span>123</span></span>

<span><span>1</span></span> row <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>01</span></span> sec)</pre><p>RT索引中存储的数据可以在正常关闭后继续存在。如果开启了二进制日志,则可以在崩溃或者非正常关闭后继续存在,并在随后的启动中恢复。</p><h2>4.2. RT实时索引使用注意事项</h2><p>在版本1.10-beta时,RT索引还处于特殊功能测试阶段:虽然没有大的问题,但是还有一些总所周知的以至于可以搅局的问题,以及一些特定的使用限制。这些使用限制在下面一一列出:</p><ul><li>前缀和中缀索引尚不支持.</li><li>MVA属性尚不支持.</li><li>常规的磁盘块优化尚未实现</li><li>在索引初始化创建时,属性按照类别被重新排序,他们的顺序如下:uint, bigint, float,
timestamp, string.
因此,在执行INSERT时,如果没有明确指定列名,就需要依次首先给出所有uint列的值,然后是bigint列的值,以此类推。</li><li>默认保留的内存块大小(rt_mem_limit)为32M,对于大型索引而言可能性能不好,如果打算要索引GB级别的数据,你应该增大到256~1024M。</li><li>较高比例的DELETE/REPLACE可导致大量的失效名单碎片和影响搜索性能。</li><li>目前的系统对事务处理没有做强制限制;太多并发的INSERT/REPLACE事务可能会耗费大量的内存。</li><li>在二进制日志损坏的情况下,恢复将在第一个损坏的事务处停止,即使在技术上可以继续搜寻随后完好的事务以及重新使用,也无济于事。当然,二进制日志文件中间损坏的情况(由于是片状磁盘/CDD/磁带?)是极为罕见的,甚至永远不会碰到。</li></ul><h2>4.3. RT实时索引原理</h2><p>RT索引内部是区块化的。它保留了内存区块用于存储所有最新的变化。内存区块的内存使用由每个索引设置中的rt_mem_limit指令严格限制。一旦内存区块的增长超过这个限制,就会根据其内容创建一个新的磁盘区块,并将内存区块复位。因此,在RT索引中,虽然大多数的变化都会在内存中瞬间执行完成(毫秒级),这些内存区块溢满到磁盘区块建立的变化会有一定的延时(几秒钟)。</p><p>磁盘区块其实就是基于磁盘的索引。但是他们是RT索引的一部分并由其自动管理,所以无需手动配置,就算你想要管理目前也没有提供方式。因为只有在RT索引的内存区块达到了限制时才会创建一个新的磁盘区块,每个磁盘区块的大小基本上为rt_mem_limit 个字节。</p><p>一般而言,最好设置一个较大限制值,使得刷新频率和索引碎片(磁盘区块)都尽可能最小化。例如,在一个专门的搜索服务器上要处理一个较大的RT索引,建议将rt_mem_limit设置为1~2GB。全局的内存限制计划实现,但是在版本1.10-beta中尚未支持。</p><p>磁盘区块的全文索引数据并不会真的被修改,所以全文索引字段的变化(即删除行和更新)其实使用失效名单列表排除来自于磁盘区块的先前版本的行,但是

实际上并不会从物理上清除数据。因此,在一个具有较高全文索引更新率的情况下,最终可能被先前版本的行污染,以及降低搜索性能。已经计划从索引中物理清除
以提高性能,但是在版本1.10-beta中尚未支持。</p><p>内存区块中的数据会在正常关闭时写入到磁盘,并在启动时再次载入。但是在守护进程或者服务器崩溃的情况下,内存区块中的更新数据可能会丢失。为了防止这种情况的发生,可以使用事务专用的二进制日志。查看 第 4.4 节 “二进制日志” 了解详情。</p><p>在RT索引中全文变化是基于事务的。他们会被存储到每个线程处理池中,并在COMMIT时立刻应用生效。在单次COMMIT中提交大量的批量更新有助于索引的快速生成。</p><h2>4.4. 二进制日志</h2><p>二进制日志本质上是一种故障恢复机制。当开启二进制日志时,searchd将每条事务处理写入到二进制日志,并可以用于在非正常关闭后恢复数据。当正常关闭时,内存区块的数据会写入到磁盘,然后删除所有的二进制日志文件。</p><p>在正常的操作中,每当达到binlog_max_log_size 的限制 (默认为 128M)时,就会打开一个新的二进制日志文件。已有的,已关闭的二进制日志文件会一直保存,直到它们存储的内容被刷新到磁盘区块中。如果设置限制为0,则在searchd运行的过程中永远不会删除二进制日志文件;但是在正常关闭时,还是会删除掉。</p><p>目前有三种不同的二进制日志刷新策略,由binlog_flush

项来控制,设置为0表示每秒将日志刷新一次到操作系统和同步到磁盘,设置为1表示表示每次事务处理都刷新和同步,设置为2(默认模式)表示每次事务处理时
刷新单每秒同步一次。同步相对而言是比较慢的,因为他需要将数据物理写入到磁盘,所以模式1是最安全的模式(每次提交的事物处理,都确保是写入到磁盘
的)。刷新日志到操作系统是为了防止searchd崩溃时数据丢失,如果操作系统没有崩溃则数据可以安全写入到磁盘。模式2是默认的模式。</p><p>在非正常关闭后再次重启此进行数据恢复,二进制日志的内容会被重新执行,最后正常存储的所有事务处理都会被还原。事务处理都会被校验,以确保二进制日志文件中损坏的垃圾数据不会被

重新执行;因而一个破坏的事务处理将被检测到,在目前版本中它将不会被重新执行。事务处理都从一个特殊标志和时间戳开始,这样子为技术上处理跳过破坏的事

务处理并从下一条正确的开始继续执行、或者从某个指定时间戳开始重新执行事务提供了可能(时间点恢复),但是在版本1.10-beta时尚未实现该功能。</p><p>二进制日志存在一个副作用,那就是在一个小的RT索上更新时,除非正常关机,否则内存区块完全充足导致二进制日志文件不断增长而又永远都不会被删除

掉。二进制日志基本上只追加相对于最后在磁盘上完好保存状态的增量,除非内存区块得到保存,否则它们不会被删除。一个不断增长的二进制日志对于磁盘使用和
崩溃恢复时间都不是好事。从版本2.0.1-beta开始,可以通过rt_flush_period指令配置searchd来周期性刷新内存区块到磁盘以解决这个问题。当周期性刷新启用时,searchd会保留一个独立的线程用于检查RT索引的内存区块是否需要写回到磁盘。一旦写回到磁盘,各个二进制日志都可以(能够)安全的删除。</p><p>请注意rt_flush_period 仅控制检查发生的频率。但是这并不保证特别是内存区块一定会得到保存。例如,定期重新保存一个巨大的内存区块但是仅更新了寥寥数行是没有任何意义的。searchd守护进程将会通过某些启发式方法判断是否需要真的执行刷新。</p><h2>第 5 章 搜索</h2><p>目录</p><dl><dt>

     <a href="#matching-modes">5.1. 匹配模式</a> 
    </dt><dt> 
     <a href="#boolean-syntax">5.2. 布尔查询语法</a> 
    </dt><dt> 
     <a href="#extended-syntax">5.3. 扩展查询语法</a> 
    </dt><dt> 
     <a href="#weighting">5.4. 权值计算</a> 
    </dt><dt> 
     <a href="#expressions">5.5. 表达式,函数,运算符</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#operators">5.5.1. 运算符</a> 
      </dt><dt> 
       <a href="#numeric-functions">5.5.2. 数值函数</a> 
      </dt><dt> 
       <a href="#date-time-functions">5.5.3. 日期和时间函数</a> 
      </dt><dt> 
       <a href="#type-conversion-functions">5.5.4. 类型转换函数</a> 
      </dt><dt> 
       <a href="#comparison-functions">5.5.5. 比较函数</a> 
      </dt><dt> 
       <a href="#misc-functions">5.5.6. 其它函数</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#sorting-modes">5.6. 排序模式</a> 
    </dt><dt> 
     <a href="#clustering">5.7. 结果分组(聚类)</a> 
    </dt><dt> 
     <a href="#distributed">5.8. 分布式搜索</a> 
    </dt><dt> 
     <a href="#query-log-format">5.9. 搜索服务(<code>searchd</code>) 查询日志格式</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#plain-log-format">5.9.1. 纯文本日志格式</a> 
      </dt><dt> 
       <a href="#sphinxql-log-format">5.9.2. SphinxQL 日志格式</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#sphinxql">5.10. MySQL 协议支持与 SphinxQL</a> 
    </dt><dt> 
     <a href="#multi-queries">5.11. 批量查询</a> 
    </dt><dt> 
     <a href="#collations">5.12. 字符串排序规则</a> 
    </dt><dt> 
     <a href="#udf">5.13. 用户自定义函数 (UDF)</a> 
    </dt></dl><h2>5.1.&nbsp;匹配模式</h2><p>有如下可选的匹配模式:</p><ul><li>SPH_MATCH_ALL, 匹配所有查询词(默认模式);</li><li>SPH_MATCH_ANY, 匹配查询词中的任意一个;</li><li>SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配;</li><li>SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式 (参见&nbsp;<a href="#boolean-syntax">第&nbsp;5.2&nbsp;节 “布尔查询语法”</a>);</li><li>SPH_MATCH_EXTENDED, 将查询看作一个CoreSeek/Sphinx内部查询语言的表达式 (参见&nbsp;<a href="#extended-syntax">第&nbsp;5.3&nbsp;节 “扩展查询语法”</a>).

从版本Coreseek 3/Sphinx 0.9.9开始,
这个选项被选项SPH_MATCH_EXTENDED2代替,它提供了更多功能和更佳的性能。保留这个选项是为了与遗留的旧代码兼容——这样即使
Sphinx及其组件包括API升级的时候,旧的应用程序代码还能够继续工作。</li><li>SPH_MATCH_EXTENDED2, 使用第二版的“扩展匹配模式”对查询进行匹配.</li><li>SPH_MATCH_FULLSCAN, 强制使用下文所述的“完整扫描”模式来对查询进行匹配。注意,在此模式下,所有的查询词都被忽略,尽管过滤器、过滤器范围以及分组仍然起作用,但任何文本匹配都不会发生.</li></ul><p> </p><p>当如下条件满足时,SPH_MATCH_FULLSCAN模式自动代替其他指定的模式被激活:</p><ol><li>查询串是空的(即长度字符串为零)</li><li>docinfo 存储方式为 extern.</li></ol><p>在完整扫描模式中,全部已索引的文档都被看作是匹配的。这类匹配仍然会被过滤、排序或分组,但是并不会做任何真正的全文检索。这种模式可以用来统一
全文检索和非全文检索的代码,或者减轻SQL服务器的负担(有些时候Sphinx扫描的速度要优于类似的MySQL查询)。
“在论坛中搜索帖子”这件事可用作完整搜索模式的例子:用SetFilter()指定用户ID但不提供任何查询词,Sphinx会匹配SetFilter()所能匹配的全部文档,也就是这个用户ID对应的全部帖子。默认情况下,其结果的第一排序标准是相关度,其次是Sphinx文档ID,正序(较老的文档在前)。</p><p>注意,在完整扫描模式中,文档必须有至少一个属性。否则,即便设置docinfo的存储方式为extern,也无法启用完整扫描模式。</p><h2>5.2. 布尔查询语法</h2><p>布尔查询SPH_MATCH_BOOLEAN允许使用下列特殊运算符:</p><ul><li>显式的与(AND)运算符:hello & world </li><li>或(OR)运算符:hello | world </li><li>非(NOT)运算符:hello -world
hello !world </li><li>分组(grouping):( hello world ) </li></ul><p>以下是一个使用了如上全部运算符的例子:</p><p>例 5.1. 布尔查询例子</p><pre>( cat -dog ) | ( cat -mouse)</pre><p> </p><p>与(AND)运算符为默认操作,所以“hello world”其实就是“hello & world”</p><p>或(OR)运算符的优先级高于与运算符,因此“lookingfor cat | dog | mouse”意思是”looking for ( cat | dog | mouse )” 而不是 ”(looking for cat) | dog | mouse”</p><p>像“-dog”这种查询不能被执行,因为它差不多包括索引所有文档。这既有技术上的原因,也有性能上的原因。从技术上说,Sphinx并不总是保持一个全部文档ID的列表。性能方面,当文档集非常大的时候(即10-100M个文档),对这种执行查询可能需要很长的时间。</p><h2>5.3. 扩展查询语法</h2><p>在扩展查询模式SPH_MATCH_EXTENDED2中可以使用如下特殊运算符:</p><ul><li>或(OR)运算符:hello | world </li><li>非(NOT)运算符:hello -world
hello !world </li><li>字段(field)搜索符:@title hello @body world </li><li>字段限位修饰符(版本Coreseek 3/Sphinx 0.9.9-rc1中引入):@body[50] hello </li><li>多字段搜索符:@(title,body) hello world </li><li>全字段搜索符:@ hello </li><li>词组搜索符:"hello world" </li><li>近似距离搜索符:"hello world"~10 </li><li>阀值匹配符:"the world is a wonderful place"/3 </li><li>严格有序搜索符(即“在前”搜索符):aaa << bbb << ccc </li><li>严格形式修饰符(版本Coreseek 3/Sphinx 0.9.9-rc1中引入):raining =cats and =dogs </li><li>字段开始和字段结束修饰符 (版本Coreseek 3.1/Sphinx 0.9.9-rc2中引入):^hello world$ </li><li>NEAR, 广义临近运算符 (版本2.0.1-beta中引入):hello NEAR/3 world NEAR/4 "my test" </li><li>SENTENCE 句子运算符 (版本2.0.1-beta中引入):all SENTENCE words SENTENCE "in one sentence" </li><li>PARAGRAPH 段落运算符 (版本2.0.1-beta中引入):"Bill Gates" PARAGRAPH "Steve Jobs" </li><li>ZONE 区域限制运算符 (版本2.0.1-beta中引入):ZONE:(h3,h4) only in these titles </li></ul><p>以下是上述某些运算符的示例:</p><p>例 5.2. 扩展匹配模式:查询例子</p><pre><span><span>"hello world"</span></span> <span><span>@title</span></span> <span><span>"example program"</span></span>~<span><span>10</span></span> <span><span>@body</span></span> python -(php|perl) @ code</pre><p>例子中查询的完整解释如下:</p><ul><li>在文档的任意字段中找相邻的“hello”和“world”</li><li>不仅如此,符合上述条件的文档的title字段中还必须包含
“example”和“program”这两个词,并且他们之间至多有10个(不包括10个)其他的词(例如“example PHP
program”可以匹配,但“example script to introduce outside data into the correct
context for your program”就不行,因为中间有10个或以上的词。</li><li>同时,body字段必须含有词“python”,但既没有“php”也没有“perl”</li><li>最后, 任一字段中包含”code“.</li></ul><p> </p><p>与(AND)操作为默认操作,因此“hello world”意思是“hello”和“world”必须同时存在文档才能匹配。</p><p>或(OR)运算符的优先级要高于与运算符,因此”looking for cat | dog | mouse” 意思是”looking for ( cat | dog | mouse )” 而不是“(looking for cat) | dog | mouse”;</p><p>字段限制(field limit)符(field limit)将其后指定的搜索限制在某个特定的字段中。通常,如果给出的字段名实际并不存在,你会得到一条错误信息。但可以通过在查询的最开始处加上@@relaxed选项来放宽限制。</p><pre>@<span><span>@relaxed</span></span> <span><span>@nosuchfield</span></span> my query</pre><p>当搜索多个具有不同schema的索引时这可能有用。</p><p>版本Coreseek 3/Sphinx 0.9.9-rc1又引入了字段限位(field position limit)符。它把搜索限制在指定字段(一个或多个)的前N个位置。例如“@body[50] hello”不会匹配那些body字段包含“hello”,但它出现在第51个位置或者更靠后的文档。</p><p>近似距离以词为单位,随词数变化而变化,并应用于引号中的全部词。举个例子,”cat dog mouse”~5
这个查询的意思是必须有一个少于8个词的词串,它要包含全部的三个词,也就是说”CAT aaa bbb ccc DOG eee fff MOUSE”
这个文档不会匹配这个查询,因为这个词串正好是8个词。</p><p>阀值匹配符引入了一种模糊匹配。它允许至少含有某个阈值数量个匹配词的文档通过。上述例子(”the world is a
wonderful place”/3)会匹配含有指定的六个词中的至少三个的那些文档。上面例子中的一个查询”the world is a
wonderful place”/3匹配的文档至少含有指定的6个词中的3个。</p><p>严格有序搜索符(即“在前”搜索符)是在版本0.9.9-rc2中引入的,它的几个参数在被匹配的文档中必须严格按查询中出现的顺序出现。例如,“black << cat”这个查询(不包括引号)可以匹配“black and white cat”,但不能匹配“the cat was black”。顺序运算符的优先级最低,它既可以应用在最简单的关键词上,也可以用在更复杂的表达式上,比如下面也是个正确的查询:</p><pre>(bag <span><span>of</span></span> words) << <span><span>"exact phrase"</span></span> << red|green|blue</pre><p> </p><p>版本0.9.9-rc1引入了“严格形式”关键字修饰符,它保证关键词在匹配文档中严格以指定的形式出现,而默认行为只要求词根相同。例如,查询“runs”既可以匹配含有“runs”的文档,也可以匹配含有“running”的文档,因为这二者的词根都是“run”——而如果查询是“=runs”,那就只有前者能匹配。严格形式修饰符要求index_exact_words选项处于启用状态。这是个影响关键字的修饰符,可以与其他一些运算符混合使用,例如词组搜索符、近似搜索符和阈值搜索符等。</p><p>关键字修饰符“字段开始”和“字段结束”是在版本Coreseek 3.1/Sphinx
0.9.9-rc2中引入的,它们确保只在一个全文字段的最开始或最结束位置匹配关键字。例如,查询“^hello
world$”(包括引号,也就是说这个查询是词组搜索符和字段起止修饰符的组合)匹配的文档必然包括某个严格只有“hello
world”这个词组的字段。</p><p>自版本Coreseek 3/Sphinx 0.9.9-rc1始,可以嵌套任意层数的括号和“非”操作,但这类查询要想能够计算出结果,就必须保证不能隐含地涉及所有文档。</p><pre><span><span>// 正确查询</span></span>
aaa -(bbb -(ccc ddd))

<span><span>// 不能处理的查询</span></span>
-aaa
aaa | -bbb
</pre><p> </p><p>NEAR 广义临近运算符, 版本2.0.1-beta引入, 是近似距离运算符的广义版本。其语法是 NEAR/N, 区分大小写, 并且不允许有空格在 NEAR 关键词与斜线以及距离值之间。</p><p>原始的近似距离运算符仅对给如的关键词集起作用。而NEAR则更加通用,可以接受任意的子表达式作为其参数,当两个表达式在N个词汇的距离中(不论先后顺序)发现对方时文档被选中。NEAR是左结合的,与“在前”搜索符具有相同(最低)的优先级。</p><p>你需要明白为什么一个使用NEAR的查询(one NEAR/7 two NEAR/7 three) 并不完全等同于一个使用关键词近似距离的查询 ("one two three"~7)。 这里的区别在于,近似距离运算符允许最多6个没有匹配的词汇出现在3个匹配到的词汇之间,但是NEAR的版本限制较少: 它允许最多6个词汇出现在 ‘one’ 与 ‘two’ 之间,然后允许匹配到的two关键词与’three’之间有最多6个词汇。</p><p>SENTENCE 句子 和 PARAGRAPH 段落运算符, 在版本2.0.1-beta中引入, 当它的参数都处于同一个句子或者段落中时文档被选中。参数可以是关键词或者短语,活着相同的运算符实例。下面是几个例子:</p><pre><span><span>one</span></span> SENTENCE two
one SENTENCE <span><span>"two three"</span></span>
one SENTENCE <span><span>"two three"</span></span> SENTENCE four
</pre><p>参数在句子或者段落中的顺序不产生影响。该功能仅在index_sp (句子和段落索引功能) 启用时生效,否则作为单纯的AND操作对待。参考index_sp章节的文档了解系统是如何来判断一个句子或者段落的。</p><p>ZONE 区域限制运算符, 版本2.0.1-beta引入, 非常类似于字段限制运算符,但是限制在一个给定的字段内或者区域的列表。请注意,其随后的字表达式并不要求限定在一个给定的连续区域之内,可以跨越多个相同的区域进行匹配。例如, (ZONE:th hello world) 查询 将 匹配下面演示的文档:</p><pre><span><span><</span><span><span><span>th</span></span></span><span>></span></span>Table 1. Local awareness of Hello Kitty brand.<span><span></</span><span><span><span>th</span></span></span><span>></span></span>
.. some table data goes here ..
<span><span><</span><span><span><span>th</span></span></span><span>></span></span>Table 2. World-wide brand awareness.<span><span></</span><span><span><span>th</span></span></span><span>></span></span>
</pre><p>ZONE运算符对查询的影响直到下一个查询字段或者区域限制符号,或者到右括号结束。它仅适用于启用了区域支持(参看 第 11.2.9 节 “index_zones:索引标签区域信息”) 的索引,否则将被忽略掉。</p><h2>5.4. 权值计算</h2><p>采用何种权值计算函数(目前)取决于查询的模式。</p><p>权值计算函数有如下两个主要部分:</p><ol><li>phrase rank,</li><li>statistical rank.</li></ol><p> </p><p>词组评分根据文档和查询的最长公共子串(LCS,longest common subsequence)的长度进行。因此如果文档对查询词组有一个精确匹配(即文档直接包含该词组),那么它的词组评分就取得了可能的最大值,也就是查询中词的个数。</p><p>统计学评分基于经典的BM25函数,该函数仅考虑词频。如果某词在整个数据库中很少见(即文档集上的低频词)或者在某个特定文档中被经常提及(即特定文档上的高频词),那么它就得到一个较高的权重。最终的BM25权值是一个0到1之间的浮点数。</p><p>在所有模式中,数据字段的词组评分是LCS乘以用户指定的数据字段权值。数据字段权值是整数,默认为1,且字段的权值必须不小于1。</p><p>在SPH_MATCH_BOOLEAN模式中,不做任何权重估计,每一个匹配项的权重都是1。</p><p>在SPH_MATCH_ALL和SPH_MATCH_PHRASE模式中,最终的权值是词组评分的加权和。</p><p>在SPH_MATCH_ANY模式中,于前面述两模式的基本思想类似,只是每个数据字段的权重都再加上一个匹配词数目。在那之前,带权的词组相关度被额外乘以一个足够大的数,以便确保任何一个有较大词组评分的数据字段都会使整个匹配的相关度较高,即使该数据字段的权重比较低。</p><p>在SPH_MATCH_EXTENDED模式中,最终的权值是带权的词组评分和BM25权重的和,再乘以1000并四舍五入到整数。</p><p>这个行为将来会被修改,以便使MATCH_ALL和MATCH_ANY这两个模式也能使用BM25算法。这将使词组评分相同的搜索结果片断得到改进,这在只有一个词的查询中尤其有用。</p><p>关键的思想(对于除布尔模式以外的全部模式中)是子词组的匹配越好则评分越高,精确匹配(匹配整个词组)评分最高。作者的经验是,这种基于词组相似性的评分方法可以提供比任何单纯的统计模型(比如其他搜索引擎中广泛使用的BM25)明显更高的搜索质量。</p><h2>5.5. 表达式,函数,运算符</h2><p>Sphinx允许你在SphinxQL和SphinxAPI中使用任意的表达式,可以涉及属性的值,内部属性(文档编号和相关度),算术运算符,内置的函数和用户自定义的函数。本章节是支持的运算符和函数的说明文档。下面是用于快速查看的完整参考列表。</p><ul><li>算术运算符: +, -, *, /, %, DIV, MOD</li><li>比较运算符: <, > <=, >=, =, <></li><li>布尔运算符: AND, OR, NOT</li><li>位运算符: &, |</li><li>ABS()</li><li>BIGINT()</li><li>CEIL()</li><li>COS()</li><li>CRC32()</li><li>DAY()</li><li>EXP()</li><li>FLOOR()</li><li>GEODIST()</li><li>IDIV()</li><li>IF()</li><li>IN()</li><li>INTERVAL()</li><li>LN()</li><li>LOG10()</li><li>LOG2()</li><li>MAX()</li><li>MIN()</li><li>MONTH()</li><li>NOW()</li><li>POW()</li><li>SIN()</li><li>SINT()</li><li>SQRT()</li><li>YEAR()</li><li>YEARMONTH()</li><li>YEARMONTHDAY()</li></ul><p> </p><h3>5.5.1. 运算符</h3><dl><dt>

       算术运算符: +, -, *, /, %, DIV, MOD 
      </dt><dd>
        标准算术运算符。计算可以以三种不同的精度进行:(a) 单精度32位IEEE754浮点值(默认情况),(b) 

32位有符号整数,(c)
64位有符号整数。如果没有任何返回浮点数的操作,表达式分析器会自动切换到整数模式,否则使用默认的浮点模式。比如,对于表达式“

       <code>a+b</code>”,如果两个参数都是32位整数的,则它会被以32位整数模式计算,如果两个参数都是整数,而其中一个是64位的,则以64位整数模式计算,否则以浮点模式计算。然而表达式“ 
       <code>a/b</code>”或者“ 
       <code>sqrt(a)</code>”却总是使用浮点模式计算,因为这些操作返回非整数的结果,要让前者使用整数模式,可以使用 
       <code>IDIV(a,b)</code>或者 
       <code>a DIV b</code>。另外,如果两个参数都是32位的,表达式“ 
       <code>a*b</code>”并不会自动提升到64位模式。要想强制64位模式,可以用BIGINT()。(但要注意的是,如果表达式中同时有浮点数,那么BIGINT()的命运就是简单地被忽略) 
      </dd><dt> 
       比较运算符: &lt;, &gt; &lt;=, &gt;=, =, &lt;&gt; 
      </dt><dd>
        比较操作符(比如=和&lt;=)在条件为真时返回1.0,否则返回0.0。例如 
       <code>(a=b)+3</code>在属性“a”与属性“b”相等时返回4,否则返回3。与MySQL不同,相等性比较符(即=和&lt;&gt;)中引入了一个小的阈值(默认是1e-6)。如果被比较的两个值的差异在阈值之内,则二者被认为相等。 
      </dd><dt> 
       布尔运算符: AND, OR, NOT 
      </dt><dd>
        布尔操作符(AND,OR,NOT)是在版本Coreseek 3.1/Sphinx 

0.9.9-rc2中引入的,其行为与一般的布尔操作没有两样。它们全部是左结合,而且比之其他操作符,它们有最低的优先级,其中NOT的优先级比AND
和OR高,但仍旧低于所有其他操作符。AND和OR有相同的优先级,因此建议使用括号来避免在复杂的表达式中出现混乱。

      </dd><dt> 
       位运算符: &amp;, | 
      </dt><dd>
        这些运算符分别进行按位AND和OR。操作数 必须是整数类型。版本1.10-beta引入。 
      </dd></dl><h3>5.5.2.&nbsp;数值函数</h3><dl><dt> 
       ABS( x ) 
      </dt><dd>
        返回 x 的绝对值。 
      </dd><dt> 
       CEIL( x ) 
      </dt><dd>
        返回大于或等于该 x 的最小整数。 
      </dd><dt> 
       COS( x ) 
      </dt><dd>
        返回 x 的余弦。 
      </dd><dt> 
       EXP( x ) 
      </dt><dd>
        返回e的X乘方后的值(e=2.718…作为自然对数的底)。 
      </dd><dt> 
       FLOOR( x ) 
      </dt><dd>
        返回小于或等于该 x 的最大整数。 
      </dd><dt> 
       IDIV( x, y ) 
      </dt><dd>
        返回 x 整除 y 的结果。两个参数都必须是整数类型。 
      </dd><dt> 
       LN( x ) 
      </dt><dd>
        返回 x 的自然对数 (自然对数的底为e=2.718…). 
      </dd><dt> 
       LOG10( x ) 
      </dt><dd>
        返回 x 的常用对数 (底为10). 
      </dd><dt> 
       LOG2( x ) 
      </dt><dd>
        返回 x 的二进制对数 (底为2). 
      </dd><dt> 
       MAX( x, y ) 
      </dt><dd>
        返回 x, y 中较大的参数. 
      </dd><dt> 
       MIN( x, y ) 
      </dt><dd>
        返回 x, y 中较小的参数. 
      </dd><dt> 
       POW( x, y ) 
      </dt><dd>
        返回 x 的 y 次方的冥。 
      </dd><dt> 
       SIN( x ) 
      </dt><dd>
        返回 x 的正弦. 
      </dd><dt> 
       SQRT( x ) 
      </dt><dd>
        返回 x 的平方根. 
      </dd></dl><h3>5.5.3.&nbsp;日期和时间函数</h3><dl><dt> 
       DAY( t ) 
      </dt><dd>
        根据当前时区,返回时间戳 t 对应的所在月日期(范围在1.. 31 )。版本2.0.1-beta引入。 
      </dd><dt> 
       MONTH( t ) 
      </dt><dd>
        根据当前时区,返回时间戳 t 对应的月份(范围在1.. 12 )。版本2.0.1-beta引入。 
      </dd><dt> 
       NOW() 
      </dt><dd>
        将当前时间戳作为整数返回。版本0.9.9-rc1引入。 
      </dd><dt> 
       YEAR( t ) 
      </dt><dd>
        根据当前时区,返回时间戳 t 对应的年份(范围在1969.. 2038 )。版本2.0.1-beta引入。 
      </dd><dt> 
       YEARMONTH( t ) 
      </dt><dd>
        根据当前时区,返回时间戳 t 对应的整数年份和月份(范围在196912..203801 )。版本2.0.1-beta引入。 
      </dd><dt> 
       YEARMONTHDAY() 
      </dt><dd>
        根据当前时区,返回时间戳 t 对应的整数年份、月份和日期(范围在19691231..20380119 )。版本2.0.1-beta引入。 
      </dd></dl><h3>5.5.4.&nbsp;类型转换函数</h3><dl><dt> 
       BIGINT() 
      </dt><dd>
        它将它的整型参数强行提升到64位,而对浮点参数无效。引入它是为了可以强制某些表达式(如“ 
       <code>a*b</code>”)用64位模式计算,即使所有的参数都是32位的。 版本0.9.9-rc1引入。 
      </dd><dt> 
       SINT() 
      </dt><dd>
        

强制将32位无符号整数重新诠释为有符号数,并提示道64位(因为32位类型是无符号的)。通过以下的例子很容易明白:通常1-2的计算结果(32位无符号整数)为4294967295,但是SINT(1-2)的计算结果为-1。
版本2.0.1-beta引入。

      </dd></dl><h3>5.5.5.&nbsp;比较函数</h3><dl><dt> 
       IF( expr, x, y ) 
      </dt><dd> 
       <code>IF()</code>&nbsp;行为与其对应的MySQL的有所不同。它接受3个参数,检查第一个参数 expr 是否为0.0,若非零则返回第二个参数 x ,为零时则返回第三个参数 y 。注意,与比较操作符不同, 
       <code>IF()</code>并 
       <strong>不</strong>使用阈值!因此在第一个参数中使用比较结果是安全的,但使用算术运算符则可能产生意料之外的结果。比如,下面两个调用会产生 
       <em>不同</em>的结果,虽然在逻辑上他们是等价的: 
       <pre><code>IF ( <span><span>sqrt</span></span>(<span><span>3</span></span>)*sqrt(3)-3&lt;&gt;0, a, b )

IF ( sqrt(3)*sqrt(<span><span>3</span></span>)<span><span>-3</span></span>, a, b )</pre>

       <p>在第一种情况下,由于有阈值,比较操作符&lt;&gt;返回0.0(逻辑假),于是<code>IF()</code>总是返回‘b’。在第二种情况下,<code>IF()</code>函数亲自擅自在<em>没有</em>阈值的情况下将同样的&nbsp;<code>sqrt(3)*sqrt(3)-3</code>与零值做比较。但由于浮点数运算的精度问题,该表达式的结果与0值会有微小的差异,因此该值与零值的相等比较不会通过,上述第二种情况中<code>IF()</code>会返回‘a’做为结果。</p> 
      </dd><dt> 
       IN( expr, val1, … ) 
      </dt><dd>
        版本0.9.9-rc1引入了函数IN(expr, val1, val2, 

…),它需要两个或更多参数,如果第一个参数与后续任何一个参数(val1到valN)相等则返回1,否则返回0。目前,所有被测试是否相等的参数(不包
括expr本身)必须是常量。(支持任意表达式在技术上是可以实现的,未来我们会这么做)。这些常量经过预先排序,测试相等时可以使用二元查找以提高效

率,因此即使参数列表很长IN()也还可以提供较高的速度。自版本0.9.9-rc2始,第一个参数可以是一个MVA多值属性,这种情况下只要MVA中的
任何一个值与后面列表中的任何一个值相等IN()就返回1。 从版本2.0.1-beta开始,IN()也支持

       <code>IN(expr,@uservar)</code>语法以检查其值是否在给定的全局用户变量列表中。 
      </dd><dt> 
       INTERVAL( expr, point1, …) 
      </dt><dd>
        版本0.9.9-rc1引入了函数INTERVAL(expr, point1, point2, point3, 

…),它接受2个或更多参数,返回第一个小于第一个参数expr的参数的下标:如果expr<point1,返回0;如果
point1<=expr<point2,返回1,一次类推。显然,必须有point1<point2<…<pointN
才能保证这个函数正确工作。

      </dd></dl><h3>5.5.6.&nbsp;其它函数</h3><dl><dt> 
       CRC32( s ) 
      </dt><dd>
        返回字符串 s 的CRC32值. 版本2.0.1-beta引入。 
      </dd><dt> 
       GEODIST( lat1, long1, lat2, long2 ) 
      </dt><dd>
        版本0.9.9-rc2引入函数GEODIST(lat1, long1, lat2, 

long2),它根据坐标计算两个指定点之间的地表距离。请注意经纬度都要以角度为单位,而结果是以米为单位的。四个参数都可以是任意表达式。当其中一对
参数引用的是文档属性对而另一对参数是常数,系统会自动选择一条优化的路径。

      </dd></dl><h2>5.6.&nbsp;排序模式</h2><p>可使用如下模式对搜索结果排序:</p><ul><li>SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)</li><li>SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)</li><li>SPH_SORT_ATTR_ASC 模式, 按属性升序排列(属性值越小的越是排在前面)</li><li>SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按相关度降序</li><li>SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排列。</li><li>SPH_SORT_EXPR 模式,按某个算术表达式排序。</li></ul><p>&nbsp;</p><p>SPH_SORT_RELEVANCE忽略任何附加的参数,永远按相关度评分排序。所有其余的模式都要求额外的排序子句,子句的语法跟具体的模式有

关。SPH_SORT_ATTR_ASC,
SPH_SORT_ATTR_DESC以及SPH_SORT_TIME_SEGMENTS这三个模式仅要求一个属性名。
SPH_SORT_RELEVANCE模式等价于在扩展模式中按”@weight DESC, @id
ASC”排序,SPH_SORT_ATTR_ASC 模式等价于”attribute ASC, @weight DESC, @id
ASC”,而SPH_SORT_ATTR_DESC 等价于”attribute DESC, @weight DESC, @id ASC”。</p><h3>SPH_SORT_TIME_SEGMENTS 模式</h3><p>在SPH_SORT_TIME_SEGMENTS模式中,属性值被分割成“时间段”,然后先按时间段排序,再按相关度排序。</p><p>时间段是根据搜索发生时的当前时间戳计算的,因此结果随时间而变化。所说的时间段有如下这些值:</p><ul><li>最近一小时</li><li>最近一天</li><li>最近一周</li><li>最近一月</li><li>最近三月</li><li>其他.</li></ul><p>时间段的分法固化在搜索程序中了,但如果需要,也可以比较容易地改变(需要修改源码)。</p><p>这种模式是为了方便对Blog日志和新闻提要等的搜索而增加的。使用这个模式时,处于更近时间段的记录会排在前面,但是在同一时间段中的记录又根据相关度排序-这不同于单纯按时间戳排序而不考虑相关度。</p><h3>SPH_SORT_EXTENDED mode</h3><p>在 SPH_SORT_EXTENDED 模式中,您可以指定一个类似SQL的排序表达式,但涉及的属性(包括内部属性)不能超过5个,例如:</p><pre><span><span>@relevance</span></span> DESC, price ASC, <span><span>@id</span></span> DESC</pre><p> </p><p>只要做了相关设置,不管是内部属性(引擎动态计算出来的那些属性)还是用户定义的属性就都可以使用。内部属性的名字必须用特殊符号@开头,用户属性按原样使用就行了。在上面的例子里,@relevance和@id是内部属性,而price是用户定义属性。</p><p>可用的内置属性:</p><ul><li>@id (匹配文档的 ID)</li><li>@weight (匹配权值)</li><li>@rank (等同 weight)</li><li>@relevance (等同 weight)</li><li>@random (随机顺序返回结果)</li></ul><p>@rank 和 @relevance 只是 @weight 的别名.</p><h3>SPH_SORT_EXPR 模式</h3><p>表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内部属性(@id和@weight),算术运算符和一些内建的函数。例如:</p><pre>$cl->SetSortMode ( SPH_SORT_EXPR,
<span><span>"@weight + ( user_karma + ln(pageviews) )*0.1"</span></span> );
</pre><p>在表达式中支持的运算符和函数请参看专门的章节第 5.5 节 “表达式,函数,运算符”.</p><h2>5.7. 结果分组(聚类)</h2><p>有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如画个漂亮的图来展示每个月有多少的blog日志,或者把Web搜索结果按站点分组,或者把找到的论坛帖子按其作者分组等等。</p><p>理论上,这可以分两步实现:首先在Sphinx中做全文检索,再在SQL服务器端对得到的ID分组。但是现实中在大结果集(10K到10M个匹配)上这样做通常会严重影响性能。</p><p>为避免上述问题,Sphinx提供了一种“分组模式”,可以用API调用SetGroupBy()来开启。在分组时,根据group-by值给匹配项赋以一个分组。这个值用下列内建函数之一根据特定的属性值计算:</p><ul><li>SPH_GROUPBY_DAY, 从时间戳中按YYYYMMDD格式抽取年、月、日;</li><li>SPH_GROUPBY_WEEK, 从时间戳中按YYYYNNN格式抽取年份和指定周数(自年初计起)的第一天;</li><li>SPH_GROUPBY_MONTH, 从时间戳中按YYYYMM格式抽取月份;</li><li>SPH_GROUPBY_YEAR, 从时间戳中按YYYY格式抽取年份;</li><li>SPH_GROUPBY_ATTR, 使用属性值自身进行分组.</li></ul><p> </p><p>最终的搜索结果中每组包含一个最佳匹配。分组函数值和每组的匹配数目分别以“虚拟”属性 @group  和 @count  的形式返回.</p><p>结果集按group-by排序子句排序,语法与SPH_SORT_EXTENDED 排序子句的语法相似。除了@id和@weight,分组排序子句还包括:</p><ul><li>@group (groupby函数值),</li><li>@count (组中的匹配数目).</li></ul><p> </p><p>默认模式是根据groupby函数值降序排列,即按照 "@group desc".</p><p>排序完成时,结果参数total_found会包含在整个索引上匹配的组的总数目。</p><p>注意: 分组操作在固定的内存中执行,因此它给出的是近似结果;所以total_found报告的数目可能比实际给出的个分组数目的和多。@count 也可能被低估。要降低不准确性,应提高max_matches。如果max_matches允许存储找到的全部分组,那结果就是百分之百准确的。</p><p>例如,如果按相关度排序,同时用SPH_GROUPBY_DAY函数按属性"published"分组,那么:</p><ul><li>结果中包含每天的匹配结果中最相关的那一个,如果那天有记录匹配的话,</li><li>结果中还附加给出天的编号和每天的匹配数目,</li><li>结果以天的编号降序排列(即最近的日子在前面).</li></ul><p> </p><p>从版本0.9.9-rc2开始, 当使用GROUP BY时,可以通过SetSelect() API调用聚合函数 (AVG(), MIN(), MAX(), SUM())</p><h2>5.8. 分布式搜索</h2><p>为提高可伸缩性,Sphnix提供了分布式检索能力。分布式检索可以改善查询延迟问题(即缩短查询时间)和提高多服务器、多CPU或多核环境下的吞吐率(即每秒可以完成的查询数)。这对于大量数据(即十亿级的记录数和TB级的文本量)上的搜索应用来说是很关键的。</p><p>其关键思想是对数据进行水平分区(HP,Horizontally partition),然后并行处理。</p><p>分区不能自动完成,您需要</p><ul><li>在不同服务器上设置Sphinx程序集(indexer和searchd)的多个实例;</li><li>让这些实例对数据的不同部分做索引(并检索);</li><li>在searchd的一些实例上配置一个特殊的分布式索引;</li><li>然后对这个索引进行查询.</li></ul><p>这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作,相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。</p><p>当searchd收到一个对分布式索引的查询时,它做如下操作</p><ol><li>连接到远程代理;</li><li>执行查询;</li><li>(在远程代理执行搜索的同时)对本地索引进行查询;</li><li>接收来自远程代理的搜索结果;</li><li>将所有结果合并,删除重复项;</li><li>将合并后的结果返回给客户端.</li></ol><p> </p><p>在应用程序看来,普通索引和分布式索引完全没有区别。
也就是说,分布式索引对应用程序而言是完全透明的,实际上也无需知道查询使用的索引是分布式的还是本地的。 (就算是在0.9.9之中,
Sphinx也不支持以其他的方式来结合分布式索引进行搜索, 也许在将来会去掉该限制.)</p><p>任一个searchd实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地搜索)。这有如下几点好处:</p><ol><li>集群中的每台机器都可以做为主控端来搜索整个集群,搜索请求可以在主控端之间获得负载平衡,相当于实现了一种HA(high availability,高可用性),可以应对某个节点失效的情况。</li><li>如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例就可以利用到全部的CPU或者核。</li></ol><p> </p><p>如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例就可以利用到全部的CPU或者核。</p><h2>5.9. 搜索服务(searchd) 查询日志格式</h2><p>在版本2.0.1-beta中支持下述的两种查询日志格式。以前的版本只支持自定义的纯文本格式,目前也仍然是默认的日志格式。 然而,虽然它可能会方便人工监测和审查,但难以回放以便做性能测试,它只能 记录搜索查询而不能记录搜索请求的其他信息,也不总是包含完整的搜索查询数据等。 默认纯文本格式也很难(有时不可能)为性能测试的目的而回放。新的 sphinxql 格式则缓解了这个问题,其目的是完整和自动化的记录信息,即使降低了简洁和可读性也无所谓。</p><h3>5.9.1. 纯文本日志格式</h3><p>默认情况下,searchd 将全部成功执行的搜索查询都记录在查询日志文件中。以下是一个类似记录文件的例子:</p><pre><span><span>[Fri Jun 29 21:17:58 2007]</span></span> 0<span><span>.004</span></span> <span><span>sec</span></span> <span><span>[all/0/rel 35254 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>test</span></span>
<span><span>[Fri Jun 29 21:20:34 2007]</span></span> 0<span><span>.024</span></span> <span><span>sec</span></span> <span><span>[all/0/rel 19886 (0,20) @channel_id]</span></span> <span><span>[lj]</span></span> <span><span>test</span></span>
</pre><p>日志格式如下</p><pre>[query-date] query-<span><span>time</span></span> [match-mode/filters-count/<span><span>sort</span></span>-mode
total-matches (offset,limit) @groupby-attr] [<span><span>index</span></span>-name] query
</pre><p>匹配模式(match-mode)可以是如下值之一</p><ul><li>“all” 代表 SPH_MATCH_ALL 模式;</li><li>“any” 代表 SPH_MATCH_ANY 模式;</li><li>“phr” 代表 SPH_MATCH_PHRASE 模式;</li><li>“bool” 代表 SPH_MATCH_BOOLEAN 模式;</li><li>“ext” 代表 SPH_MATCH_EXTENDED 模式;</li><li>“ext2″ 代表 SPH_MATCH_EXTENDED2 模式;</li><li>“scan” 代表使用了完整扫描模式,这可能是由于设置了SPH_MATCH_FULLSCAN模式导致的,也可能是因为查询是空的。 (参见文档 匹配模式)</li></ul><p>排序模式(sort-mode)可以取如下值之一:</p><ul><li>“rel” 代表 SPH_SORT_RELEVANCE 模式;</li><li>“attr-” 代表 SPH_SORT_ATTR_DESC 模式;</li><li>“attr+” 代表 SPH_SORT_ATTR_ASC 模式;</li><li>“tsegs” 代表 SPH_SORT_TIME_SEGMENTS 模式;</li><li>“ext” 代表 SPH_SORT_EXTENDED 模式.</li></ul><p> </p><p>此外,如果searchd 启动的时候带参数 --iostats,那么在列出被搜索的全部索引后还会给出一块数据。</p><p>一个查询日志项看起来就像这样:</p><pre><span><span>[Fri Jun 29 21:17:58 2007]</span></span> 0<span><span>.004</span></span> <span><span>sec</span></span> <span><span>[all/0/rel 35254 (0,20)]</span></span> <span><span>[lj]</span></span>
<span><span>[ios=6 kb=111.1 ms=0.5]</span></span> <span><span>test</span></span>
</pre><p>多出来的这块数据是关于搜索中执行的I/O操作的信息,包括执行的I/O操作次数、从索引文件中读取数据的kb数和I/O操作占用的时间(尽管这个时间还包括一个后台处理组件所占用的,但主要是I/O时间)</p><h3>5.9.2. SphinxQL 日志格式</h3><p>这是版本2.0.1-beta引入的新的日志格式,其目标是开始以一种简单的格式去自动记录所有的一切(例如为了自动回放)。 新的格式可以通过配置文件中的query_log_format指令来启用, 或者在访问过程中通过SphinxQL语句SET GLOBAL query_log_format=... 进行来回切换。在新的格式中,前面的例子将如下所示:(为了方便阅读进行了换行,但是在实际的日志中每行一个查询)</p><pre><span><span>/ Fri Jun 29 21:17:58.609 2007 2011 conn 2 wall 0.004 found 35254 /</span></span>
<span><span>SELECT</span></span> * <span><span>FROM</span></span> lj <span><span>WHERE</span></span> <span><span>MATCH</span></span>(<span><span>'test'</span></span>) <span><span>OPTION</span></span> ranker=proximity;

<span><span>/ Fri Jun 29 21:20:34 2007.555 conn 3 wall 0.024 found 19886 /</span></span>
<span><span>SELECT</span></span> * <span><span>FROM</span></span> lj <span><span>WHERE</span></span> <span><span>MATCH</span></span>(<span><span>'test'</span></span>) <span><span>GROUP</span></span> <span><span>BY</span></span> channel_id
<span><span>OPTION</span></span> ranker=proximity;
</pre><p>请注意, 所有的请求都将以此格式记录, 包括那些通过SphinxAPI和SphinxSE发送的请求,而不只是那些通过SphinxQL 发送的请求。 还需要注意的是,这种日志记录方式仅适合纯文本日志格式,如果使用’syslog’记录则不会工作。</p><p>SphinxQL日志格式相对默认的纯文本日志格式的特点如下:</p><ul><li>所有类型的请求都会被记录。 (该工作还在继续和完善.)</li><li>全部报表数据将被尽可能的记录。</li><li>错误和提醒也会被记录。</li><li>该日志可以通过SphinxQL自动回放。</li><li>额外的性能计数器(目前,记录了每个Agent的分布式查询时间)被记录。</li></ul><p> </p><p>每个请求(包括SphinxAPI和SphinxQL )都正好对应一个日志记录行。 所有的请求类型,包括INSERT,
CALL SNIPPETS等,都会被记录(但 编写本手册时,这方面的工作还在继续和完善)。
每个记录行都是有效的SphinxQL语句,可以用于完整的重构请求,但是请求记录如果太大则需要考虑性能原因而缩短。
其他信息,例如性能计数器等会被作为注释记录在请求后。</p><h2>5.10. MySQL 协议支持与 SphinxQL</h2><p>Sphinx的searchd守护程序从 版本0.9.9-rc2开始支持MySQL二进制网络协议,并且能够通过标准的MySQL API访问。例如,“mysql”命令行程序可以很好地工作。以下是用MySQL客户端对Sphinx进行查询的例子:</p><pre>$ mysql -P 9306
Welcome to the MySQL monitor. Commands <span><span>end</span></span> <span><span>with</span></span> ; or \g.
Your MySQL connection id is 1
Server version: 0.9.9-dev (r1734)

Type '<span><span>help</span></span>;' or '\h' for help. <span><span>Type</span></span> <span><span>'\c'</span></span> <span><span>to</span></span> <span><span>clear</span></span> the buffer.

mysql> <span><span>SELECT</span></span> * <span><span>FROM</span></span> test1 <span><span>WHERE</span></span> <span><span>MATCH</span></span>(<span><span>'test'</span></span>)
-> <span><span>ORDER</span></span> <span><span>BY</span></span> <span><span>group_id</span></span> <span><span>ASC</span></span> <span><span>OPTION</span></span> ranker=bm25;
+<span><span>------+--------+----------+------------+</span></span>
| id | weight | group_id | date_added |
+<span><span>------+--------+----------+------------+</span></span>
| 4 | 1442 | 2 | 1231721236 |
| 2 | 2421 | 123 | 1231721236 |
| 1 | 2421 | 456 | 1231721236 |
+<span><span>------+--------+----------+------------+</span></span>
3 rows in <span><span>set</span></span> (<span><span>0.00</span></span> sec)
</pre><p> </p><p>请注意mysqld甚至根本没有在测试机上运行。所有事情都是searchd自己搞定的。</p><p>新的访问方法是对原生API的一种补充,原生API仍然完美可用。事实上,两种访问方法可以同时使用。另外,原生API仍旧是默认的访问方法。MySQL协议支持需要经过额外的配置才能启用。当然这只需要更动一行配置文件,加入一个协议为mysql41的监听器(listener)就可以了:</p><pre><span><span>listen</span></span> = localhost:<span><span>9306</span></span>:mysql41</pre><p> </p><p>如果仅仅支持这个协议但不支持SQL语法,那没什么实际意义。因此Sphinx现在还支持SQL的一个很小的子集,我们给这个子集起个绰号,叫

SphinxQL。它支持在所有类型的索引上进行标准SELECT查询,支持在RT索引上使用INSERT、REPLACE、DELETE来更改信息,以
及更多的处理。 详细的SphinQL指南请查看 第 7 章 SphinxQL 指南.</p><h2>5.11. 批量查询</h2><p>多查询,或者批量查询,用于一次发送多条查询到Sphinx(更专业的说法是再一次网络请求中)。</p><p>目前有两个方法来实现批量查询,他们是 AddQuery() 和 RunQueries()。 你也可以通过SphinxQL来执行批量查询,参见 第 7.18 节 “多结果集查询(批量查询)”. (事实上,常规的 Query() 调
用在内部实现上是一次单独的AddQuery()调用紧跟RunQueries()调用。)
AddQuery()会保持前面的API调用对查询设置的当前状态,并且记住这些查询。RunQueries()实际上发送所有记住的查询,并依次返回多
个结果集。 对于查询本身没有任何限制,但在一次批量查询中会进行查询数目的完成检查 (参见 第 11.4.25 节 “max_batch_queries:最大批量查询”).</p><p>为什么要使用批量查询呢? 通常是是为了提升性能。 首先,在一次批量查询中将多个请求一次发送到searchd 而不是由一个接一个的发送,或多或少会减少网络通信。 其次,更重要的是,在批量查询中发送多条查询时,searchd会执行某些内部优化。随着时间的推移逐渐增加了新的优化措施,在可能的情况下将所有的查询打包为批量查询是有意义的,因此简单地升级Sphinx到一个新的版本将自动启用新的优化措施。 在处理时如果没有任何可能的批量查询优化可应用,查询在内部将被一个接一个的处理。</p><p>为什么(或者说什么时候)不使用批量查询呢? 批量查询要求一次处理中的查询都是相互独立的,但是有时候并非如此。
也就是说,有时候查询B是基于查询A的结果的,只能在查询A运行完成以后才能生成新的查询。例如,你可能需要在主索引查不到任何结果的时候,再从第二个索

引查询显示结果。或者,有时候需要根据第一次查询的结果数去指定第二次查询的结果偏移量。诸如此类情况下,你不得不使用多次分开的查询(或者多次分开的批
量查询)。</p><p>截止版本0.9.10,有两个主要的优化措施需要注意: 公共查询优化(从版本0.9.8开始提供);公共子树优化(从版本0.9.10开始提供)。</p><p>公共查询优化 是指 searchd发现批量查询中的查询仅排序和分组设置不同时,将只执行一次搜索。
例如,如果一次批量查询包含三个查询,查询关键字全部都是“ipod
nano”,但是第一个查询取按照价格排序前十的结果,第二个查询按照供应商分组并取评分最高的前五个供货商,而第三个查询取最高价格的,则针
对”ipod nano”的全文查询仅执行一次,但其结果会重复使用来建立三个不同的结果集。</p><p>从这个优化措施得到好处的一个典型的案例就是所谓的faceted分面搜索。事实上,分面搜索可以通过执行一定数量的查询,一来获取搜索结果本身,同时进行相同全文关键字的一些其他查询,如根据不同的分组设置所有必要的分组结果(前三作者,前五供货商等等)。而这些只需要保持全文检索和过滤设置相同,公共查询优化将会触发并大幅提高查询性能。</p><p>公共子树优化 更加有趣。 它能让 searchd 分析利用批量全文查询中的相似之处。它可以识别所有查询中的公共全文查询部分(子树),并且在查询中缓存其结果。例如,我们可以看下面的批量查询:</p><pre><span><span>barack</span></span> obama president
barack obama john mccain
barack obama speech
</pre><p>他们有一个共同的部分是两个单词(“barack obama”),这将被计算一次,然后缓存并在查询之间共享。这个工作就是公共子树优化来做的。每个查询的缓存大小由subtree_docs_cache 和subtree_hits_cache指令严格控制(使得即使缓存匹配了“i am”的超多文档也不会耗尽内存和导致服务服务器挂掉)</p><p>下面演示的代码(使用PHP )展示了在同一查询中使用3种不同 排序方式:</p><pre><span><span>require</span></span> ( <span><span>"sphinxapi.php"</span></span> );
$cl = <span><span>new</span></span> SphinxClient ();
$cl->SetMatchMode ( SPH_MATCH_EXTENDED2 );

$cl->SetSortMode ( SPH_SORT_RELEVANCE );
$cl->AddQuery ( <span><span>"the"</span></span>, <span><span>"lj"</span></span> );
$cl->SetSortMode ( SPH_SORT_EXTENDED, <span><span>"published desc"</span></span> );
$cl->AddQuery ( <span><span>"the"</span></span>, <span><span>"lj"</span></span> );
$cl->SetSortMode ( SPH_SORT_EXTENDED, <span><span>"published asc"</span></span> );
$cl->AddQuery ( <span><span>"the"</span></span>, <span><span>"lj"</span></span> );
$res = $cl->RunQueries();
</pre><p> </p><p>如何确认批量查询的请求真的被优化了呢? 如果优化过,在他们各自的查询日志将有一个“倍数“区段 特别之处有多少个查询是一起处理的:</p><pre><span><span>[Sun Jul 12 15:18:17.000 2009]</span></span> 0<span><span>.040</span></span> <span><span>sec</span></span> <span><span>x3</span></span> <span><span>[ext2/0/rel 747541 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>the</span></span>
<span><span>[Sun Jul 12 15:18:17.000 2009]</span></span> 0<span><span>.040</span></span> <span><span>sec</span></span> <span><span>x3</span></span> <span><span>[ext2/0/ext 747541 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>the</span></span>
<span><span>[Sun Jul 12 15:18:17.000 2009]</span></span> 0<span><span>.040</span></span> <span><span>sec</span></span> <span><span>x3</span></span> <span><span>[ext2/0/ext 747541 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>the</span></span>
</pre><p>请注意 “x3″ 区段. 这意味着该查询是优化的并且在同一批次中处理了3个查询。作为参考,没有进行批量查询处理的多次查询的通常日志会是下面这样:</p><pre><span><span>[Sun Jul 12 15:18:17.062 2009]</span></span> 0<span><span>.059</span></span> <span><span>sec</span></span> <span><span>[ext2/0/rel 747541 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>the</span></span>
<span><span>[Sun Jul 12 15:18:17.156 2009]</span></span> 0<span><span>.091</span></span> <span><span>sec</span></span> <span><span>[ext2/0/ext 747541 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>the</span></span>
<span><span>[Sun Jul 12 15:18:17.250 2009]</span></span> 0<span><span>.092</span></span> <span><span>sec</span></span> <span><span>[ext2/0/ext 747541 (0,20)]</span></span> <span><span>[lj]</span></span> <span><span>the</span></span>
</pre><p>请注意每个查询多时间查询案件是由一个因素改善 的1.5倍至2.3倍,这取决于在特定的排序模式。 其实在这两方面,
常见的查询优化和共同子树,还有的报告和3倍 甚至更多的改进,而且从生产情况的,而不仅仅是 综合测试。
值得提醒的是批量查询方式中每个查询的时间会改善1.5倍到2.3倍,具体如何取决于特定的排序模式。其实,不仅在综合测试中,公共查询优化和公共子树优
化都会提升3倍或者更多的改善,在实际生产运营环境中也是如此。</p><h2>5.12. 字符串排序规则</h2><p>Sphinx从版本2.0.1-beta开始支持字符串排序,而排序规则势必会影响字符串属性的比较。Sphinx在进行字符串属性的ORDER BY或者GROUP BY操作时所进行的字符串比较,与字符集的编码设定和策略有关。</p><p>在索引时,字符串属性仅仅是存储起来,没有字符集 或语言信息附加给他们。 这没关系,Sphinx 只需要存储并逐字返回字符串给调用的应用程序。 但是如果你让Sphinx进行字符串值排序,这个请求就会产生歧义。</p><p>首先,单字节(ASCII码或ISO – 8859 – 1或Windows – 1251 )字符串 处理不同于UTF – 8编码的字符串(可能 每一个字符包含可变数目的字节)。 因此,我们需要知道字符集的类型,以便能够正确地解析每个原始字节为有意义的字符。</p><p>第二,我们还需要知道特定语言的 字符串排序规则。 例如,当排序根据美国规则并 在en_US区域时,重音字符’
ï’(带分音符的小写字母i ) 在一些地方应该放在’Z ‘的寿面。 然而,根据法国规则排序
并在fr_FR区域的语言环境中时,它应该放在’i'和’J'之间。 而一些 其他语言规则可以选择忽略所有的口音,使’ ï’ 和’i'可以任意混合。</p><p>第三位,但并非最不重要的,我们也许需要区分在某些场景下大小写相关的排序,而在其他一些情况下大小写无关的排序。</p><p>排序规则结合以上所述:字符集, 语言规则, ,大小写区分。Sphinx目前提供以下四种 排序规则。</p><ol><li>libc_ci</li><li>libc_cs</li><li>utf8_general_ci</li><li>binary</li></ol><p> </p><p>前两个排序规则依赖于几个标准C库(libc)的调用, 因此,可以支持任何在您的系统中安装的语言环境。他们分别提供对大小写无关和大小写敏感的排序规则支持。 默认情况下,会使用C语言环境,按位进行逐字节对比。你可以通过使用collation_libc_locale指令来制定一个在当前系统中可用的其他语言环境设置来改变它。还可以通过locale命令来获得当前系统上可用的语言环境列表:</p><pre>$ locale <span><span>-a</span></span>
C
en_AG
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_NG
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZW.utf8
es_ES
fr_FR
POSIX
ru_RU.utf8
ru_UA.utf8
</pre><p> </p><p>不同系统上的语言环境列表可能有所不同。请参考操作系统的文档,以安装更多所需的语言环境。</p><p>utf8_general_ci 与 binary 语言环境是Sphinx内建支持的。第一个是UTF-8数据的通用字符串校对类型(没有针对任何语言进行定制)。它与MySQL的 utf8_general_ci 排序规则类似。第二个是简单的字节对比。</p><p>字符集校对可以在每次会话过程中通过SphinxQL的 SET collation_connection语句来覆盖全局设置。所有后续的SphinxQL查询都将使用该字符集校对。SphinxAPI和SphinxSE查询都将使用由collation_server配置指令专门指定的服务器默认字符集校对。当前,Sphinx的默认字符集校对为 libc_ci。</p><p>排序规则会影响所有的字符串属性比较操作,包括在ORDER BY 和 GROUp By中的使用,根据所选择的排序规则将返回不同的排序或者分组结果。</p><h2>5.13. 用户自定义函数 (UDF)</h2><p>从版本2.0.1-beta开始,Sphinx支持用户自定义函数,或者简称为UDF。 他们可以被searchd动态的加载或者卸载,而不用重启驻守进程, 并可以在搜索时用在表达式中。UDF的功能如下所述:</p><ul><li>函数可以接受整数 (32-bit 与 64-bit), 浮点数, 字符串, 或者MVA参数.</li><li>函数可以返回整数或者浮点数值.</li><li>函数可以检查参数数量、类型和名称,以及引发错误.</li><li>目前仅支持简单的函数(即非聚合的).</li></ul><p> </p><p>用户自定义函数需要你的系统支持动态库调用(也就是共享对象)。 大部分现代操作系统都支持,包括Linux、Windows、MacOS、Solaris、BSD以及其他的。 (内部测试是在Linux和Windows上进行的。)UDF库需要放置在有plugin_dir 指令专门指定的目录中,并且服务需要配置为workers = threads模式。库文件不能使用相对路径。 一旦库文件成功编译构建并拷贝到正确的位置,就可以使用CREATE FUNCTION and DROP FUNCTION语句来分别动态的安装或者反安装这些函数。 单个库可以包含多个函数。每个库会在第一次安装其中的某个函数时加载,并在反安装库中的所有函数后被卸载。</p><p>库函数将实现可被SQL语句调用的UDF,他们需要遵循C调用规则,以及简单的命名约定。 Sphinx源代码发行包中包含了一个简单的示例文件, src/udfexample.c, 其中定义了一些简单的函数来演示如何使用证书、字符串以及MVA参数;你可以使用其中的某一个为样板来创建你的新函数。 它包含了UDF接口的头文件 src/sphinxudf.h, 其中定义了所需的类型和结构。sphinxudf.h头是独立的,也就是说不需要Sphinx源代码的任何其他部分就可以编译。</p><p>你想要用在SELECT语句中的任何一个函数,都需要至少两个相应的C/C++函数:初始化调用和函数本身的调用。
你也可以根据需要定义反初始化调用以便函数需要在查询后进行清理。 SQL中的函数名是大小写无辜啊的,但是C函数不是,他们需要全部为小写。
函数名称错误将会阻止UDF调入。 你还需要特别注意编译时的调用约定,包括参数顺序和类型,以及主调用函数的返回类型。
任何疏忽都可能导致服务崩溃,最好的情况也许是返回了不可预期的结果。 最后但并非最不重要的,所有的函数都必须是线程安全的。</p><p>假设因为因为测试的原因,你在SphinxQL中的UDF起名为MYFUNC。初始化、主调用与卸载函数需要按照以下方式命名并使用对应的参数:</p><pre><span><span>/// 初始化</span></span>
<span><span>/// 查询初始化时调用called once during query initialization</span></span>
<span><span>/// returns 0 on success</span></span>
<span><span>/// returns non-zero and fills error_message buffer on failure</span></span>
<span><span><span><span>int</span></span></span><span> </span><span><span><span>myfunc_init</span></span></span><span> </span><span><span><span>( SPH_UDF_INIT init, SPH_UDF_ARGS args,
</span></span><span><span><span><span>char</span></span></span></span><span><span> * error_message )</span></span></span></span>;

<span><span>/// 主调用</span></span>
<span><span>/// 返回计算的结果</span></span>
<span><span>/// 给error_flag写入非零值表示出现错误</span></span>
<span><span>RETURN_TYPE </span><span><span><span>myfunc</span></span></span><span> </span><span><span><span>( SPH_UDF_INIT init, SPH_UDF_ARGS args,
</span></span><span><span><span><span>char</span></span></span></span><span><span> * error_flag )</span></span></span></span>;

<span><span>/// 可选的卸载函数</span></span>
<span><span>/// 调用一次清理一次以完成查询处理</span></span>
<span><span><span><span>void</span></span></span><span> </span><span><span><span>myfunc_deinit</span></span></span><span> </span><span><span><span>( SPH_UDF_INIT * init )</span></span></span></span>;
</pre><p>上面提到的两个结构体, SPH_UDF_INIT 和 SPH_UDF_ARGS在 src/sphinxudf.h街头头文件中定义并说明。 主调用的RETURN_TYPE 可以是以下之一:</p><ul><li>int 表示函数返回值为 INT.</li><li>sphinx_int64_t 表示函数返回值为 BIGINT.</li><li>float 表示函数返回值为 FLOAT.</li></ul><p> </p><p>他们的调用顺序如下. myfunc_init() 在查询初始化时调用一次。它可以返回非零值表示失败;在此情况下查询将不会被执行,并可以通过error_message缓冲区来返回错误信息。然后,myfunc()会在每行处理中调用,myfunc_deinit()则在查询结束时调用。myfunc()可以通过写入非零值到error_flag来表示错误,此时它将不再被序列中的行调用,而是用默认值0来取代。Sphinx可能会也可能不会选择提前终止此类查询,目前不保证一定会如何选择。</p><h2>第 6 章 命令行工具参考</h2><p>目录</p><dl><dt>

     <a href="#ref-indexer">6.1.&nbsp;<code>indexer</code>:索引命令参考</a> 
    </dt><dt> 
     <a href="#ref-searchd">6.2.&nbsp;<code>searchd</code>:搜索服务端命令参考</a> 
    </dt><dt> 
     <a href="#ref-search">6.3.&nbsp;<code>search</code>:命令行搜索命令参考</a> 
    </dt><dt> 
     <a href="#ref-spelldump">6.4.&nbsp;<code>spelldump</code>:拼写信息导出命令参考</a> 
    </dt><dt> 
     <a href="#ref-indextool">6.5.&nbsp;<code>indextool</code>:索引信息导出命令参考</a> 
    </dt></dl><p>就像其他地方已经提到的,Sphinx不是个名叫“sphinx”的单独可执行程序,而是由四个独立的程序共同组成的。本节介绍这些工具和他们的用法。</p><h2>6.1.&nbsp;indexer:索引命令参考</h2><p>indexer&nbsp;是Sphinx的两个关键工具之一。不管是从命令行直接调用,还是作为一个较大的脚本的一部分使用,indexer都只负责一件事情——收集要被检索的数据。.</p><p>indexer的调用语法基本上是这样:</p><pre><code><span><span>indexer</span></span> <span><span>[OPTIONS]</span></span> <span><span>[indexname1 [indexname2 [...]</span></span>]]</code></pre><p>用户可以在sphinx.conf中设置好可能有哪些索引(index)(这些索引可以在晚些时候别搜索),因此在调用indexer的时候,最简单的情况下,只需要告诉它你要建立哪个(或者哪些)索引就行了。</p><p>假设&nbsp;sphinx.conf&nbsp;包含了两个索引的具体设置,&nbsp;mybigindex&nbsp;和&nbsp;mysmallindex, ,你可以这么调用:</p><pre><code><span><span>$ </span></span>indexer mybigindex

<span><span>$ </span></span>indexer mysmallindex mybigindex</code></pre><p>在配置文件sphinx.conf里面,用户可以为他们的数据指定一个或多个索引。然后调用indexer来对其中一个特定的索引进行重新编制索引操作,或者是重新编制所有索引——不限于某一个或同时全部,用户总是可以指定现有索引的一个组合。</p><p>indexer的大部分选项都可以在配置文件中给出,然而有一部分选项还需要在命令行上指定,这些选项影响编制索引这一操作是如何进行的。这些选项列举如下:</p><ul><li>--config &lt;file&gt;&nbsp;(简写为-c &lt;file&gt;) 使&nbsp;indexer&nbsp;将指定的文件file作为配置文件。 通常,indexer是会在安装目录(例如e.g.&nbsp;/usr/local/sphinx/etc/sphinx.conf&nbsp;,如果sphinx被安装在&nbsp;/usr/local/sphinx)中寻找sphinx.conf,若找不到,则继续在用户在shell中调用indexer时所在的目录中寻找。 这个选项一般在共享sphinx安装的情况下使用,比如二进制文件安装在/usr/local/sphinx,而不同用户都有权定制自己的sphinx设置。或者在同一个服务器上运行多个实例的情况下使用。在上述两中情况中,用户可以创建自己的sphinx.conf文件,然后把它做为参数传给indexer。例如:$ indexer --config /home/myuser/sphinx.conf myindex </li><li>--all 使indexer对sphinx.conf文件中列出的所有索引进行重新编制索引,这样就不比一次列出每个索引的名字了。这个选项在配置文件较小的情况下,或者在类似基于cron的维护工作中很有用。在上述情况中,整个索引集每天或每周或别的什么合适的时间间隔中就重新建立一次。用法示例:$ indexer --config /home/myuser/sphinx.conf --all </li><li>--rotate&nbsp;用于轮换索引。对新的文档建立索引时几乎肯定都确保搜索服务仍然可用,除非你有信心在搜索服务停止同时不给你的用户带来困扰。--rotate建立一个额外的索引,并列于原有索引(与原有索引在相同目录,简单地在原有索引文件名基础上加一个.new后缀)。一旦这个额外的索引建立完成,indexer给searchd发一个SIGHUP信号做为通知。searchd会尝试将索引重新命名(给原有索引加上.old后缀,而把带有.new后缀的新索引改为原名,以达替换之目的),继而用新的文件重启服务。依&nbsp;<a href="#conf-seamless-rotate">seamless_rotate</a>&nbsp;选项设定之不同,在新索引可用之前可能有一点小的延迟。用法示例:$ indexer --rotate --all </li><li>--quiet 使indexer不输出除错误(error)外的任何东西。这个选项通常用在cron定时任务的情境下或者脚本中,这些情况下大部分输出是无关紧要或完全没用的,除非是发生了某些种类的错误。用法示例:$ indexer --rotate --all --quiet </li><li>--noprogress&nbsp;不随时显示进度信息,而是仅在索引结束时报告最终的状态细节(例如为哪些文档建立了索引,建立索引的速度等)。当脚本没有运行在一个控制台(console,或“tty”)时,这个选项是默认的。用法示例:$ indexer --rotate --all --noprogress </li><li>--buildstops <outputfile.text> <N> 像建立索引一样扫描索引对应的数据源,产生一个最终会被加入索引的词项的列表。换种说法,产生一个用这个索引可以检索的词项的列表。注意,这个选项使indexer并不真正更新指定的索引,而只是“假装”建在立索引似地处理一遍数据,包括运行sql_query_pre或者sql_query_post选项指定的查询。outputfile.txt文件最终会包含一个词表,每行一个词,按词频排序,高频在前。参数N指定了列表中最多可出现的词项数目,如果N比索引中全部词项的数目还大,则返回的词项数就是全部词项数。客户端应用程序利用这种字典式的词表来提供“您是要搜索。。。吗?(Did you mean…)”的功能,通常这个选项与下面要讲的--buildfreqs选项一同使用。示例:$ indexer myindex --buildstops word_freq.txt 1000 这条命令在当前目录产生一个word_freq.txt文件,内含myindex这个索引中最常用的1000个词,且最常用的排在最前面。注意,当指定了多个索引名或使用了--all选项(相当于列出配置文件中的所有索引名)时,这个选项对其中的最后一个索引起作用。 </li><li>--buildfreqs 与 --buildstops一同使用 (如果没有指定 --buildstops 则--buildfreqs也被忽略). 它给--buildstops产
生的词表的每项增加一个计数信息,即该词在索引中共出现了多少次,这在建立停用词(stop
words,出现特别普遍的词)表时可能有用。在开发“您是要搜索。。。吗?(Did you
mean…)”的功能时这个选项也能帮上忙,因为有了它你就能知道一个词比另一个相近的词出现得更频繁的程度。示例:$ indexer myindex --buildstops word_freq.txt 1000 --buildfreqs 这个命令将产生一个类似于上一条命令的word_freq.txt&nbsp;,但不同在于,每个词的后面都会附加一个数字,指明在指定的索引中这个词出现了多少次。 </li><li>--merge &lt;dst-index&gt; &lt;src-index&gt;&nbsp;用于在物理上将多个索引合并,比方说你在使用“主索引+增量索引”模式,主索引很少改变,但增量索引很频繁地重建,而--merge选项允许将这两个索引合而为一。操作是从右向左进行的,即先考察src-index的内容,然后在物理上将之与dst-index合并,最后结果留在dst-index里。用伪代码说就是dst-index += src-index。示例:$ indexer --merge main delta --rotate 上例中main是主索引,很少更动,delta是增量索引,频繁更新。上述命令调用indexer将delta的内容合并到main里面并且对索引进行轮换。 </li><li>--merge-dst-range <attr> <min> <max> 在合并索引的时候运行范围过滤。具体地说,向目标索引 (是 --merge 的一个参数,如果没有指定 --merge, 则--merge-dst-range 也被忽略)合并时,indexer会对将要合并进去的文档做一次过滤,只有通过过滤才能最终出现在目标索引中。举一个实用的例子,假设某个索引有一个“已删除(deleted)”属性,0代表“尚未删除”。这样一个索引可以用如下命令进行合并:$ indexer --merge main delta --merge-dst-range deleted 0 0 这样标记为已删除的文档(值为1)就不会出现在新生成的目标索引中了。这个选项可以在命令行上指定多次,以便指定多个相继的过滤,这样一个文档要想合并到最终的目标索引中去,就必须依次通过全部这些过滤。 </li><li>--dump-rows <FILE> 用于从SQL数据源导出获取的数据到指定的文件,每行数据使用MySQL兼容的格式。导出的数据用于完整的再现indexer收到的数据并帮助重现索引时的问题。</li><li>--verbose 确保每条导致索引出现问题的行都会报告出来 ( 重复, 为零, 或者没有文档编号ID; 或者外部文件字段的Io问题; 等等) . 默认情况下,该选项是关闭的,作为替代的是报告问题摘要。</li><li>--sighup-each 有助于重建多个较大的索引并在每个索引轮换完成后马上生效可被searchd使用. 使用 --sighup-each, indexer 会在每个索引成功完成各项工作后给searchd发送SIGHUP信号。 (默认做法是在全部索引建立后发送SIGHUP信号)</li><li>--print-queries prints out SQL queries that indexer sends
to the database, along with SQL connection and disconnection events.
That is useful to diagnose and fix problems with SQL sources.</li></ul><p> </p><h2>6.2. searchd:搜索服务端命令参考</h2><p>searchd也是sphinx的两个关键工具之一。 searchd是系统实际上处理搜索的组件,运行时它表现得就像一种服务,他与客户端应用程序调用的五花八门的API通讯,负责接受查询、处理查询和返回数据集。</p><p>不同于 indexer, searchd 并不是设计用来在命令行或者一般的脚本中调用的, 相反,它或者做为一个守护程序(daemon)被init.d调用(在Unix/Linux类系统上),或者做为一种服务(在Windows类系统上),因此并不是所有的命令行选项都总是有效,这与构建时的选项有关。</p><p>使用 searchd 就像这么简单:</p><pre><span><span>$ </span></span>searchd [OPTIONS]</code></pre><p>不管&nbsp;searchd&nbsp;是如何构建的,下列选项总是可用:</p><ul><li>--help&nbsp;(可以简写为-h&nbsp;) 列出可以在你当前的searchd构建上调用的参数。.</li><li>--config &lt;file&gt;&nbsp;(可简写为-c &lt;file&gt;) 使&nbsp;searchd&nbsp;使用指定的配置文件,与上述indexer的--config开关相同。</li><li>--stop&nbsp;用于异步停掉&nbsp;searchd,使用sphinx.conf中所指定的PID文件,因此您可能还需要用--config选项来确认searchd使用哪个配置文件。值得注意的是,调用&nbsp;--stop&nbsp;会确保用&nbsp;<a href="#api-func-updateatttributes">UpdateAttributes()</a>&nbsp;对索引进行的更动会反应到实际的索引文件中去。示例:$ searchd --config /home/myuser/sphinx.conf --stop </li><li>--stopwait 用于同步停止 searchd. --stop 本质上是通知运行实例退出 (通过发送 SIGTERM信号) 然后立刻返回. --stopwait 将会一直等待直到 searchd 实例确实的完成了关闭(例如,保存所有在内存中的属性改变) 并退出. 示例:$ searchd --config /home/myuser/sphinx.conf --stopwait 可能的退出代码如下:

       
        
        0 表示成功; 
        1 表示连接到运行的searchd守护进程失败。; 
        2 表示守护进程在关闭时报告了错误; 
        3 表示守护进程关闭时崩溃. 
        
       </li><li>--status&nbsp;用来查询运行中的searchd实例的状态,,使用指定的(也可以不指定,使用默认)配置文件中描述的连接参数。它通过配置好的第一个UNIX套接字或TCP端口与运行中的实例连接。一旦连接成功,它就查询一系列状态和性能计数器的值并把这些数据打印出来。在应用程序中,可以用<a href="#api-func-status">Status()</a>&nbsp;API调用来访问相同的这些计数器。示例:$ searchd --status

$ searchd --config /home/myuser/sphinx.conf --status </li><li>--pidfile&nbsp;用来显式指定一个PID文件。PID文件存储着关于searchd的进程信息,这些信息用于进程间通讯(例如indexer需要知道这个PID以便在轮换索引的时候与searchd进行通讯)searchd在正常模式运行时会使用一个PID(即不是使用–console选项启动的),但有可能存在searchd在控制台(--console)模式运行,而同时正在索引正在进行更新和轮换操作的情况,此时就需要一个PID文件。$ searchd --config /home/myuser/sphinx.conf --pidfile /home/myuser/sphinx.pid </li><li>--console is used to force searchd 用来强制searchd以控制台模式启动;典型情况下searchd像一个传统的服务器应用程序那样运行,它把信息输出到(sphinx.conf配

置文件中指定的)日志文件中。但有些时候需要调试配置文件或者守护程序本身的问题,或者诊断一些很难跟踪的问题,这时强制它把信息直接输出到调用他的控制

台或者命令行上会使调试工作容易些。同时,以控制台模式运行还意味着进程不会fork(因此搜索操作都是串行执行的),也不会写日志文件。(要特别注意,searchd并不是被主要设计用来在控制台模式运行的)。可以这样调用searchd:$ searchd --config /home/myuser/sphinx.conf --console </li><li>--logdebug&nbsp;让额外的调试信息输出到守护进程日志中。使用的较少,用于帮助调试难以重现的请求。</li><li>--iostats&nbsp;当使用日志时(必须在sphinx.conf中启用query_log选项)启用--iostats会对每条查询输出关于查询过程中发生的输入输出操作的详细信息,会带来轻微的性能代价,并且显然会导致更大的日志文件。更多细节请参考&nbsp;<a href="#query-log-format">query log format</a>&nbsp;一节。可以这样启动searchd:$ searchd --config /home/myuser/sphinx.conf --iostats </li><li>--cpustats 使实际CPU时间报告(不光是实际度量时间(wall time))出现在查询日志文件(每条查询输出一次)和状态报告(累加之后)中。这个选项依赖clock_gettime()系统调用,因此可能在某些系统上不可用。可以这样启动searchd:$ searchd --config /home/myuser/sphinx.conf --cpustats </li><li>--port portnumber&nbsp;(可简写为-p) 指定searchd监听的端口,通常用于调试。这个选项的默认值是9312,但有时用户需要它运行在其他端口上。在这个命令行选项中指定端口比配置文件中做的任何设置优先级都高。有效的端口范围是0到65535,但要使用低于1024的端口号可能需要权限较高的账户。使用示例:$ searchd --port 9313 </li><li>--listen ( address ":" port | port | path ) [ ":" protocol ] (or -l for short) Works as --port, but allow you to specify not only the port, but full path, as IP address and port, or Unix-domain socket path, that searchd will
listen on. Otherwords, you can specify either an IP address (or
hostname) and port number, or just a port number, or Unix socket path.
If you specify port number but not the address, searchd will listen on
all network interfaces. Unix path is identified by a leading slash. As
the last param you can also specify a protocol handler (listener) to be
used for connections on this socket. Supported protocol values are
‘sphinx’ (Sphinx 0.9.x API protocol) and ‘mysql41′ (MySQL protocol used
since 4.1 upto at least 5.1).</li><li>--index <index> (或者缩写为 -i <index>) 强制searchd只提供针对指定索引的搜索服务。跟上面的--port相同,这主要是用于调试,如果是长期使用,则应该写在配置文件中。使用示例:$ searchd --index myindex </li><li>--strip-path 用于去除索引中所有引用到的文件名中的路径名 (stopwords, wordforms, exceptions, 等等). 这有助于继续使用在其他可能路径布局不同的机器上建立的索引。</li></ul><p>searchd在Windows平台上有一些特有的选项,与它做为windows服务所产生的额外处理有关,这些选项只存在于Windows二进制版本。</p><p>注意,在Windows上searchd默认以--console模式运行,除非用户将它安装成一个服务。</p><ul><li>--install installs searchd 将searchd安装成一个微软管理控制台(Microsoft Management Console, 控制面板 / 管理工具 / 服务)中的服务。如果一条命令指定了--install,那么同时使用的其他所有选项,都会被保存下来,服务安装好后,每次启动都会调用这些命令。例如,调用searchd时,我们很可能希望用--config指定要使用的配置文件,那么在使用--install的同时也要加入这个选项。一旦调用了这个选项,用户就可以在控制面板中的管理控制台中对searchd进行启动、停止等操作,因此一切可以开始、停止和重启服务的方法对searchd也都有效。示例:C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --install
--config C:\Sphinx\sphinx.conf 如果每次启动searchd你都希望得到I/O stat信息,那就应该把这个选项也用在调用--install的命令行里: C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --install
--config C:\Sphinx\sphinx.conf --iostats </li><li>--delete 在微软管理控制台(Microsoft Management Console)和其他服务注册的地方删除searchd,当然之前要已经通过--install安装过searchd服务。注意,这个选项既不删除软件本身,也不删除任何索引文件。调用这个选项之后只是使软件提供的服务不能从windows的服务系统中调用,也不能在机器重启后自动启动了。如果调用时searchd正在做为服务运行中,那么现有的示例并不会被结束(一直会运行到机器重启或调用--stop)。如果服务安装时(用--servicename)指定了自定义的名字,那在调用此选项卸载服务时里也需要用--servicename指定相同的名字。示例:C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --delete </li><li>--servicename <name> 在安装或卸载服务时指定服务的名字,这个名字会出现在管理控制台中。有一个默认的名字searchd,但若安装服务的系统可能有多个管理员登录,或同时运行多个searchd实例,那么起一个描述性强的名字将是个好好主意。注意,只有在与--install或者--delete同时使用的时候--servicename才有效,否则这个选项什么都不做。示例:C:\WINDOWS\system32> C:\Sphinx\bin\searchd.exe --install
--config C:\Sphinx\sphinx.conf --servicename SphinxSearch </li><li>--ntservice 在Windows平台,管理控制台将searchd做为服务调用时将这个选项传递给它。通常没有必要直接调用这个开关,它是为Windows系统准备的,当服务启动时,系统把这个参数传递给searchd。然而理论上,你也可以用这个开关从命令行将searchd启动成普通服务模式(与--console代表的控制台模式相对)</li></ul><p>最后但并非最不重要的,类似其他的守护进程(daemon),searchd支持多种信号。</p><dl><dt>

       SIGTERM 
     </dt><dd>
       进行一次平滑的重启。新的请求不会被接受;但是已经开始的请求不会被强行中断。 
     </dd><dt>
       SIGHUP 
     </dt><dd>
       启动索引轮换。取决于&nbsp; 
      <a href="#conf-seamless-rotate">seamless_rotate</a>&nbsp;的设置,新的请求可能会在短期内陷入停顿;客户端将接收到临时错误。 
     </dd><dt>
       SIGUSR1 
     </dt><dd>
       强制重新打开searchd日志和查询日志,使得日志轮换可以进行。 
     </dd></dl><p>&nbsp;</p><h2>6.3.&nbsp;search:命令行搜索命令参考</h2><p>search&nbsp;是Sphinx中的一个辅助工具。searchd负责服务器类环境中的搜索,而search专注于在命令行上对索引进行快速测试,而不需要构建一个复杂的架构来处理到服务器端的连接和处理服务器返回的响应。</p><p>注意:search并不是设计用来做为客户端应用程序的一部分。我们强烈建议用户不要针对search编写接口,相反,应该针对searchd。Sphinx提供的任何客户端API也都不支持这种用法。(任何时候search总是每次都重新调入索引,而searchd会把索引缓冲在内存中以利性能)。</p><p>澄清了这些我们就可以继续了。很多通过API构造的查询也可以用search来做到,然而对于非常复杂的查询,可能还是用个小脚本和对应的API调用来实现比较简单。除此之外,可能有些新的特性先在searchd系统中实现了而尚未引入到search中。</p><p>search&nbsp;的调用语法如下:</p><pre><code><span><span>search</span></span> <span><span>[OPTIONS]</span></span> <span><span>word1</span></span> <span><span>[word2 [word3 [...]</span></span>]]</code></pre><p>调用search并不要求searchd正在运行,只需运行search的账户对配置文件和索引文件及其所在路径有读权限即可。</p><p>默认行为是对在配置文件中设置的全部索引的全部字段搜索word1(AND word2 AND word3….)。如果用API调用来构建这个搜索,那相当于向SetMatchMode传递参数SPH_MATCH_ALL,然后在调用Query的时候指定要查询的索引是*。</p><p>search有很多选项。首先是通用的选项:</p><ul><li>--config &lt;file&gt;&nbsp;(可简写为-c &lt;file&gt;) 使search使用指定的配置文件,这与上述indexer的对应选项相同。</li><li>--index &lt;index&gt;&nbsp;(可简写为-i &lt;index&gt;) 使search仅搜索指定的索引。通常它会尝试搜索sphinx.conf中列出的全部物理索引,不包括分布式索引。</li><li>--stdin使search接受标准输入(STDIN)上传入的查询,而不是命令行上给出的查询。有时你要用脚本通过管道给search传入查询,这正是这个选项的用武之地。</li></ul><p>&nbsp;</p><p>设置匹配方式的选项:</p><ul><li>--any&nbsp;(可简写为-a) 更改匹配模式,匹配指定的任意一个词(word1 OR word2 OR word3),这对应API调用中向SetMatchMode传递参数SPH_MATCH_ANY。</li><li>--phrase&nbsp;(可简写为-p) 更改匹配模式,将指定的全部词做为一个词组(不包括标点符号)构成查询,这对应API调用中向SetMatchMode传递参数SPH_MATCH_PHRASE。</li><li>--boolean&nbsp;(可简写为-b) 将匹配模式设为&nbsp;<a href="#boolean-syntax">Boolean matching</a>。注意如果在命令行上使用布尔语法,可能需要对某些符号(用反斜线“\”)加以转义,以避免外壳程序(shell)或命令行处理器对这些符号做特殊理解,例如,在Unix/Linux系统上必须转义“&”以防止search被fork成一个后台进程,尽管这个问题也可以像下文一样通过使用--stdin选项来解决。这个选项对应API调用中向SetMatchMode传递参数SPH_MATCH_BOOLEAN。</li><li>--ext&nbsp;(可简写为-e) 将匹配模式设为<a href="#extended-syntax">Extended matching</a>。这对应与API调用中向SetMatchMode传递参数SPH_MATCH_EXTENDED。要注意的是因为已经有了更好的扩展匹配模式版本2,所以并不鼓励使用这个选项,见下一条说明。</li><li>--ext2&nbsp;(可简写为-e2) 将匹配模式设为&nbsp;<a href="#extended-syntax">扩展比配, 版本 2</a>。这个选项对应在API调用中向SetMatchMode传递参数SPH_MATCH_EXTENDED2。要注意这个选项相比老的扩展匹配模式更有效也提供更多的特性,因此推荐使用这个新版的选项。</li><li>--filter &lt;attr&gt; &lt;v&gt;&nbsp;(可简写为-f &lt;attr&gt; &lt;v&gt;) 对结果进行过滤,只有指定的属性attr匹配指定的值v时才能通过过滤。例如--filter deleted 0&nbsp;只匹配那些有deleted属性,并且其值是0的文档。也可以在命令行上多次给出--filter以便指定多重过滤,但是如果重复定义针对同一个属性的过滤器,那么第二次指定的过滤条件会覆盖第一次的。</li></ul><p>&nbsp;</p><p>用于处理搜索结果的选项:</p><ul><li>--limit &lt;count&gt;&nbsp;(可简写为-l count) 限制返回的最多匹配结果数。如果指定了分组(group)选项,则表示的是返回的最多匹配组数。默认值是20个结果(与API相同)</li><li>--offset &lt;count&gt;&nbsp;(可简写为-o &lt;count&gt;) 从第count个结果开始返回,用于给搜索结果分页。如果想要每页20个结果,那么第二页就从偏移量20开始,第三页从偏移量40开始,以此类推。</li><li>--group &lt;attr&gt;&nbsp;(可简写为-g &lt;attr&gt;) 搜索结果按照指定的属性attr进行分组。类似SQL中的GROUP BY子句,这会将attr属性值一致的结果结合在一起,返回的结果集中的每条都是一组中最好的那条结果。如果没有特别指定,那“最好”指的是相关度最大的。</li><li>--groupsort &lt;expr&gt;&nbsp;(可简写为-gs &lt;expr&gt;) 使搜索结果根据-group分组后,再用表达式&lt;expr&gt;的值决定分组的顺序。注意,这个选项指定的不是各组内部哪条结果是最好的,而是分组本身返回的顺序。</li><li>--sortby &lt;clause&gt;&nbsp;(可简写为-s &lt;clause&gt;) 指定结果按照&lt;clause&gt;中指定的顺序排序。这使用户可以控制搜索结果展现时的顺序,即根据不同的列排序。例如,--sortby "@weight DESC entrytime DESC"的意思是将结果首先按权值(相关度)排序,如果有两条或以上结果的相关度相同,则他们的顺序由时间值entrytime决定,时间最近(值最大)的排在前面。通常需要将这些项目放在引号里(--sortby "@weight DESC")或者用逗号隔开(--sortby @weight,DESC),以避免它们被分开处理。另外,与通常的排序模式相同,如果指定了--group(分组),这个选项就影响分组内部的结果如何排序。</li><li>--sortexpr expr&nbsp;(可简写为-S expr) 搜索结果展现的顺序由指定的算术表达式expr决定。例如:&nbsp;--sortexpr "@weight + ( user_karma + ln(pageviews) )*0.1"(再次提示,要用引号来避免shell对星号*做特殊处理)。扩展排序模式在<a href="#sorting-modes">排序模式</a>&nbsp;一章下的SPH_SORT_EXTENDED条目下具体讨论。</li><li>--sort=date&nbsp;搜索结果按日期降序(日期最新的在前)排列。要求索引中有一个属性被指定为时间戳。</li><li>--rsort=date&nbsp;特别指定结果升序排列(日期中较老的在前)。要求索引中有一个属性被指定为时间戳。</li><li>--sort=ts&nbsp;搜索结果按时间戳分成组。先返回时间戳在最近一小时内的这组结果,在组内部按相关度排序。其后返回时间戳为最近一天之内的结果,也按相关度排序。再之后是最近一周的,最后是最近一个月的。在<a href="#sorting-modes">排序模式</a>&nbsp;一章的SPH_SORT_TIME_SEGMENTS&nbsp;条目下对此有更详细的讨论。</li></ul><p>&nbsp;</p><p>其他选项:</p><ul><li>--noinfo&nbsp;(可简写为-q) 使search不在SQL数据库中查询文档信息(Document Info)。具体地说,为了调试search和MySQL共同使用时出现的问题,你可以在使用这个选项的同时提供一个根据文档ID搜索整个文章全文的查询。细节可参考<a href="#conf-sql-query-info">sql_query_info</a>指令。</li></ul><p>&nbsp;</p><h2>6.4.&nbsp;spelldump:拼写信息导出命令参考</h2><p>spelldump&nbsp;是Sphinx的一个辅助程序。</p><p>用于从ispell或者MySpell格式的字典文件中可用来辅助建立词形列表(wordforms)的内容——词的全部可能变化都预先构造好。</p><p>一般用法如下:</p><pre><code><span><span>spelldump</span></span> <span><span>[options]</span></span> &lt;<span><span>dictionary</span></span>&gt; &lt;<span><span>affix</span></span>&gt; <span><span>[result]</span></span> <span><span>[locale-name]</span></span></code></pre><p>两个主要参数是词典的主文件([language-prefix].dict)和词缀文件([language-prefix].aff);通常这两种文件被命名为[语言简写].dict和[语言简写].aff,大多数常见的Linux发行版中都有这些文件,网上也到处找得到。</p><p>[result]&nbsp;指定的是字典数据的输出位置,而[locale-name]指定了具体使用的区域设置(locale)。</p><p>还有一个-c [file]选项,用来指定一个包含大小写转换方面细节的文件。</p><p>用法示例:</p><pre><code><span><span>spelldump</span></span> <span><span>en</span></span><span><span>.dict</span></span> <span><span>en</span></span><span><span>.aff</span></span>

<span><span>spelldump</span></span> <span><span>ru</span></span><span><span>.dict</span></span> <span><span>ru</span></span><span><span>.aff</span></span> <span><span>ru</span></span><span><span>.txt</span></span> <span><span>ru_RU</span></span><span><span>.CP1251</span></span>
<span><span>spelldump</span></span> <span><span>ru</span></span><span><span>.dict</span></span> <span><span>ru</span></span><span><span>.aff</span></span> <span><span>ru</span></span><span><span>.txt</span></span> <span><span>.1251</span></span>
</pre><p>结果文件会包含字典中包含的全部词,字典序排列,wordforms文件格式。可以根据具体的使用环境定制这些文件。结果文件的一个例子:</p><pre><span><span>zone</span></span> > zone
zoned > zoned
zoning > zoning
</pre><h2>6.5. indextool:索引信息导出命令参考</h2><p>indextool是版本0.9.9-rc2中引入的辅助工具。用于输出关于物理索引的多种调试信息。(未来还计划加入索引验证等功能,因此起名较indextool而不是indexdump)。 基本用法如下:</p><pre>indextool <<span><span>command</span></span>> [options]</pre><p>唯一一个所有命令都有的选项是--config,用于指定配置文件:</p><ul><li>--config <file> (可简写为-c <file> ) 覆盖默认的配置文件名。</li></ul><p> </p><p>其他可用的命令如下:</p><ul><li>--dumpheader FILENAME.sph 在不涉及任何其他索引文件甚至配置文件的前提下,快速输出索引头文件的内容,包括索引的全部设置,尤其是完整的属性列表、字段列表。在版本0.9.9-rc2之前,这个命令是由search工具提供的。 CLI search utility.</li><li>--dumpconfig FILENAME.sph 从给定的索引头文件导出sphinx.conf文件格式兼容(基本上)的索引配置信息。版本2.0.1-beta新增。</li><li>--dumpheader INDEXNAME 输出给定索引名的索引头内容,索引头文件的路径是在配置文件中查得的。</li><li>--dumpdocids INDEXNAME 输出给定索引名涉及的文档ID。数据是从属性文件(.spa)中抽取的,因此要求doc_info=extern正常工作。</li><li>--dumphitlist INDEXNAME KEYWORD 输出指定关键字KEYWORD在执行索引中的的全部出现。</li><li>--dumphitlist INDEXNAME --wordid ID 输出指定关键字KEYWORD在执行索引中的的全部出现,但是关键字使用特定的内部数字编号。</li><li>--htmlstrip INDEXNAME 使用指定的索引中的HTML剥离器设置来过滤标准输入并打印过滤结果到标准输出。需要注意的是配置信息从sphinx.conf中获得,而不是从索引头文件中获得。</li><li>--check INDEXNAME 检查可能由于indexer的bug或者硬件问题导致的索引数据一致性错误。</li><li>--strip-path 用于去除索引中所有引用到的文件名中的路径名 (stopwords, wordforms, exceptions, 等等). 这有助于继续使用在其他可能路径布局不同的机器上建立的索引。</li></ul><h2>第 7 章 SphinxQL 指南</h2><p>目录</p><dl><dt>

     <a href="#sphinxql-select">7.1. SELECT(搜索查询)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-show-meta">7.2. SHOW META(显示查询状态信息)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-show-warnings">7.3. SHOW WARNINGS(显示查询警告信息)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-show-status">7.4. SHOW STATUS(显示服务端状态信息)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-insert">7.5. INSERT 和 REPLACE(数据插入和替换)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-delete">7.6. DELETE(数据删除)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-set">7.7. SET(设置服务端变量)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-commit">7.8. BEGIN, COMMIT, 以及 ROLLBACK(事务处理)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-call-snippets">7.9. CALL SNIPPETS(摘要生成)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-call-keywords">7.10. CALL KEYWORDS(关键词生成)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-show-tables">7.11. SHOW TABLES(显示当前提供搜索服务的索引列表)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-describe">7.12. DESCRIBE(显示指定搜索服务索引的字段信息)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-create-function">7.13. CREATE FUNCTION(添加自定义函数)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-drop-function">7.14. DROP FUNCTION(删除自定义函数)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-show-variables">7.15. SHOW VARIABLES(显示服务器端变量)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-show-variables">7.16. SHOW COLLATION(显示字符集校对)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-update">7.17. UPDATE(数据更新)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-multi-queries">7.18. 多结果集查询(批量查询)</a> 
    </dt><dt> 
     <a href="#sphinxql-comment-syntax">7.19. COMMIT(注释)语法</a> 
    </dt><dt> 
     <a href="#sphinxql-reserved-keywords">7.20. SphinxQL 保留关键字列表</a> 
    </dt><dt> 
     <a href="#sphinxql-upgrading-magics">7.21. SphinxQL 升级备注, version 2.0.1-beta</a> 
    </dt></dl><p>SphinxQL是有我们自己特色的SQL子集,通过使用标准的SQL语句并加上Sphinx特定的扩展,将搜索驻守进程的功能对外提供。所有通过

SphinxAPI提供的功能都可以通过SphinxQL访问,不过反过来则不行,例如对RT索引的写操作只能通过SPhinxQL。本章的文档列出了所
支持的SphinxQL语句的语法。</p><h2>7.1. SELECT(搜索查询)语法</h2><pre><span><span>SELECT</span></span>
select_expr [, select_expr ...]
<span><span>FROM</span></span> <span><span>index</span></span> [, index2 ...]
[<span><span>WHERE</span></span> where_condition]
[<span><span>GROUP</span></span> <span><span>BY</span></span> {col_name | expr_alias}]
[<span><span>ORDER</span></span> <span><span>BY</span></span> {col_name | expr_alias} {<span><span>ASC</span></span> | <span><span>DESC</span></span>} [, ...]]
[<span><span>WITHIN</span></span> <span><span>GROUP</span></span> <span><span>ORDER</span></span> <span><span>BY</span></span> {col_name | expr_alias} {<span><span>ASC</span></span> | <span><span>DESC</span></span>}]
[<span><span>LIMIT</span></span> <span><span>offset</span></span>, <span><span>row_count</span></span>]
[<span><span>OPTION</span></span> opt_name = opt_value [, ...]]
</pre><p>SELECT 语句在版本0.9.9-rc2引入。 其语法基于通常的SQL,但是加入了一些Sphinx特定的扩展,并省略了一些功能(例如(目前)不支持多表联合(JOIN))。特别的,</p><ul><li>Column list clause. Column names, arbitrary expressions, and star (‘’) are all allowed (ie. SELECT @id, group_id123+456 AS expr1 FROM test1 will
work). Unlike in regular SQL, all computed expressions must be aliased
with a valid identifier. Starting with version 2.0.1-beta, AS is
optional. Special names such as @id and @weight should currently be
used with leading at-sign. This at-sign requirement will be lifted in
the future.</li><li>FROM clause. FROM clause should contain the list of indexes
to search through. Unlike in regular SQL, comma means enumeration of
full-text indexes as in Query() API call rather than JOIN.</li><li>WHERE clause. This clause will map both to fulltext query
and filters. Comparison operators (=, !=, <, >, <=, >=), IN,
AND, NOT, and BETWEEN are all supported and map directly to filters. OR
is not supported yet but will be in the future. MATCH(‘query’) is
supported and maps to fulltext query. Query will be interpreted
according to full-text query language rules. There must be at most one MATCH() in the clause. Starting with version 2.0.1-beta, {col_name | expr_alias} [NOT] IN @uservar condition syntax is supported. (Refer to 第 7.7 节 “SET(设置服务端变量)语法” for a discussion of global user variables.)</li><li>GROUP BY clause. Currently only supports grouping by a single column. The column however can be a computed expression:SELECT , group_id1000+article_type AS gkey FROM example GROUP BY gkey Aggregate
functions (AVG(), MIN(), MAX(), SUM()) in column list clause are
supported. Arguments to aggregate functions can be either plain
attributes or arbitrary expressions. COUNT(*) is implicitly supported as
using GROUP BY will add @count
column to result set. Explicit support might be added in the future.
COUNT(DISTINCT attr) is supported. Currently there can be at most one
COUNT(DISTINCT) per query and an argument needs to be an attribute. Both
current restrictions on COUNT(DISTINCT) might be lifted in the future. SELECT *, AVG(price) AS avgprice, COUNT(DISTINCT storeid)
FROM products
WHERE MATCH('ipod')
GROUP BY vendorid Starting with 2.0.1-beta, GROUP BY on a string attribute is supported, with respect for current collation (参见 第 5.12 节 “字符串排序规则”). </li><li>WITHIN GROUP ORDER BY clause. This is a Sphinx specific
extension that lets you control how the best row within a group will to
be selected. The syntax matches that of regular ORDER BY clause:SELECT , INTERVAL(posted,NOW()-786400,NOW()-86400) AS timeseg
FROM example WHERE MATCH('my search query')
GROUP BY siteid
WITHIN GROUP ORDER BY @weight DESC
ORDER BY timeseg DESC, @weight DESC Starting with 2.0.1-beta, WITHIN GROUP ORDER BY on a string attribute is supported, with respect for current collation (参见 第 5.12 节 “字符串排序规则”). </li><li>ORDER BY clause. Unlike in regular SQL, only column names
(not expressions) are allowed and explicit ASC and DESC are required.
The columns however can be computed expressions:SELECT , @weight10+docboost AS skey FROM example ORDER BY skey Starting with 2.0.1-beta, ORDER BY on a string attribute is supported, with respect for current collation (参见 第 5.12 节 “字符串排序规则”). </li><li>LIMIT clause. Both LIMIT N and LIMIT M,N forms are
supported. Unlike in regular SQL (but like in Sphinx API), an implicit
LIMIT 0,20 is present by default.</li><li>OPTION clause. This is a Sphinx specific extension that lets you control a number of per-query options. The syntax is:OPTION <optionname>=<value> [ , ... ] Supported options and respectively allowed values are:

       
        
        ‘ranker’ – any of ‘proximity_bm25′, ‘bm25′, ‘none’, ‘wordcount’, ‘proximity’, ‘matchany’, or ‘fieldmask’ 
        ‘max_matches’ – integer (per-query max matches value) 
        ‘cutoff’ – integer (max found matches threshold) 
        ‘max_query_time’ – integer (max search time threshold, msec) 
        ‘retry_count’ – integer (distributed retries count) 
        ‘retry_delay’ – integer (distributed retry delay, msec) 
        ‘field_weights’ – a named integer list (per-field user weights for ranking) 
        ‘index_weights’ – a named integer list (per-index user weights for ranking) 
        ‘reverse_scan’ – 0 or 1, lets you control the order in which full-scan query processes the rows 
        
       Example: SELECT * FROM test WHERE MATCH('@title hello <a href="http://my.oschina.net/xshiyun" target="_blank">@body</a>  world')

OPTION ranker=bm25, max_matches=3000,

field_weights=(title=10, body=3) </li></ul><p> </p><h2>7.2. SHOW META(显示查询状态信息)语法</h2><pre><span><span>SHOW</span></span> META</pre><p>SHOW META shows additional meta-information about the latest query such as query time and keyword statistics:</p><pre>mysql> SELECT * FROM test1 WHERE MATCH(<span><span>'testonetwo'</span></span>);
<span><span>id</span></span> weight <span><span>group_id</span></span> date_added <span><span>
</span></span> <span><span>1</span></span> <span><span>3563</span></span> <span><span>456</span></span> <span><span>1231721236</span></span>
<span><span>2</span></span> <span><span>2563</span></span> <span><span>123</span></span> <span><span>1231721236</span></span> <span><span>
</span></span> <span><span>4</span></span> <span><span>1480</span></span> <span><span>2</span></span> <span><span>1231721236</span></span>

<span><span>3</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>01</span></span> sec)

mysql> SHOW META;
<span><span>Variable_name</span></span> Value <span><span>
</span></span> total <span><span>3</span></span>
<span><span>total_found</span></span> <span><span>3</span></span> <span><span>
</span></span> time <span><span>0.005</span></span>
<span><span>keyword[0]</span></span> test <span><span>
</span></span> docs[<span><span>0</span></span>] <span><span>3</span></span>
<span><span>hits[0]</span></span> <span><span>5</span></span> <span><span>
</span></span> keyword[<span><span>1</span></span>] <span><span>one</span></span>
<span><span>docs[1]</span></span> <span><span>1</span></span> <span><span>
</span></span> hits[<span><span>1</span></span>] <span><span>2</span></span>
<span><span>keyword[2]</span></span> two <span><span>
</span></span> docs[<span><span>2</span></span>] <span><span>1</span></span>
<span><span>hits[2]</span></span> <span><span>2</span></span> <span><span>

12 rows </span><span><span><span>in</span></span></span><span> set (0.00 sec)</span></span></pre><p> </p><h2>7.3. SHOW WARNINGS(显示查询警告信息)语法</h2><pre><span><span>SHOW</span></span> <span><span>WARNINGS</span></span></pre><p>SHOW WARNINGS statement, introduced in
version 0.9.9-rc2, can be used to retrieve the warning produced by the
latest query. The error message will be returned along with the query
itself:</p><pre>mysql> SELECT * FROM test1 WHERE MATCH('@@title hello') \G
ERROR 1064 (42000): index test1: syntax error, unexpected TOK_FIELDLIMIT
near '@title hello'

mysql> SELECT * FROM test1 WHERE MATCH('@title -hello') \G
ERROR 1064 (42000): index test1: query is non-computable (single NOT operator)

mysql> SELECT * FROM test1 WHERE MATCH('"test doc"/3') \G
<span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span> 1. row </span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span>
id: 4
weight: 2500
group_id: 2
date_added: 1231721236
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS \G
<span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span> 1. row </span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span>
Level: warning
Code: 1000
Message: quorum threshold too high (words=2, thresh=3); replacing quorum operator
with AND operator
1 row in set (0.00 sec)
</pre><p> </p><h2>7.4. SHOW STATUS(显示服务端状态信息)语法</h2><p>SHOW STATUS, introduced in version 0.9.9-rc2,
displays a number of useful performance counters. IO and CPU counters
will only be available if searchd was started with –iostats and

–cpustats switches respectively.</p><pre>mysql> SHOW STATUS;
<span><span>Variable_name</span></span> Value <span><span>
</span></span> uptime <span><span>216</span></span>
<span><span>connections</span></span> <span><span>3</span></span> <span><span>
</span></span> maxed_out <span><span>0</span></span>
<span><span>command_search</span></span> <span><span>0</span></span> <span><span>
</span></span> command_excerpt <span><span>0</span></span>
<span><span>command_update</span></span> <span><span>0</span></span> <span><span>
</span></span> command_keywords <span><span>0</span></span>
<span><span>command_persist</span></span> <span><span>0</span></span> <span><span>
</span></span> command_status <span><span>0</span></span>
<span><span>agent_connect</span></span> <span><span>0</span></span> <span><span>
</span></span> agent_retry <span><span>0</span></span>
<span><span>queries</span></span> <span><span>10</span></span> <span><span>
</span></span> dist_queries <span><span>0</span></span>
<span><span>query_wall</span></span> <span><span>0</span></span>.<span><span>075</span></span> <span><span>
</span></span> query_cpu <span><span>OFF</span></span>
<span><span>dist_wall</span></span> <span><span>0</span></span>.<span><span>000</span></span> <span><span>
</span></span> dist_local <span><span>0.000</span></span>
<span><span>dist_wait</span></span> <span><span>0</span></span>.<span><span>000</span></span> <span><span>
</span></span> query_reads <span><span>OFF</span></span>
<span><span>query_readkb</span></span> OFF <span><span>
</span></span> query_readtime <span><span>OFF</span></span>
<span><span>avg_query_wall</span></span> <span><span>0</span></span>.<span><span>007</span></span> <span><span>
</span></span> avg_query_cpu <span><span>OFF</span></span>
<span><span>avg_dist_wall</span></span> <span><span>0</span></span>.<span><span>000</span></span> <span><span>
</span></span> avg_dist_local <span><span>0.000</span></span>
<span><span>avg_dist_wait</span></span> <span><span>0</span></span>.<span><span>000</span></span> <span><span>
</span></span> avg_query_reads <span><span>OFF</span></span>
<span><span>avg_query_readkb</span></span> OFF <span><span>
</span></span> avg_query_readtime <span><span>OFF</span></span>
<span><span>29</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>00</span></span> sec)</pre><p> </p><h2>7.5. INSERT 和 REPLACE(数据插入和替换)语法</h2><pre>{INSERTREPLACE} INTO index [(column, <span><span>...</span></span>)]

VALUES (value, <span><span>...</span></span>)
[, (<span><span>...</span></span>)]</pre><p>INSERT statement, introduced in version 1.10-beta, is only
supported for RT indexes. It inserts new rows (documents) into an
existing index, with the provided column values.</p><p>ID column must be present in all cases. Rows with duplicate IDs will not be overwritten by INSERT; use REPLACE to do that.</p><p>index is the name of RT index into which the new
row(s) should be inserted. The optional column names list lets you only
explicitly specify values for some of the columns present in the index.
All the other columns will be filled with their default values (0 for
scalar types, empty string for text types).</p><p>Expressions are not currently supported in INSERT and values should be explicitly specified.</p><p>Multiple rows can be inserted using a single INSERT statement
by providing several comma-separated, parens-enclosed lists of rows
values.</p><h2>7.6. DELETE(数据删除)语法</h2><pre><span><span>DELETE</span></span> <span><span>FROM</span></span> <span><span>index</span></span> <span><span>WHERE</span></span> {<span><span>id</span></span> = <span><span>value</span></span> | <span><span>id</span></span> <span><span>IN</span></span> (val1 [, val2 [, ...]])}</pre><p>DELETE statement, introduced in version 1.10-beta, is only
supported for RT indexes. It deletes existing rows (documents) from an
existing index based on ID.</p><p>index is the name of RT index from which the row should be deleted. value is the row ID to be deleted. Support for batch id IN (2,3,5) syntax was added in version 2.0.1-beta.</p><p>Additional types of WHERE conditions (such as conditions on attributes, etc) are planned, but not supported yet as of 1.10-beta.</p><h2>7.7. SET(设置服务端变量)语法</h2><pre><span><span>SET</span></span> [<span><span>GLOBAL</span></span>] server_variable_name = <span><span>value</span></span>
<span><span>SET</span></span> <span><span>GLOBAL</span></span> @user_variable_name = (int_val1 [, int_val2, ...])
</pre><p>SET statement, introduced in version 1.10-beta, modifies a
server variable value. The variable names are case-insensitive. No
variable value changes survive server restart. There are the following
classes of the variables:</p><ol><li>per-session server variable (1.10-beta and above)</li><li>global server variable (2.0.1-beta and above)</li><li>global user variable (2.0.1-beta and above)</li></ol><p> </p><p>Global user variables are shared between concurrent sessions.
Currently, the only supported value type is the list of BIGINTs, and
these variables can only be used along with IN() for filtering purpose.
The intended usage scenario is uploading huge lists of values to searchd (once) and reusing them (many times) later, saving on network overheads. Example:</p><pre>// <span><span>in</span></span> session <span><span>1</span></span>
mysql> SET GLOBAL @myfilter=(<span><span>2</span></span>,<span><span>3</span></span>,<span><span>5</span></span>,<span><span>7</span></span>,<span><span>11</span></span>,<span><span>13</span></span>);
Query OK, <span><span>0</span></span> rows affected (<span><span>0.00</span></span> sec)

// later <span><span>in</span></span> session <span><span>2</span></span>
mysql> SELECT * FROM test1 WHERE group_id IN @myfilter;
+<span><span>------+--------+----------+------------+-----------------+------+</span></span>
| id | weight | group_id | date_added | title | tag |
+<span><span>------+--------+----------+------------+-----------------+------+</span></span>
| <span><span>3</span></span> | <span><span>1</span></span> | <span><span>2</span></span> | <span><span>1299338153</span></span> | another doc | <span><span>15</span></span> |
| <span><span>4</span></span> | <span><span>1</span></span> | <span><span>2</span></span> | <span><span>1299338153</span></span> | doc number four | <span><span>7</span></span>,<span><span>40</span></span> |
+<span><span>------+--------+----------+------------+-----------------+------+</span></span>
<span><span>2</span></span> rows <span><span>in</span></span> set (<span><span>0.02</span></span> sec)
</pre><p> </p><p>Per-session and global server variables affect certain server
settings in the respective scope. Known per-session server variables
are:</p><dl><dt>

      <code>AUTOCOMMIT = {0 | 1}</code> 
     </dt><dd>
       Whether any data modification statement should be implicitly wrapped by BEGIN and COMMIT. 版本2.0.1-beta引入。 
     </dd><dt> 
      <code>COLLATION_CONNECTION = collation_name</code> 
     </dt><dd>
       Selects the collation to be used for ORDER BY or GROUP BY on string values in the subsequent queries. Refer to&nbsp; 
      <a href="#collations">第&nbsp;5.12&nbsp;节 “字符串排序规则”</a>&nbsp;for a list of known collation names. 版本2.0.1-beta引入。 
     </dd><dt> 
      <code>CHARACTER_SET_RESULTS = charset_name</code> 
     </dt><dd>
       Does nothing; a placeholder to support frameworks, clients, 

and connectors that attempt to automatically enforce a charset when
connecting to a Sphinx server. 版本2.0.1-beta引入。

     </dd></dl><p>&nbsp;</p><p>Known global server variables are:</p><dl><dt> 
      <code>QUERY_LOG_FORMAT = {plain | sphinxql}</code> 
     </dt><dd>
       Changes the current log format. 版本2.0.1-beta引入。 
     </dd><dt> 
      <code>LOG_LEVEL = {info | debug | debugv | debugvv}</code> 
     </dt><dd>
       Changes the current log verboseness level. 版本2.0.1-beta引入。 
     </dd></dl><p>&nbsp;</p><p>Examples:</p><pre><code>mysql&gt; SET autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL query_<span><span>log</span></span>_format=sphinxql;
Query OK, 0 rows affected (0.00 sec)</pre><p> </p><h2>7.8. BEGIN, COMMIT, 以及 ROLLBACK(事务处理)语法</h2><pre><span><span>START</span></span> <span><span>TRANSACTION</span></span> | <span><span>BEGIN</span></span>
<span><span>COMMIT</span></span>
<span><span>ROLLBACK</span></span>
<span><span>SET</span></span> AUTOCOMMIT = {<span><span>0</span></span> | <span><span>1</span></span>}
</pre><p>BEGIN, COMMIT, and ROLLBACK statements were 版本2.0.1-beta引入。
BEGIN statement (or its START TRANSACTION alias) forcibly commits
pending transaction, if any, and begins a new one. COMMIT statement
commits the current transaction, making all its changes permanent.
ROLLBACK statement rolls back the current transaction, canceling all its
changes. SET AUTOCOMMIT controls the autocommit mode in the active
session.</p><p>AUTOCOMMIT is set to 1 by default, meaning that every
statement that perfoms any changes on any index is implicitly wrapped in
BEGIN and COMMIT.</p><p>Transactions are limited to a single RT index, and also
limited in size. They are atomic, consistent, overly isolated, and
durable. Overly isolated means that the changes are not only invisible
to the concurrent transactions but even to the current session itself.</p><h2>7.9. CALL SNIPPETS(摘要生成)语法</h2><pre><span><span>CALL</span></span> SNIPPETS(<span><span>data</span></span>, <span><span>index</span></span>, <span><span>query</span></span>[, opt_value <span><span>AS</span></span> opt_name[, ...]])</pre><p>CALL SNIPPETS statement, introduced in version 1.10-beta,
builds a snippet from provided data and query, using specified index
settings.</p><p>data is the source data string to extract a snippet from. index is the name of the index from which to take the text processing settings. query is the full-text query to build snippets for. Additional options are documented in 第 8.7.1 节 “BuildExcerpts (产生文本摘要和高亮)”. Usage example:</p><pre><span><span>CALL</span></span> SNIPPETS(<span><span>'this is my document text'</span></span>, <span><span>'test1'</span></span>, <span><span>'hello world'</span></span>,
<span><span>5</span></span> <span><span>AS</span></span> around, <span><span>200</span></span> <span><span>AS</span></span> <span><span>limit</span></span>)
</pre><h2>7.10. CALL KEYWORDS(关键词生成)语法</h2><pre><span><span>CALL</span></span> KEYWORDS(<span><span>text</span></span>, <span><span>index</span></span>, [hits])</pre><p>CALL KEYWORDS statement, introduced in version 1.10-beta,
splits text into particular keywords. It returns tokenized and
normalized forms of the keywords, and, optionally, keyword statistics.</p><p>text is the text to break down to keywords. index is the name of the index from which to take the text processing settings. hits is an optional boolean parameter that specifies whether to return document and hit occurrence statistics.</p><h2>7.11. SHOW TABLES(显示当前提供搜索服务的索引列表)语法</h2><pre><span><span>SHOW</span></span> <span><span>TABLES</span></span></pre><p>SHOW TABLES statement, introduced in version 2.0.1-beta,
enumerates all currently active indexes along with their types. As of

2.0.1-beta, existing index types are local, distributed, and rtrespectively. Example:</p><pre>mysql> SHOW TABLES;
<span><span>Index</span></span> Type <span><span>
</span></span> dist1 <span><span>distributed</span></span>
<span><span>rt</span></span> rt <span><span>
</span></span> test1 <span><span>local</span></span>
<span><span>test2</span></span> local <span><span>
4 rows </span><span><span><span>in</span></span></span><span> set (0.00 sec)</span></span></pre><p> </p><h2>7.12. DESCRIBE(显示指定搜索服务索引的字段信息)语法</h2><pre><span></span><span><span></span><span>{DESCDESCRIBE}</span></span><span><span> index</span></span></pre><p>DESCRIBE statement, introduced in version 2.0.1-beta, lists

index columns and their associated types. Columns are document ID,
full-text fields, and attributes. The order matches that in which fields
and attributes are expected by INSERT and REPLACE statements. As of

2.0.1-beta, column types are field, integer, timestamp, ordinal, bool, float, bigint, string, and mva. ID column will be typed either integer or bigint based on whether the binaries were built with 32-bit or 64-bit document ID support. Example:</p><pre>mysql> DESC rt;
<span><span>Field</span></span> Type <span><span>
</span></span> id <span><span>integer</span></span>
<span><span>title</span></span> field <span><span>
</span></span> content <span><span>field</span></span>
<span><span>gid</span></span> integer <span><span>

4 rows </span><span><span><span>in</span></span></span><span> set (0.00 sec)</span></span></pre><h2>7.13. CREATE FUNCTION(添加自定义函数)语法</h2><pre><span><span>CREATE</span></span> <span><span>FUNCTION</span></span> udf_name
<span><span>RETURNS</span></span> {<span><span>INT</span></span> | <span><span>BIGINT</span></span> | <span><span>FLOAT</span></span>}
<span><span>SONAME</span></span> <span><span>'udf_lib_file'</span></span>
</pre><p>CREATE FUNCTION statement, introduced in version 2.0.1-beta, installs a user-defined function (UDF) with the given name and type from the given library file. The library file must reside in a trusted plugin_dir directory. On success, the function is available for use in all subsequent queries that the server receives. Example:</p><pre>mysql> CREATE FUNCTION avgmva RETURNS INT SONAME <span><span>'udfexample.dll'</span></span>;
Query OK, <span><span>0</span></span> rows affected (<span><span>0</span></span>.<span><span>03</span></span> sec)

mysql> SELECT *, AVGMVA(tag) AS q from test1;
<span><span>id</span></span> weight <span><span>tag</span></span> q <span><span>
</span></span> <span><span>1</span></span> <span><span>1</span></span> <span><span>1</span></span>,<span><span>3</span></span>,<span><span>5</span></span>,<span><span>7</span></span> <span><span>4.000000</span></span>
<span><span>2</span></span> <span><span>1</span></span> <span><span>2,4,6</span></span> <span><span>4.000000</span></span> <span><span>
</span></span> <span><span>3</span></span> <span><span>1</span></span> <span><span>15</span></span> <span><span>15.000000</span></span>
<span><span>4</span></span> <span><span>1</span></span> <span><span>7,40</span></span> <span><span>23.500000</span></span> <span><span>

+------+--------+---------+-----------+</span></span></pre><h2>7.14. DROP FUNCTION(删除自定义函数)语法</h2><pre><span><span>DROP</span></span> <span><span>FUNCTION</span></span> udf_name</pre><p>DROP FUNCTION statement, introduced in version 2.0.1-beta, deinstalls a user-defined function (UDF) with
the given name. On success, the function is no longer available for use
in subsequent queries. Pending concurrent queries will not be affected
and the library unload, if necessary, will be postponed until those
queries complete. Example:</p><pre>mysql> DROP <span><span><span><span>FUNCTION</span></span></span><span> </span><span><span><span>avgmva</span></span></span></span>;
Query OK, <span><span>0</span></span> rows affected (<span><span>0.00</span></span> sec)
</pre><h2>7.15. SHOW VARIABLES(显示服务器端变量)语法</h2><pre><span><span>SHOW</span></span> <span><span>VARIABLES</span></span></pre><p>Added in version 2.0.1-beta, this is currently a placeholder
query that does nothing and reports success. That is in order to keep
compatibility with frameworks and connectors that automatically execute
this statement.</p><pre><span><span>mysql</span></span>> <span><span>SHOW</span></span> <span><span>VARIABLES</span></span>;
<span><span>Query</span></span> <span><span>OK</span></span>, 0 <span><span>rows</span></span> <span><span>affected</span></span> (0<span><span>.00</span></span> <span><span>sec</span></span>)
</pre><h2>7.16. SHOW COLLATION(显示字符集校对)语法</h2><pre><span><span>SHOW</span></span> <span><span>COLLATION</span></span></pre><p>Added in version 2.0.1-beta, this is currently a placeholder
query that does nothing and reports success. That is in order to keep
compatibility with frameworks and connectors that automatically execute
this statement.</p><pre><span><span>mysql</span></span>> <span><span>SHOW</span></span> <span><span>COLLATION</span></span>;
<span><span>Query</span></span> <span><span>OK</span></span>, 0 <span><span>rows</span></span> <span><span>affected</span></span> (0<span><span>.00</span></span> <span><span>sec</span></span>)
</pre><h2>7.17. UPDATE(数据更新)语法</h2><pre><span><span>UPDATE</span></span> <span><span>index</span></span> <span><span>SET</span></span> col1 = newval1 [, ...] <span><span>WHERE</span></span> <span><span>ID</span></span> = docid</pre><p>UPDATE statement was added in version 2.0.1-beta. It can
currently update 32-bit integer attributes only. Multiple attributes and
values can be specified. Both RT and disk indexes are supported.
Updates on other attribute types are also planned.</p><pre>mysql> UPDATE myindex SET enabled=<span><span>0</span></span> WHERE <span><span>id</span></span>=<span><span>123</span></span>;
Query OK, <span><span>1</span></span> rows affected (<span><span>0.00</span></span> sec)
</pre><h2>7.18. 多结果集查询(批量查询)</h2><p>Starting version 2.0.1-beta, SphinxQL supports multi-statement
queries, or batches. Possible inter-statement optimizations described
in 第 5.11 节 “批量查询” do
apply to SphinxQL just as well. The batched queries should be separated
by a semicolon. Your MySQL client library needs to support MySQL
multi-query mechanism and multiple result set. For instance, mysqli
interface in PHP and DBI/DBD libraries in Perl are known to work.</p><p>Here’s a PHP sample showing how to utilize mysqli interface with Sphinx.</p><pre><?php

$link = mysqli_connect ( <span><span>"127.0.0.1"</span></span>, <span><span>"root"</span></span>, <span><span>""</span></span>, <span><span>""</span></span>, <span><span>9306</span></span> );
<span><span>if</span></span> ( mysqli_connect_errno() )
<span><span>die</span></span> ( <span><span>"connect failed: "</span></span> . mysqli_connect_error() );

$batch = <span><span>"SELECT * FROM test1 ORDER BY group_id ASC;"</span></span>;
$batch .= <span><span>"SELECT * FROM test1 ORDER BY group_id DESC"</span></span>;

<span><span>if</span></span> ( !mysqli_multi_query ( $link, $batch ) )
<span><span>die</span></span> ( <span><span>"query failed"</span></span> );

<span><span>do</span></span>
{
<span><span>//</span></span> fetch <span><span>and</span></span> <span><span>print</span></span> result set
<span><span>if</span></span> ( $result = mysqli_store_result($link) )
{
<span><span>while</span></span> ( $row = mysqli_fetch_row($result) )
<span><span>printf</span></span> ( <span><span>"id=%s\n"</span></span>, $row[<span><span>0</span></span>] );
mysqli_free_result($result);
}

// <span><span>print</span></span> divider
<span><span>if</span></span> ( mysqli_more_results($link) )
<span><span>printf</span></span> ( <span><span>"------\n"</span></span> );

} <span><span>while</span></span> ( mysqli_next_result($link) );</code></pre><p>Its output with the sample&nbsp;test1&nbsp;index included with Sphinx is as follows.</p><pre><code>$ php test_multi.php
<span><span>id</span></span>=<span><span>1</span></span>
<span><span>id</span></span>=<span><span>2</span></span>
<span><span>id</span></span>=<span><span>3</span></span>

<span><span>id</span></span>=<span><span>4</span></span>

<span><span>id</span></span>=<span><span>3</span></span>
<span><span>id</span></span>=<span><span>4</span></span>
<span><span>id</span></span>=<span><span>1</span></span>
<span><span>id</span></span>=<span><span>2</span></span>
</pre><p> </p><p>The following statements can currently be used in a batch:
SELECT, SHOW WARNINGS, SHOW STATUS, and SHOW META. Arbitrary sequence of
these statements are allowed. The results sets returned should match
those that would be returned if the batched queries were sent one by
one.</p><h2>7.19. COMMIT(注释)语法</h2><p>Since version 2.0.1-beta, SphinxQL supports C-style comment syntax. Everything from an opening / sequence to a closing / sequence is ignored. Comments can span multiple lines, can not nest, and should not get logged. MySQL specific /! ... / comments are also currently ignored. (As the comments support was rather added for better compatibility withmysqldump produced dumps, rather than improving generaly query interoperability between Sphinx and MySQL.)</p><pre><span><span>SELECT</span></span> <span><span>/! SQL_CALC_FOUND_ROWS /</span></span> col1 <span><span>FROM</span></span> table1 <span><span>WHERE</span></span> ...</pre><p> </p><h2>7.20. SphinxQL 保留关键字列表</h2><p>A complete alphabetical list of keywords that are currently
reserved in SphinxQL syntax (and therefore can not be used as
identifiers).</p><pre>AND
AS
ASC
AVG
<span><span>BEGIN</span></span>
<span><span>BETWEEN</span></span>
<span><span>BY</span></span>
<span><span>CALL</span></span>
<span><span>COLLATION</span></span>
<span><span>COMMIT</span></span>
<span><span>COUNT</span></span>
<span><span>DELETE</span></span>
<span><span>DESC</span></span>
<span><span>DESCRIBE</span></span>
<span><span>DISTINCT</span></span>
<span><span>FALSE</span></span>
<span><span>FROM</span></span>
<span><span>GLOBAL</span></span>
<span><span>GROUP</span></span>
<span><span>ID</span></span>
<span><span>IN</span></span>
<span><span>INSERT</span></span>
<span><span>INTO</span></span>
<span><span>LIMIT</span></span>
<span><span>MATCH</span></span>
<span><span>MAX</span></span>
META
<span><span>MIN</span></span>
<span><span>NOT</span></span>
<span><span>NULL</span></span>
<span><span>OPTION</span></span>
<span><span>OR</span></span>
<span><span>ORDER</span></span>
<span><span>REPLACE</span></span>
<span><span>ROLLBACK</span></span>
<span><span>SELECT</span></span>
<span><span>SET</span></span>
<span><span>SHOW</span></span>
<span><span>START</span></span>
<span><span>STATUS</span></span>
<span><span>SUM</span></span>
<span><span>TABLES</span></span>
<span><span>TRANSACTION</span></span>
<span><span>TRUE</span></span>
<span><span>UPDATE</span></span>
<span><span>VALUES</span></span>
<span><span>VARIABLES</span></span>
<span><span>WARNINGS</span></span>
WEIGHT
<span><span>WHERE</span></span>
<span><span>WITHIN</span></span>
</pre><h2>7.21. SphinxQL 升级备注, version 2.0.1-beta</h2><p>This section only applies to existing applications that use SphinxQL versions prior to 2.0.1-beta.</p><p>In previous versions, SphinxQL just wrapped around SphinxAPI
and inherited its magic columns and column set quirks. Essentially,
SphinxQL queries could return (slightly) different columns and in a
(slightly) different order than it was explicitly requested in the
query. Namely, weight magic column (which is not a real column in any index) was added at all times, and GROUP BY related @count@group , and @distinct magic
columns were conditionally added when grouping. Also, the order of
columns (attributes) in the result set was actually taken from the index
rather than the query. (So if you asked for columns C, B, A in your
query but they were in the A, B, C order in the index, they would have
been returned in the A, B, C order.)</p><p>In version 2.0.1-beta, we fixed that. SphinxQL is now more SQL
compliant (and will be further brought in as much compliance with
standard SQL syntax as possible). That is not yet a breaking change,
because searchd now supports compat_sphinxql_magics directive
that flips between the old “compatibility” mode and the new
“compliance” mode. However, the compatibility mode support is going to
be removed in future, so it’s strongly advised to update SphinxQL
applications and switch to the compliance mode.</p><p>The important changes are as follows:</p><ul><li>@ID magic name is deprecated in favor of ID. Document ID is considered an attribute.</li><li>WEIGHT is no longer implicitly returned,
because it is not actually a column (an index attribute), but rather an
internal function computed per each row (a match). You have to
explicitly ask for it, using the WEIGHT() function. (The requirement to alias the result will be lifted in the next release.)SELECT id, WEIGHT() w FROM myindex WHERE MATCH('test')   </li><li>You can now use quoted reserved keywords as aliases. The quote character is backtick (“”, ASCII code 96 decimal, 60 hex). One particularly useful example would be returningweight&nbsp;column like the old mode:SELECT id, WEIGHT() weight` FROM myindex WHERE MATCH('test')   </li><li>The column order is now different and should now match the
one expliclitly defined in the query. So if you are accessing columns
based on their position in the result set rather than the name (for
instance, by using mysql_fetch_row() rather than mysql_fetch_assoc() in PHP), check and fix the order of columns in your queries.</li><li>SELECT  return the columns in index order, as it used to, including the ID column. However, SELECT  does not automatically return WEIGHT(). To update such queries in case you access columns by names, simply add it to the query:SELECT , WEIGHT() weight FROM myindex WHERE MATCH('test') Otherwise, i.e., in case you rely on column order, select ID, weight, and then other columns: SELECT id, , WEIGHT() weight FROM myindex WHERE MATCH('test')   </li><li>Magic @count  and @distinct attributes are no longer implicitly returned.
You now have to explicitly ask for them when using GROUP BY. (Also note
that you currently have to alias them; that requirement will be lifted
in the future.)SELECT gid, COUNT(*) q FROM myindex WHERE MATCH('test')
GROUP BY gid ORDER BY q DESC   </li></ul><p> </p><h2>第 8 章 API参考</h2><p>目录</p><dl><dt>

     <a href="#api-funcgroup-general">8.1. 通用API方法</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-getlasterror">8.1.1. GetLastError (错误信息)</a> 
      </dt><dt> 
       <a href="#api-func-getlastwarning">8.1.2. GetLastWarning (告警信息)</a> 
      </dt><dt> 
       <a href="#api-func-setserver">8.1.3. SetServer (设置搜索服务)</a> 
      </dt><dt> 
       <a href="#api-func-setretries">8.1.4. SetRetries (设置失败重试)</a> 
      </dt><dt> 
       <a href="#api-func-setconnecttimeout">8.1.5. SetConnectTimeout (设置超时时间)</a> 
      </dt><dt> 
       <a href="#api-func-setarrayresult">8.1.6. SetArrayResult (设置结果返回格式)</a> 
      </dt><dt> 
       <a href="#api-func-isconnecterror">8.1.7. IsConnectError (检查链接错误)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-general-query-settings">8.2. 通用搜索设置</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-setlimits">8.2.1. SetLimits (设置结果集偏移量)</a> 
      </dt><dt> 
       <a href="#api-func-setmaxquerytime">8.2.2. SetMaxQueryTime (设置最大搜索时间)</a> 
      </dt><dt> 
       <a href="#api-func-setoverride">8.2.3. SetOverride (设置临时属性值覆盖)</a> 
      </dt><dt> 
       <a href="#api-func-setselect">8.2.4. SetSelect (设置返回信息的内容)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-fulltext-query-settings">8.3. 全文搜索设置</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-setmatchmode">8.3.1. SetMatchMode (设置匹配模式)</a> 
      </dt><dt> 
       <a href="#api-func-setrankingmode">8.3.2. SetRankingMode (设置评分模式)</a> 
      </dt><dt> 
       <a href="#api-func-setsortmode">8.3.3. SetSortMode (设置排序模式)</a> 
      </dt><dt> 
       <a href="#api-func-setweights">8.3.4. SetWeights (设置权重)</a> 
      </dt><dt> 
       <a href="#api-func-setfieldweights">8.3.5. SetFieldWeights (设置字段权重)</a> 
      </dt><dt> 
       <a href="#api-func-setindexweights">8.3.6. SetIndexWeights (设置索引权重)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-filtering">8.4. 结果集过滤设置</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-setidrange">8.4.1. SetIDRange (设置查询ID范围)</a> 
      </dt><dt> 
       <a href="#api-func-setfilter">8.4.2. SetFilter (设置属性过滤)</a> 
      </dt><dt> 
       <a href="#api-func-setfilterrange">8.4.3. SetFilterRange (设置属性范围)</a> 
      </dt><dt> 
       <a href="#api-func-setfilterfloatrange">8.4.4. SetFilterFloatRange (设置浮点数范围)</a> 
      </dt><dt> 
       <a href="#api-func-setgeoanchor">8.4.5. SetGeoAnchor (设置地表距离锚点)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-groupby">8.5. 分组设置</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-setgroupby">8.5.1. SetGroupBy (设置分组的属性)</a> 
      </dt><dt> 
       <a href="#api-func-setgroupdistinct">8.5.2. SetGroupDistinct (设置分组计算不同值的属性)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-querying">8.6. 搜索数据</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-query">8.6.1. Query (查询)</a> 
      </dt><dt> 
       <a href="#api-func-addquery">8.6.2. AddQuery (增加批量查询)</a> 
      </dt><dt> 
       <a href="#api-func-runqueries">8.6.3. RunQueries (执行批量查询)</a> 
      </dt><dt> 
       <a href="#api-func-resetfilters">8.6.4. ResetFilters (清除当前设置的过滤器)</a> 
      </dt><dt> 
       <a href="#api-func-resetgroupby">8.6.5. ResetGroupBy (清除现有的分组设置)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-additional-functionality">8.7. 附加方法</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-buildexcerpts">8.7.1. BuildExcerpts (产生文本摘要和高亮)</a> 
      </dt><dt> 
       <a href="#api-func-updateatttributes">8.7.2. UpdateAttributes (更新属性)</a> 
      </dt><dt> 
       <a href="#api-func-buildkeywords">8.7.3. BuildKeywords (获取分词结果)</a> 
      </dt><dt> 
       <a href="#api-func-escapestring">8.7.4. EscapeString (转义特殊字符)</a> 
      </dt><dt> 
       <a href="#api-func-status">8.7.5. Status (查询服务状态)</a> 
      </dt><dt> 
       <a href="#api-func-flushattributes">8.7.6. FlushAttributes (强制更新属性到磁盘)</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#api-funcgroup-pconn">8.8. 持久连接</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#api-func-open">8.8.1. Open (打开连接)</a> 
      </dt><dt> 
       <a href="#api-func-close">8.8.2. Close (关闭连接)</a> 
      </dt></dl> 
    </dd></dl><p>Sphnix有几种不同编程语言的原生searchd客户端API的实现。在本文完成之时,我们对我们自己开发的PHP,Python和java客户端实现提供官方支持。此外,也有一些针对Perl,Ruby和C++的第三方免费、开源API实现。</p><p>API的参考实现是用PHP写成的,因为(我们相信)较之其他语言,Sphinx在PHP中应用最广泛。因此这份参考文档基于PHP API的参考,而且这节中的所有的代码样例都用PHP给出。</p><p>当然,其他所有API都提供相同的方法,也使用完全相同的网络协议。因此这份文档对他们同样适用。在方法命名习惯方面或者具体数据结构的使用上可能会有小的差别。但不同语言的API提供的功能上绝不会有差异。</p><h2>8.1.&nbsp;通用API方法</h2><h3>8.1.1.&nbsp;GetLastError (错误信息)</h3><p>原型:&nbsp;function GetLastError()</p><p>以可读形式返回最近的错误描述信息。如果前一次API调用没有错误,返回空字符串。</p><p>任何其他函数(如&nbsp;<a href="#api-func-query">Query()</a>)失败后(函数失败一般返回false),都应该调用这个函数,它将返回错误的描述。</p><p>此函数本身并不重置对错误描述,因此如有必要,可以多次调用。</p><h3>8.1.2.&nbsp;GetLastWarning (告警信息)</h3><p>原型:&nbsp;function GetLastWarning ()</p><p>以可读格式返回最近的警告描述信息。如果前一次API调用没有警告,返回空字符串。</p><p>您应该调用这个函数来确认您的请求(如&nbsp;<a href="#api-func-query">Query()</a>)是否虽然完成了但产生了警告。例如,即使几个远程代理超时了,对分布式索引的搜索查询也可能成功完成。这时会产生一个警告信息。</p><p>此函数本身不会重置警告信息,因此如有必要,可以多次调用。</p><h3>8.1.3.&nbsp;SetServer (设置搜索服务)</h3><p>原型:&nbsp;function SetServer ( $host, $port )</p><p>设置searchd的主机名和TCP端口。此后的所有请求都使用新的主机和端口设置。默认的主机和端口分别是“localhost”和9312。</p><h3>8.1.4.&nbsp;SetRetries (设置失败重试)</h3><p>原型:&nbsp;function SetRetries ( $count, $delay=0 )</p><p>设置分布式搜索重试的次数和延迟时间。</p><p>对于暂时的失败,searchd对每个代理重试至多$count次。$delay是两次重试之间延迟的时间,以毫秒为单位。默认情况下,重试是禁止的。注意,这个调用不会使API本身对暂时失败进行重试,它只是让searchd这样做。目前暂时失败包括connect()调用的各种失败和远程代理超过最大连接数(过于繁忙)的情况。</p><h3>8.1.5.&nbsp;SetConnectTimeout (设置超时时间)</h3><p>原型:&nbsp;function SetConnectTimeout ( $timeout )</p><p>设置连接超时时间,在与服务器连接时,如果超过这个时间没有连上就放弃。</p><p>有时候服务器在响应上会有所延迟,这有可能由于网络的延时,也有可能是因为服务器未处理完的查询太多,堆积所致。不管是什么情况,有了这个选项,就给客户端应用程序提供了一定的控制权,让它可以决定当searchd不可用的时候如何处理,而且可以避免脚本由于超过运行限制而运行失败(尤其是在PHP里)</p><p>当连接失败的而时候,会将合适的错误码返回给应用程序,以便在应用程序级别进行错误处理和通知用户。</p><h3>8.1.6.&nbsp;SetArrayResult (设置结果返回格式)</h3><p>原型:&nbsp;function SetArrayResult ( $arrayresult )</p><p>PHP专用。控制搜索结果集的返回格式(匹配项按数组返回还是按hash返回)</p><p>$arrayresult&nbsp;参数应为布尔型。如果$arrayresult为false(默认),匹配项以PHP hash格式返回,文档ID为键,其他信息(权重、属性)为值。如果$arrayresult为true,匹配项以普通数组返回,包括匹配项的全部信息(包含文档ID)。</p><p>这个调用是对MVA属性引入分组支持时同时引入的。对MVA分组的结果可能包含重复的文档ID。因此需要将他们按普通数组返回,因为hash对每个文档ID仅能保存一个记录。</p><h3>8.1.7.&nbsp;IsConnectError (检查链接错误)</h3><p>原型:&nbsp;function IsConnectError ()</p><p>检查上一个错误是API层面的网络错误还是searchd返回的远程错误。如果是上一次连接searchd的尝试在API层面失败了,返回真,否则返回假(错误发生在远程,或者根本没有尝试连接)。 这是在版本0.9.9-rc1引入的。</p><h2>8.2.&nbsp;通用搜索设置</h2><h3>8.2.1.&nbsp;SetLimits (设置结果集偏移量)</h3><p>原型:&nbsp;function SetLimits ( $offset, $limit, $max_matches=0, $cutoff=0 )</p><p>给服务器端结果集设置一个偏移量($offset)和从那个偏移量起向客户端返回的匹配项数目限制($limit)。并且可以在服务器端设定当前查询的结果集大小($max_matches),另有一个阈值($cutoff),当找到的匹配项达到这个阀值时就停止搜索。全部这些参数都必须是非负整数。</p><p>前两个参数的行为与MySQL LIMIT子句中参数的行为相同。他们令searchd从编号为$offset的匹配项开始返回最多$limit个匹配项。偏移量($offset)和结果数限制($limit)的默认值分别是0和20,即返回前20个匹配项。</p><p>max_matches这个设置控制搜索过程中searchd在内存中所保持的匹配项数目。一般来说,即使设置了max_matches为1,全部的匹配文档也都会被处理、评分、过滤和排序。但是任一时刻只有最优的N个文档会被存储在内存中,这是为了性能和内存使用方面的原因,这个设置正是控制这个N的大小。注意,max_matches在两个地方设置。针对单个查询的限制由这个API调用指定。但还有一个针对整个服务器的限制,那是由配置文件中的max_matches设置控制的。为防止滥用内存,服务器不允许单个查询的限制高于服务器的限制。</p><p>在客户端不可能收到超过max_matches个匹配项。默认的限制是1000,您应该不会遇到需要设置得更高的情况。1000个记录足够向最终用户展示了。如果您是想将结果传输给应用程序以便做进一步排序或过滤,那么请注意,在Sphinx端完成效率要高得多。</p><p>$cutoff设置是为高级性能优化而提供的。它告诉searchd&nbsp;在找到并处理$cutoff个匹配后就强制停止。</p><h3>8.2.2.&nbsp;SetMaxQueryTime (设置最大搜索时间)</h3><p>原型:&nbsp;function SetMaxQueryTime ( $max_query_time )</p><p>设置最大搜索时间,以毫秒为单位。参数必须是非负整数。默认值为0,意思是不做限制。</p><p>这个设置与<a href="#api-func-setlimits">SetLimits()</a>中的$cutoff相似,不过这个设置限制的是查询时间,而不是处理的匹配数目。一旦处理时间已经太久,本地搜索查询会被停止。注意,如果一个搜索查询了多个本地索引,那这个限制独立地作用于这几个索引。</p><h3>8.2.3.&nbsp;SetOverride (设置临时属性值覆盖)</h3><p>原型:&nbsp;function SetOverride ( $attrname, $attrtype, $values )</p><p>设置一个临时的(只对单个查询有效)针对不同文档的属性值覆盖。只支持标量属性。$value是一个哈希表,他的键是要覆盖属性的文档ID,之是对应该文档ID的要覆盖的值。 于版本0.9.9-rc1引入。</p><p>属性覆盖特性使用户可以针对一次查询“临时性地”修改一些文档的值,不影响其他查询。这个函数可以用来进行数据个性化。例如,假设正在实现一个个性

化搜索函数,用来将朋友推荐的帖子排在前面,这类数据不仅是动态的,而且是个性化的,因此不能简单地把这种数据放入索引,因为不能影响其他用户的搜索。而
覆盖机制是针对单个查询的,不会影响其他人。因此可以,比如说,给每个文档设置一个“friends_weight”属性,默认值是0,然后临时将文档
123,456,789(当前用户的朋友推荐的)的这个属性设置为1,最后用这个值进行相关度计算。</p><h3>8.2.4. SetSelect (设置返回信息的内容)</h3><p>原型: function SetSelect ( $clause )</p><p>设置select子句,列出具体要取出的属性以及要计算并取出的expressions。子句的语法模仿了SQL。于版本0.9.9-rc1引入。</p><p>SetSelect()于标准SQL查询中SELECT和FROM之间的部分非常相近。它允许你指定要取出哪些属性(列),以及在这些列上要计算和

取出哪些表达式。与SQL语言的区别是,表达式必须用关键字AS给每个表达式取一个别名,别名必须是有效的标识符(由字母和数字组成)。在SQL里面可以
这样做,但是不是强制的。Sphinx强制必须有别名,以便计算结果总是可以以一个“正常”的名字在结果集中返回,或者在其他子句中引用,等等。</p><p>其他方面基本上等同于SQL。支持星号(“”),支持函数,支持任意数目的表达式。计算出的表达式可以用于排序、过滤和分组,这与其他常规属性相同。</p><p>从版本0.9.9-rc2开始,允许使用GROUP BY的时候使用聚集函数(AVG(), MIN(), MAX(), SUM())。</p><p>表达式排序(第 5.6 节 “SPH_SORT_EXPR 模式”)和地理距离计算函数(第 8.4.5 节 “SetGeoAnchor (设置地表距离锚点)”)现在的内部实现就是这种表达式计算机制,分别使用“魔法名字”“@expr”和“@geodist”。</p><h4>示例:</h4><pre>$cl->SetSelect ( <span><span>", @weight+(user_karma+ln(pageviews))*0.1 AS myweight"</span></span> );
$cl-&gt;SetSelect ( <span><span>"exp_years, salary_gbp*{$gbp_usd_rate} AS salary_usd,
IF(age>40,1,0) AS over40"</span></span> );
$cl-&gt;SetSelect ( <span><span>"*, AVG(price) AS avgprice"</span></span> );</code></pre><h2>8.3.&nbsp;全文搜索设置</h2><h3>8.3.1.&nbsp;SetMatchMode (设置匹配模式)</h3><p>原型:&nbsp;function SetMatchMode ( $mode )</p><p>设置全文查询的匹配模式,见第 5.1 节 “匹配模式”中的描述。参数必须是一个与某个已知模式对应的常数。</p><p>警告: (仅PHP)查询模式常量不能包含在引号中,那给出的是一个字符串而不是一个常量:</p><pre>$cl->SetMatchMode ( <span><span>"SPH_MATCH_ANY"</span></span> ); <span><span>// INCORRECT! will not work as expected</span></span>
$cl-&gt;SetMatchMode ( SPH_MATCH_ANY ); <span><span>// correct, works OK</span></span></code></pre><p>&nbsp;</p><h3>8.3.2.&nbsp;SetRankingMode (设置评分模式)</h3><p>原型:&nbsp;function SetRankingMode ( $ranker )</p><p>设置评分模式。目前只在SPH_MATCH_EXTENDED2这个匹配模式中提供。参数必须是与某个已知模式对应的常数。</p><p>Sphinx默认计算两个对最终匹配权重有用的因子。主要是查询词组与文档文本的相似度。其次是称之为BM25的统计函数,该函数值根据关键字文档中的频率(高频导致高权重)和在整个索引中的频率(低频导致高权重)在0和1之间取值。</p><p>然而,有时可能需要换一种计算权重的方法——或者可能为了提高性能而根本不计算权值,结果集用其他办法排序。这个目的可以通过设置合适的相关度计算模式来达到。</p><p>已经实现的模式包括:</p><ul><li>SPH_RANK_PROXIMITY_BM25, 默认模式,同时使用词组评分和BM25评分,并且将二者结合。</li><li>SPH_RANK_BM25, 统计相关度计算模式,仅使用BM25评分计算(与大多数全文检索引擎相同)。这个模式比较快,但是可能使包含多个词的查询的结果质量下降。</li><li>SPH_RANK_NONE, 禁用评分的模式,这是最快的模式。实际上这种模式与布尔搜索相同。所有的匹配项都被赋予权重1。</li><li>SPH_RANK_WORDCOUNT, 根据关键词出现次数排序。这个排序器计算每个字段中关键字的出现次数,然后把计数与字段的权重相乘,最后将积求和,作为最终结果。</li><li>SPH_RANK_PROXIMITY, 版本0.9.9-rc1新增,将原始的词组相似度作为结果返回。在内部,这个模式被用来模拟SPH_MATCH_ALL的查询。</li><li>SPH_RANK_MATCHANY, 版本0.9.9-rc1新增,返回之前在SPH_MATCH_ANY中计算的位次,在内部这个模式用于模拟SPH_MATCH_ANY的查询。</li><li>SPH_RANK_FIELDMASK, 版本0.9.9-rc2新增,返回一个32位掩码,其中第N位对应第N个全文字段,从0开始计数,如果某个字段中出现了满足查询的关键词,则对应的标志位被置1。</li><li>SPH_RANK_SPH04, 版本1.10-beta新增, 基本功能给予默认的
SPH_RANK_PROXIMITY_BM25 评分,
但是当他们在一段文本的最开始或者最后匹配时作了进一步处理。也就是说,当一个字段严格匹配查询时,相对于一个包含查询而非完全相同的字段,SPH04会
给予更高的评分。(例如,当查询为”Hyde Park”时,一篇名称为”Hyde Park”的文档取得的评分将高于一篇名称为 “Hyde
Park, London” 或者 “The Hyde Park Cafe”的文档。)</li></ul><p> </p><h3>8.3.3. SetSortMode (设置排序模式)</h3><p>原型: function SetSortMode ( $mode, $sortby=”" )</p><p>设置匹配项的排序模式,见第 5.6 节 “排序模式”中的描述。参数必须为与某个已知模式对应的常数。</p><p>警告: (仅PHP)查询模式常量不能包含在引号中,那给出的是一个字符串而不是一个常量:</p><pre>$cl->SetSortMode ( <span><span>"SPH_SORT_ATTR_DESC"</span></span> ); <span><span>// INCORRECT! will not work as expected</span></span>
$cl-&gt;SetSortMode ( SPH_SORT_ATTR_ASC ); <span><span>// correct, works OK</span></span></code></pre><p>&nbsp;</p><h3>8.3.4.&nbsp;SetWeights (设置权重)</h3><p>原型:&nbsp;function SetWeights ( $weights )</p><p>按在索引中出现的先后顺序给字段设置权重。 不推荐使用, 建议使用 SetFieldWeights()。</p><h3>8.3.5. SetFieldWeights (设置字段权重)</h3><p>原型: function SetFieldWeights ( $weights )</p><p>按字段名称设置字段的权值。参数必须是一个hash(关联数组),该hash将代表字段名字的字符串映射到一个整型的权值上。</p><p>字段权重影响匹配项的评级。<a href="#weighting">第&nbsp;5.4&nbsp;节 “权值计算”</a>&nbsp;解释了词组相似度如何影响评级。这个调用用于给不同的全文数据字段指定不同于默认值的权值。</p><p>给定的权重必须是正的32位整数。最终的权重也是个32位的整数。默认权重为1。未知的属性名会被忽略。</p><p>目前对权重没有强制的最大限制。但您要清楚,设定过高的权值可能会导致出现32位整数的溢出问题。例如,如果设定权值为10000000并在扩展模式中进行搜索,那么最大可能的权值为10M(您设的值)乘以1000(BM25的内部比例系数,参见<a href="#weighting">第&nbsp;5.4&nbsp;节 “权值计算”</a>, “权值计算”)再乘以1或更多(词组相似度评级)。上述结果最少是100亿,这在32位整数里面没法存储,将导致意想不到的结果。</p><h3>8.3.6.&nbsp;SetIndexWeights (设置索引权重)</h3><p>原型:&nbsp;function SetIndexWeights ( $weights )</p><p>设置索引的权重,并启用不同索引中匹配结果权重的加权和。参数必须为在代表索引名的字符串与整型权值之间建立映射关系的hash(关联数组)。默认值是空数组,意思是关闭带权加和。</p><p>当在不同的本地索引中都匹配到相同的文档ID时,Sphinx默认选择查询中指定的最后一个索引。这是为了支持部分重叠的分区索引。</p><p>然而在某些情况下索引并不仅仅是被分区了,您可能想将不同索引中的权值加在一起,而不是简单地选择其中的一个。SetIndexWeights()允许您这么做。当开启了加和功能后,最后的匹配权值是各个索引中的权值的加权合,各索引的权由本调用指定。也就是说,如果文档123在索引A被找到,权值是2,在B中也可找到,权值是3,而且您调用了SetIndexWeights ( array ( "A"=>100, "B"=>10 ) ),那么文档123最终返回给客户端的权值为2100+310 = 230。</p><h2>8.4. 结果集过滤设置</h2><h3>8.4.1. SetIDRange (设置查询ID范围)</h3><p>原型: function SetIDRange ( $min, $max )</p><p>设置接受的文档ID范围。参数必须是整数。默认是0和0,意思是不限制范围。</p><p>此调用执行后,只有ID在$min和$max(包括$min和$max)之间的文档会被匹配。</p><h3>8.4.2. SetFilter (设置属性过滤)</h3><p>原型: function SetFilter ( $attribute, $values, $exclude=false )</p><p>增加整数值过滤器。</p><p>此调用在已有的过滤器列表中添加新的过滤器。$attribute是属性名。$values是整数数组。$exclude是布尔值,它控制是接受匹配的文档(默认模式,即$exclude为false时)还是拒绝它们。</p><p>只有当索引中$attribute列的值与$values中的任一值匹配时文档才会被匹配(或者拒绝,如果$exclude值为true)</p><h3>8.4.3. SetFilterRange (设置属性范围)</h3><p>原型: function SetFilterRange ( $attribute, $min, $max, $exclude=false )</p><p>添加新的整数范围过滤器。</p><p>此调用在已有的过滤器列表中添加新的过滤器。$attribute是属性名,&nbsp;$min 、$max定义了一个整数闭区间,$exclude布尔值,它控制是接受匹配的文档(默认模式,即$exclude为false时)还是拒绝它们。</p><p>只有当索引中$attribute列的值落在$min&nbsp;和&nbsp;$max之间(包括$min&nbsp;和&nbsp;$max),文档才会被匹配(或者拒绝,如果$exclude值为true)。</p><h3>8.4.4.&nbsp;SetFilterFloatRange (设置浮点数范围)</h3><p>原型:&nbsp;function SetFilterFloatRange ( $attribute, $min, $max, $exclude=false )</p><p>增加新的浮点数范围过滤器。</p><p>此调用在已有的过滤器列表中添加新的过滤器。$attribute是属性名, $min&nbsp;、$max定义了一个浮点数闭区间,$exclude必须是布尔值,它控制是接受匹配的文档(默认模式,即$exclude为false时)还是拒绝它们。</p><p>只有当索引中$attribute列的值落在$min 和 $max之间(包括$min 和 $max),文档才会被匹配(或者拒绝,如果$exclude值为true)。</p><h3>8.4.5. SetGeoAnchor (设置地表距离锚点)</h3><p>原型: function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )</p><p>为地理距离计算设置锚点,并且允许使用它们。</p><p>$attrlat&nbsp;和&nbsp;$attrlong是字符串,分别指定了对应经度和纬度的属性名称。$lat&nbsp;和&nbsp;$long是浮点值,指定了锚点的经度和纬度值,以角度为单位。</p><p>一旦设置了锚点,您就可以在您的过滤器和/或排序表达式中使用"@geodist"特殊属性。Sphinx将在每一次全文检索中计算给定经纬度与锚点之前的地表距离,并把此距离附加到匹配结果上去。SetGeoAnchor和索引属性数据中的经纬度值都是角度。而结果会以米为单位返回,因此地表距离1000.0代表1千米。一英里大约是1609.344米。</p><h2>8.5. 分组设置</h2><h3>8.5.1. SetGroupBy (设置分组的属性)</h3><p>原型: function SetGroupBy ( $attribute, $func, $groupsort=”<a href="http://my.oschina.net/u/562020" target="_blank">@group</a> desc” )</p><p>设置进行分组的属性、函数和组间排序模式,并启用分组(参考<a href="#clustering">第&nbsp;5.7&nbsp;节 “结果分组(聚类)”</a>中的描述)。</p><p>$attribute是字符串,为进行分组的属性名。$func为常数,它指定内建函数,该
函数以前面所述的分组属性的值为输入,目前的可选的值为: SPH_GROUPBY_DAY、SPH_GROUPBY_WEEK、
SPH_GROUPBY_MONTH、 SPH_GROUPBY_YEAR、SPH_GROUPBY_ATTR 。 $groupsort&nbsp;是控制分组如何排序的子句。其语法与<a href="#sort-extended">第&nbsp;5.6&nbsp;节 “SPH_SORT_EXTENDED mode”</a>中描述的相似。</p><p>分组与SQL中的GROUP BY子句本质上相同。此函数调用产生的结果与下面伪代码产生的结果相同。</p><pre><code><span><span>SELECT</span></span> ... <span><span>GROUP</span></span> <span><span>BY</span></span> $func($<span><span>attribute</span></span>) <span><span>ORDER</span></span> <span><span>BY</span></span> $groupsort
</pre><p>注意,影响最终结果集中匹配项顺序的是$groupsort。排序模式(见<a href="#api-func-setsortmode">第&nbsp;8.3.3&nbsp;节 “SetSortMode (设置排序模式)”</a>)影响每个分组内的顺序,即每组内哪些匹配项被视为最佳匹配。比如,组之间可以根据每组中的匹配项数量排序的同时每组组内又根据相关度排序。</p><p>从版本 0.9.9-rc2 开始, 聚合函数 (AVG(), MIN(), MAX(), SUM()) 可以在GROUP BY时被&nbsp;<a href="#api-func-setselect">SetSelect()</a>&nbsp;API 调用。</p><p>从版本2.0.1-beta开始, 支持按照字符串属性分组(根据其当前字符集校对)。</p><h3>8.5.2.&nbsp;SetGroupDistinct (设置分组计算不同值的属性)</h3><p>原型:&nbsp;function SetGroupDistinct ( $attribute )</p><p>设置分组中需要计算不同取值数目的属性名。只在分组查询中有效。</p><p>$attribute是包含属性名的字符串。每个组的这个属性的取值都会被储存起来(只要内存允许),其后此属性在此组中不同值的总数会被计算出来并返回给客户端。这个特性与标准SQL中的COUNT(DISTINCT)子句类似。因此如下Sphinx调用</p><pre><code>$cl->SetGroupBy ( <span><span>"category"</span></span>, SPH_GROUPBY_ATTR, <span><span>"</span></span><span><span>@count</span></span><span><span> desc"</span></span> );
$cl->SetGroupDistinct ( <span><span>"vendor"</span></span> );
</pre><p>等价于如下的SQL语句:</p><pre><span><span>SELECT</span></span> <span><span>id</span></span>, weight, all-<span><span>attributes</span></span>,
<span><span>COUNT</span></span>(<span><span>DISTINCT</span></span> vendor) <span><span>AS</span></span> @<span><span>distinct</span></span>,
<span><span>COUNT</span></span>(*) <span><span>AS</span></span> @<span><span>count</span></span>
<span><span>FROM</span></span> products
<span><span>GROUP</span></span> <span><span>BY</span></span> <span><span>category</span></span>
<span><span>ORDER</span></span> <span><span>BY</span></span> @<span><span>count</span></span> <span><span>DESC</span></span>
</pre><p>在上述示例伪代码中,SetGroupDistinct()调用只与COUNT(DISINCT vendor)对应。GROUP BY,ORDER By和COUNT()子句则与SetGroupBY()调用等价。两个查询都会在每类中返回一个匹配的行。除了索引中的属性,匹配项还可以包含每类的匹配项计数和每类中不同来源 ID的计数。</p><h2>8.6. 搜索数据</h2><h3>8.6.1. Query (查询)</h3><p>原型: function Query ( $query, $index=””, $comment=”" )</p><p>连接到searchd服务器,根据服务器的当前设置执行给定的查询,取得并返回结果集。</p><p>$query是查询字串,$index是包含一个或多个索引名的字符串。一旦发生一般错误,则返回假并设置GetLastError()信息。若成功则返回搜索的结果集。 此外,&nbsp;$comment 将被发送到查询日志中搜索部分的前面,这对于调试是非常有用的。目前,注释的长度限制为128个字符以内。</p><p>$index的默认值是"*",意思是对全部本地索引做查询。索引名中允许的字符包括拉丁字母(a-z),数字(0-9),减号(-)和下划线(_),其他字符均视为分隔符。因此,下面的示例调用都是有效的,而且会搜索相同的两个索引:</p><pre><code>$cl->Query ( <span><span>"test query"</span></span>, <span><span>"main delta"</span></span> );
$cl->Query ( <span><span>"test query"</span></span>, <span><span>"main;delta"</span></span> );
$cl->Query ( <span><span>"test query"</span></span>, <span><span>"main, delta"</span></span> );
</pre><p>给出多个索引时索引的顺序是有意义的。如果同一个文档ID的文档在多个索引中找到,那么权值和属性值会取最后一个索引中所存储的作为该文档ID的权值和属性值,用于排序、过滤,并返回给客户端(除非用SetIndexWeights()显式改变默认行为)。因此在上述示例中,索引“delta”中的匹配项总是比索引“main”中的更优先。</p><p>如果搜索成功,Query()返回的结果集包含找到的全部匹配项中的一部分(根据SetLimits()之设定)和与查询相关的统计数据。结果集是hash(仅PHP,其他语言的API可能使用其他数据结构) ,包含如下键和值:</p><dl><dt>

        “matches”: 
      </dt><dd>
        是一个hash表,存储文档ID以及其对应的另一个包含文档权重和属性值的hash表(或者,如果启用了 
       <a href="#api-func-setarrayresult">SetArrayResult()</a>则返回数组)。 
      </dd><dt>
        “total”: 
      </dt><dd>
        本查询在 
       <em>搜索服务器</em>检索所得的匹配文档总数(即服务器端结果集的大小)。这是在当前设置下,用当前查询可以从服务器端获得的搜索结果(匹配文档)数目的上限。其最大限制值由 
       <a href="#api-func-setarrayresult">SetLimits()</a>设定。 
      </dd><dt>
        “total_found”: 
      </dt><dd>
        (搜索服务器上找到和处理了的)索引中匹配文档的总数。其与total的差别在于:total表示客户端实际可以读取的结果数目,而total_found仅表示服务器端存在多少匹配的文档(永远不会比total小)。 
      </dd><dt>
        “words”: 
      </dt><dd>
        hash表,它将查询关键字(关键字已经过大小写转换,取词干和其他处理)映射到一个包含关于关键字的统计数据(“docs”——在多少文档中出现,“hits”——共出现了多少次)的小hash表上。 
      </dd><dt>
        “error”: 
      </dt><dd> 
       <code>searchd</code>&nbsp;报告的错误信息(人性化可读的字符串)。若无错误则为空字符串。 
      </dd><dt>
        “warning”: 
      </dt><dd> 
       <code>searchd</code>报告的警告信息(人类可读字符串)。若无警告则为空串。 
      </dd></dl><p>&nbsp;</p><p>需要指出的是&nbsp;Query()&nbsp;索执行的操作,与没有中间步骤的&nbsp;AddQuery()和&nbsp;RunQueries()&nbsp;相同 ; 它类似一次单独的AddQuery()调用,紧跟一次相应的RunQueries()调用,然后返回匹配的第一个数组元素 (从第一次,也是仅有的一次查询返回)。</p><h3>8.6.2.&nbsp;AddQuery (增加批量查询)</h3><p>原型:&nbsp;function AddQuery ( $query, $index=”*”, $comment=”" )</p><p>向批量查询增加一个查询。$query为查询串。$index为包含一个或多个索引名的字符串。 此外, 如果提供了$comment,它 将被发送到查询日志中搜索部分的前面,这对于调试是非常有用的。目前,注释的长度限制为128个字符以内。返回<a href="#api-func-runqueries">RunQueries()</a>返回的数组中的一个下标。</p><p>批量查询(或多查询)使searchd能够进行可能的内部优化,并且无论在任何情况下都会减少网络连接和进程创建方面的开销。相对于单独的查询,批量查询不会引入任何额外的开销。因此当您的Web页运行几个不同的查询时,一定要考虑使用批量查询。</p><p>例如,多次运行同一个全文查询,但使用不同的排序或分组设置,这会使searchd仅运行一次开销昂贵的全文检索和相关度计算,然后在此基础上产生多个分组结果。</p><p>有时您不仅需要简单地显示搜索结果,而且要显示一些与类别相关的计数信息,例如按制造商分组后的产品数目,此时批量查询会节约大量的开销。若无批量

查询,您会必须将这些本质上几乎相同的查询运行多次并取回相同的匹配项,最后产生不同的结果集。若使用批量查询,您只须将这些查询简单地组成一个批量查
询,Sphinx会在内部优化掉这些冗余的全文搜索。</p><p>AddQuery()在内部存储全部当前设置状态以及查询,您也可在后续的AddQuery()调用中改变设置。早先加入的查询不会被影响,实际上没有任何办法可以改变它们。下面是一个示例:</p><pre>$cl->SetSortMode ( SPH_SORT_RELEVANCE );
$cl->AddQuery ( <span><span>"hello world"</span></span>, <span><span>"documents"</span></span> );

$cl->SetSortMode ( SPH_SORT_ATTR_DESC, <span><span>"price"</span></span> );
$cl->AddQuery ( <span><span>"ipod"</span></span>, <span><span>"products"</span></span> );

$cl->AddQuery ( <span><span>"harry potter"</span></span>, <span><span>"books"</span></span> );

$results = $cl->RunQueries ();</pre><p>用上述代码,第一个查询会在“documents”索引上查询“hello
world”并将结果按相关度排序,第二个查询会在“products”索引上查询“ipod”并将结果按价格排序,第三个查询在“books”索引上搜
索“harry potter”,结果仍按价格排序。注意,第二个SetSortMode()调用并不会影响第一个查询(因为它已经被添加了),但后面的两个查询都会受影响。</p><p>此外,在AddQuery()之前设置的任何过滤,都会被后续查询继续使用。因此,如果在第一个查询前使用SetFilter(),则通过AddQuery()执行的第二个查询(以及随后的批量查询)都会应用同样的过滤,除非你先调用ResetFilters()来清除过滤规则。同时,你还可以随时加入新的过滤规则</p><p>AddQuery()并不修改当前状态。也就是说,已有的全部排序、过滤和分组设置都不会因这个调用而发生改变,因此后续的查询很容易地复用现有设置。</p><p>AddQuery()返回RunQueries()结果返回的数组中的一个下标。它是一个从0开始的递增整数,即,第一次调用返回0,第二次返回1,以此类推。这个方便的特性使你在需要这些下标的时候不用手工记录它们。</p><h3>8.6.3. RunQueries (执行批量查询)</h3><p>原型: function RunQueries ()</p><p>连接到searchd,运行由AddQuery()添加的全部查询,获取并返回它们的结果集。若发生一般错误(例如网络I/O失败)则返回假并设置GetLastError()信息。若成功则返回结果集的简单数组。</p><p>该数组中的每一个结果集都跟Query()返回的结果集完全相同。</p><p>注意,批量查询请求自身几乎总是成功——除非有网络错误、正在进行索引轮换,或者其他导致整个查询无法被处理的因素。</p><p>然而其中的单个的查询很可能失败。此时与之对应的结果集只包含一个非空的"error"信息,而没有关于匹配或查询的统计信息。在极端情况下,批量查询中的所有单个查询可能都失败。但这仍然不会导致报告一般错误,因为API已经成功地连接到searchd,提交了批量查询并得到返回结果——但每个结果集都只包含特定的错误信息。</p><h3>8.6.4. ResetFilters (清除当前设置的过滤器)</h3><p>原型: function ResetFilters ()</p><p>清除当前设置的过滤器。</p><p>通常此调用在使用批量查询的时候会用到。您可能需要为批量查询中的不同查询提供不同的过滤器,为达到这个目的,您需要调用ResetFilters()然后用其他调用增加新的过滤器。</p><h3>8.6.5. ResetGroupBy (清除现有的分组设置)</h3><p>原型: function ResetGroupBy ()</p><p>清除现有的全部分组设置,并取消分组设定。</p><p>通常此调用在使用批量查询的时候会用到。单独的分组设置可以用SetGroupBy()和SetGroupDistinct()来改变,但它们不能关闭分组。ResetGroupBy()将之前的分组设置彻底重置并在当前状态下关闭分组模式,因此后续的AddQuery()可以进行无分组的搜索。</p><h2>8.7. 附加方法</h2><h3>8.7.1. BuildExcerpts (产生文本摘要和高亮)</h3><p>原型: function BuildExcerpts ( $docs, $index, $words, $opts=array() )</p><p>该函数用来产生文档片段(摘要)。连接到searchd,要求它从指定文档中产生片段(摘要),并返回结果。</p><p>$docs为包含各文档内容的数组。$index为包含索引名字的字符串。给定索引的不同设置(例如字符集、形态学、词形等方面的设置)会被使用。$words为包含需要高亮的关键字的字符串。它们会按索引的设置被处理。例如,如果英语取词干(stemming)在索引中被设置为允许,那么即使关键词是“shoe”,“shoes”这个词也会被高亮。从版本0.9.9-rc1开始,关键字可以包含通配符,与查询支持的<a href="#conf-enable-star">star-syntax</a>类似。$opts为包含其他可选的高亮参数的hash表:</p><dl><dt>

        “before_match”: 
      </dt><dd>
        在匹配的关键字前面插入的字符串。从版本 

1.10-beta开始,可以在该字符串中使用%PASSAGE_ID%宏。该宏会被替换为当前片段的递增值。递增值的起始值默认为1,但是可以通
过”start_passage_id”设置覆盖。在多文档中调用时,%PASSAGE_ID%会在每篇文档中重新开始。默认为”<b>”。

      </dd><dt>
        “after_match”: 
      </dt><dd>
        在匹配的关键字后面插入的字符串。从版本1.10-beta开始,可以在该字符串中使用%PASSAGE_ID%宏。默认为 “&lt;/b&gt;”。 
      </dd><dt>
        “chunk_separator”: 
      </dt><dd>
        在摘要块(段落)之间插入的字符串。默认为”&nbsp;…&nbsp;”. 
      </dd><dt>
        “limit”: 
      </dt><dd>
        摘要最多包含的符号(码点)数。整数,默认为256。 
      </dd><dt>
        “around”: 
      </dt><dd>
        每个关键词块左右选取的词的数目。整数,默认为 5. 
      </dd><dt>
        “exact_phrase”: 
      </dt><dd>
        是否仅高亮精确匹配的整个查询词组,而不是单独的关键词。布尔值,默认为false. 
      </dd><dt>
        “single_passage”: 
      </dt><dd>
        是否仅抽取最佳的一个区块。布尔值,默认为false. 
      </dd><dt>
        “use_boundaries”: 
      </dt><dd>
        是否跨越由 
       <a href="#conf-phrase-boundary">phrase_boundary</a>选项设置的词组边界符。布尔型,默认为false. 
      </dd><dt>
        “weight_order”: 
      </dt><dd>
        对于抽取出的段落,要么根据相关度排序(权重下降),要么根据出现在文档中的顺序(位置递增)。布尔型,默认是false. 
      </dd><dt>
        “query_mode”: 
      </dt><dd>
        版本1.10-beta新增。设置将$words当作&nbsp; 
       <a href="#extended-syntax">扩展查询语法</a>的

查询处理,还是当做普通的文本字符串处理(默认行为)。例如,在查询模式时,(“one two” | “three
four”)仅高亮和包含每个片段中出现”one two” 或 “three four” 的地方及相邻的部分。而在默认模式时,
每个单独出现”one”, “two”, “three”, 或 “four”的地方都会高亮。布尔型,默认是false。

      </dd><dt>
        “force_all_words”: 
      </dt><dd>
        版本1.10-beta新增. 忽略摘要的长度限制直至包含所有的词汇。布尔型,默认为false. 
      </dd><dt>
        “limit_passages”: 
      </dt><dd>
        版本1.10-beta新增. 限制摘要中可以包含的最大区块数。整数值,默认为 0 (不限制). 
      </dd><dt>
        “limit_words”: 
      </dt><dd>
        版本1.10-beta新增. 限制摘要中可以包含的最大词汇数。整数值,默认为 0 (不限制). 
      </dd><dt>
        “start_passage_id”: 
      </dt><dd>
        版本1.10-beta新增. 设置 %PASSAGE_ID% 宏的起始值 (在 
       <code>before_match</code>,&nbsp; 
       <code>after_match</code>&nbsp;字符串中检查和应用). 整数值,默认为1. 
      </dd><dt>
        “load_files”: 
      </dt><dd>
        版本1.10-beta新增. 设置是否将$docs作为摘要抽取来源的数据(默认行为),或者将其当做文件名。从版本2.0.1-beta开始,如果该标志启用,每个请求将创建最多 
       <a href="#conf-dist-threads">dist_threads</a>个工作线程进行并发处理。布尔型,默认为false. 
      </dd><dt>
        “html_strip_mode”: 
      </dt><dd>
        版本1.10-beta新增. 

HTML标签剥离模式设置。默认为”index”,表示使用index的设置。可以使用的其他值为”none”和”strip”,用于强制跳过或者应用剥

离,而不管索引如何设置的。还可以使用”retain”,表示保留HTMK标签并防止高亮时打断标签。”retain”模式仅用于需要高亮整篇文档,并且
不能设置限制片段的大小。字符型,可用值为”none”,”strip”,”index”或者”retain”。

      </dd><dt>
        “allow_empty”: 
      </dt><dd>
        版本1.10-beta新增. 允许无法产生摘要时将空字符串作为高亮结果返回 (没有关键字匹配或者不符合片段限制。). 默认情况下,原始文本的开头会被返回而不是空字符串。布尔型,默认为false. 
      </dd><dt>
        “passage_boundary”: 
      </dt><dd>
        版本2.0.1-beta新增. 确保区块不跨越句子,段落或者zone区域(仅当每个索引的设置启用时有效)。字符型,可用值为 “sentence”, “paragraph”, 或者 “zone”. 
      </dd><dt>
        “emit_zones”: 
      </dt><dd>
        版本2.0.1-beta新增. 在每个区块前使用区域对应的HTML标签来封闭区域。布尔型,魔默认为false。 
      </dd></dl><p>&nbsp;</p><p>摘要提取算法倾向于提取更好的片段(与关键词完全匹配),然后是不在摘要中但是包含了关键词的片段。 

通常情况下,它会尝试高亮查询的最佳匹配,并且在限制条件下尽可能的高亮查询中的所有关键词。
如果文档没有匹配查询,默认情况下将根据限制条件返回文档的头部。从版本1.10-beta开始,可以通过设置allow_empty属性位true以返
回空的片段来替代默认方式。</p><p>失败时返回false。成功时返回包含有片段(摘要)字符串的数组。</p><h3>8.7.2. UpdateAttributes (更新属性)</h3><p>原型: function UpdateAttributes ( $index, $attrs, $values )</p><p>立即更新指定文档的指定属性值。成功则返回实际被更新的文档数目(0或更多),失败则返回-1。</p><p>$index 为待更新的(一个或多个)索引名。$attrs为属性名字符串的数组,其所列的属性会被更新。$attrs为hash表,$values表的键为文档ID,$values表的值为新的属性值的简单数组。</p><p>$index&nbsp;既可以是一个单独的索引名,也可以是一个索引名的列表,就像Query()的参数。与Query()不同的是不允许通配符,全部待更新的索引必须明确指出。索引名列表可以包含分布式索引。对分布式索引,更新会同步到全部代理上。</p><p>只有在docinfo=extern这个存储策略下才可以运行更新。更新非常快,因为操作完全在内存中进行,但它们也可以变成持久的,更新会在searchd干净关闭时(收到SIGTERM信号时)被写入磁盘。在额外限制条件下,MVA属性也可以被更新,参见<a href="#conf-mva-updates-pool">mva_updates_pool</a>详细了解。</p><p>使用示例:</p><pre><code>$cl->UpdateAttributes ( <span><span>"test1"</span></span>, <span><span>array</span></span>(<span><span>"group_id"</span></span>), <span><span>array</span></span>(<span><span>1</span></span>=><span><span>array</span></span>(<span><span>456</span></span>)) );
$cl->UpdateAttributes ( <span><span>"products"</span></span>, <span><span>array</span></span> ( <span><span>"price"</span></span>, <span><span>"amount_in_stock"</span></span> ),
<span><span>array</span></span> ( <span><span>1001</span></span>=><span><span>array</span></span>(<span><span>123</span></span>,<span><span>5</span></span>), <span><span>1002</span></span>=><span><span>array</span></span>(<span><span>37</span></span>,<span><span>11</span></span>), <span><span>1003</span></span>=>(<span><span>25</span></span>,<span><span>129</span></span>) ) );</pre><p>第一条示例语句会更新索引“test1”中的文档1,设置“group_id”为456.第二条示例语句则更新索引“products”中的文档
1001,1002和1003。文档1001的“price”会被更新为123,“amount_in_stock”会被更新为5;文档
1002,“price”变为37而“amount_in_storage”变为11,等等。</p><h3>8.7.3. BuildKeywords (获取分词结果)</h3><p>原型: function BuildKeywords ( $query, $index, $hits )</p><p>根据指定索引的符号化(tokenizer)方式的设置,从查询中抽取关键词,也可以同时返回每个关键词出现次数的统计信息。返回一个数组,其元素是一些字典,每个字典包含一个关键字的信息。</p><p>$query 是抽取关键字的目标。$index是某个索引的名字,系统会使用这个索引的符号化(tokenizer)设置,关键词出现次数的统计信息也从这个索引中得出。$hits是一个布尔值,它指定了是否需要返回关键词出现此处的信息。</p><p>使用示例:</p><pre>$keywords = $cl->BuildKeywords ( <span><span>"this.is.my query"</span></span>, <span><span>"test1"</span></span>, <span><span>false</span></span> );</pre><h3>8.7.4. EscapeString (转义特殊字符)</h3><p>原型: function EscapeString ( $string )</p><p>查询语言分析器将某些字符理解成特殊操作符,这个函数对字符串中的那些有特殊意义的字符进行转义。返回转义后的字符串。</p><p>$string 是待转义的字符串。</p><p>表面上看这个函数是多余的,因为可以很容易地在可能调用这个函数的程序里实现这个转义功能。然而这些特殊字符的集合可能随着时间而改变,因此理应提供一个API调用来完成这个功能,并保证任何时候都可以正确地转义全部特殊字符。</p><p>使用示例:</p><pre>$escaped = $cl->EscapeString ( <span><span>"escaping-sample@query/string"</span></span> );</pre><h3>8.7.5. Status (查询服务状态)</h3><p>原型: function Status ()</p><p>查询searchd的状态,返回一个数组,数组元素是由状态变量名和值的键值对构成。</p><p>使用示例:</p><pre>$status = $cl->Status ();
<span><span>foreach</span></span> ( $status <span><span>as</span></span> $row )
<span><span>print</span></span> join ( <span><span>": "</span></span>, $row ) . <span><span>"\n"</span></span>;
</pre><h3>8.7.6. FlushAttributes (强制更新属性到磁盘)</h3><p>原型: function FlushAttributes ()</p><p>强制 searchd 刷新等待更新的属性到磁盘,并阻塞访问直到完成。 成功时返回一个非负的内部刷新标记值。错误时返回-1,并设置错误信息。 版本2.0.1-beta引入。</p><p>使用UpdateAttributes()API调用更新的属性值将一直保存在内存中,直到一次这样的刷新(将当前所有可能需要更新的属性值写回到磁盘)。FlushAttributes()调用将强制执行一次更新。 调用后将会阻塞访问直到searchd将数据全部写入到磁盘,这个过程可能会需要数秒或者数分钟,这取决于所有待更新数据的大小(.spa文件的大小)。所有当前被更新的索引都会被刷新。</p><p>刷新标记仅仅是一个不断增长的不定数值,并没有实际意义。它一定是一个非负值,并且随着时间而增长,但是并不一定是连续增长;例如,两个调用分别返

回10和1000,他们都是有效的返回值。如果两个FlushAttributes()调用返回相同的标记值,就意味着没有在他们两者之间任何实际的属性
更新,英雌当前的刷新状态将保持不变(所有索引)。</p><p>使用示例:</p><pre>$status = $cl->FlushAttributes ();
<span><span>if</span></span> ( $status<<span><span>0</span></span> )
<span><span>print</span></span> <span><span>"ERROR: "</span></span> . $cl->GetLastError();
</pre><h2>8.8. 持久连接</h2><p>“持久连接”特性允许利用一个单独的网络连接来运行本来需要多个连接的多个命令。</p><h3>8.8.1. Open (打开连接)</h3><p>原型: function Open ()</p><p>打开到服务器的持久连接。</p><h3>8.8.2. Close (关闭连接)</h3><p>原型: function Close ()</p><p>关闭先前打开的持久连接。</p><h2>第 9 章 MySQL 存储引擎 (SphinxSE)</h2><p>目录</p><dl><dt>

     <a href="#sphinxse-overview">9.1. SphinxSE 概览</a> 
    </dt><dt> 
     <a href="#sphinxse-installing">9.2. 安装 SphinxSE</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#sphinxse-mysql50">9.2.1. 编译支持SphinxSE的MySQL 5.0.x</a> 
      </dt><dt> 
       <a href="#sphinxse-mysql51">9.2.2. 编译支持SphinxSE的MySQL 5.1.x</a> 
      </dt><dt> 
       <a href="#sphinxse-checking">9.2.3. 检查SphinxSE安装与否</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#sphinxse-using">9.3. 使用 SphinxSE</a> 
    </dt><dt> 
     <a href="#sphinxse-snippets">9.4. 通过 MySQL 生成片段 (摘要)</a> 
    </dt></dl><h2>9.1.&nbsp;SphinxSE 概览</h2><p>SphinxSE是一个可以编译进MySQL 

5.x版本的MySQL存储引擎,它利用了该版本MySQL的插件式体系结构。SphinxSE不能用于MySQL 4.x系列,它需要MySQL
5.0.22或更高版本;或MySQL 5.1.12或更高版本;或MySQL 5.5.8或更高版本</p><p>尽管被称作“存储引擎”,SphinxSE自身其实并不存储任何数据。它其实是一个允许MySQL服务器与searchd交互并获取搜索结果的嵌入式客户端。所有的索引和搜索都发生在MySQL之外。</p><p>显然,SphinxSE的适用于:</p><ul><li>使将MySQL FTS 应用程序移植到Sphinx;</li><li>使没有Sphinx API的那些语言也可以使用Sphinx;</li><li>当需要在MySQL端对Sphinx结果集做额外处理(例如对原始文档表做JOIN,MySQL端的额外过滤等等)时提供优化。</li></ul><p> </p><h2>9.2. 安装 SphinxSE</h2><p>你需要获得MySQL的源代码,然后重新编译MySQL。MySQL的源代码 (mysql-5.x.yy.tar.gz) 可在 dev.mysql.com 网站获得.</p><p>针对某些版本的MySQL,Sphinx 网站提供了包含支持SphinxSE的打过补丁tarball压缩包。将这些文件解压出来替换原始文件,就可以配置(configure)、构建(build)以生成带有内建Shpinx支持的MySQL了。</p><p>如果网站上没有对应版本的tarball,或者由于某种原因无法工作,那您可能需要手工准备这些文件。您需要一份安装好的GUN Autotools框架(autoconf,automake和libtool)来完成这项任务。</p><h3>9.2.1. 编译支持SphinxSE的MySQL 5.0.x</h3><p>如果使用我们事先做好的打过补丁的tarball,那请跳过步骤1-3。</p><ol><li>将 sphinx.5.0.yy.diff 补丁文件复制到MySQL源码目录并运行patch -p1 < sphinx.5.0.yy.diff 如果没有与您的MySQL版本完全匹配的.diff文件,请尝试一个最接近版本的.diff文件。确保补丁顺利应用,没有rejects。 </li><li>在MySQL源码目录中运行sh BUILD/autorun.sh </li><li>在MySQL源码目录中建立sql/sphinx目录,并把Sphinx源码目录中mysqlse目录下的全部文件拷贝到这个目录。示例:cp -R /root/builds/sphinx-0.9.7/mysqlse/* /root/builds/mysql-5.0.24/sql/sphinx </li><li>配置(configure)MySQL,启用Sphinx引擎:./configure --with-sphinx-storage-engine </li><li>构建(build)并安装MySQL:make
make install </li></ol><h3>9.2.2. 编译支持SphinxSE的MySQL 5.1.x</h3><p>如果使用我们事先做好的打过补丁的tarball,那请跳过步骤1-2。</p><ol><li>在MySQL源码目录中建立storage/sphinx目录,并将Sphinx源码目录中的mysqlse目录下的全部文件拷贝到这个目录。示例:cp -R /root/builds/sphinx-0.9.7/mysqlse/* /root/builds/mysql-5.1.14/storage/sphinx </li><li>在MySQL源码目录运行sh BUILD/autorun.sh </li><li>配置(configure)MySQL,启用Sphinx引擎./configure --with-plugins=sphinx </li><li>构建(build)并安装MySQLmake

make install </li></ol><h3>9.2.3. 检查SphinxSE安装与否</h3><p>为了检查SphinxSE是否成功地编入了MySQL,启动新编译出的MySQL服务器,运行mysql客户端,执行SHOW ENGINES查询,这会显示一个全部可用引擎的列表。Sphinx应该出现在这个列表中,而且在“Support”列上显示“YES”:</p><pre>mysql> show engines;
<span><span>Engine</span></span> Support <span><span>Comment</span></span>
<span><span>MyISAM</span></span> DEFAULT <span><span>Default engine as of MySQL 3.23 with great performance</span></span>

...
<span><span>| SPHINX |</span></span> YES <span><span>| Sphinx storage engine |</span></span>

...

<span><span>13</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>00</span></span> sec)</pre><h2>9.3. 使用 SphinxSE</h2><p>要通过SphinxSE搜索,您需要建立特殊的ENGINE=SPHINX的“搜索表”(中间表,没有实际数据,查询时从searchd获取数据返回给MySQL),然后使用SELECT语句从中检索,把全文查询放在WHERE子句中。</p><p>让我们从一个create语句和搜索查询的例子开始:</p><pre><span><span>CREATE</span></span> <span><span>TABLE</span></span> t1
(
<span><span>id</span></span> <span><span>INTEGER</span></span> <span><span>UNSIGNED</span></span> <span><span>NOT</span></span> <span><span>NULL</span></span>,
weight <span><span>INTEGER</span></span> <span><span>NOT</span></span> <span><span>NULL</span></span>,
<span><span>query</span></span> <span><span>VARCHAR</span></span>(<span><span>3072</span></span>) <span><span>NOT</span></span> <span><span>NULL</span></span>,
<span><span>group_id</span></span> <span><span>INTEGER</span></span>,
<span><span>INDEX</span></span>(<span><span>query</span></span>)
) <span><span>ENGINE</span></span>=SPHINX <span><span>CONNECTION</span></span>=<span><span>"sphinx://localhost:9312/test"</span></span>;

<span><span>SELECT</span></span> <span><span>FROM</span></span> t1 <span><span>WHERE</span></span> <span><span>query</span></span>=<span><span>'test it;mode=any'</span></span>;</pre><p> </p><p>搜索表前三列(字段)的类型必须是INTEGER UNSINGED(或者 BIGINT),INTEGER(或者 BIGINT)和VARCHAR(或者 TEXT),这三列分别对应文档ID,匹配权值和搜索查询。这前三个列的映射关系是固定的,你不能忽略这三列中的任何一个,或者移动其位置,或者改变其类型。搜索查询列必须被索引,其他列必须无索引。列的名字会被忽略,所以可以任意命名。</p><p>除此之外,其他列(字段)的类型必须是INTEGER、TIMESTAMP、BIGINT、VARCHAR或者FLOAT之一。它们必须与Sphinx结果集中提供的属性按名称绑定,即它们的名字必须与sphinx.conf中指定的属性名一一对应。如果Sphinx搜索结果中没有某个属性名,该列的值就为NULL.</p><p>特殊的内部“虚拟”属性名也可以与SphinxSE列绑定。但特殊符号@用_sph_代替。例如,要取得@group@count 或者@distinct内部属性,列名应分别使用_sph_group、_sph_count或者_sph_distinct。</p><p>可以使用字符串参数CONNECTION来指定用这个表搜索时的默认搜索主机、端口号和索引。如果CREATE TABLE中没有使用连接(connection)串,那么默认使用索引名“”(搜索所有索引)和localhost:9312。连接串的语法如下:</p><pre><span><span>CONNECTION</span></span>=<span><span>"sphinx://HOST:PORT/INDEXNAME"</span></span></pre><p>默认的连接串也可以需要时改变:</p><pre><span><span>ALTER</span></span> <span><span>TABLE</span></span> t1 <span><span>CONNECTION</span></span>=<span><span>"sphinx://NEWHOST:NEWPORT/NEWINDEXNAME"</span></span>;</pre><p>也可以在查询中覆盖全部这些选项。</p><p>如例子所示,查询文本和搜索选项都应放在WHERE子句中对query列的限制中(即第三列),选项之间用分号分隔,选项名与选项值用等号隔开。可以指定任意数目的选项。可用的选项如下:</p><ul><li>query – 查询文本;</li><li>mode – 匹配模式.必须是 “all”, “any”, “phrase”, “boolean”, 或者 “extended”, 或者 “extended2″ 之一。默认为 “all”;</li><li>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'; </li><li>offset – 结果集中的偏移量,默认是0;</li><li>limit – 从结果集中获取的匹配项数目,默认为20;</li><li>index – 待搜索的索引:... WHERE query='test;index=test1;';
... WHERE query='test;index=test1,test2,test3;'; </li><li>minid, maxid – 匹配文档ID的最小值和最大值;</li><li>weights – 逗号分隔的列表,指定Sphinx全文数据字段的权值:... WHERE query='test;weights=1,2,3;'; </li><li>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;'; </li><li>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;'; </li><li>maxmatches – 此查询最大匹配的数量, 与SetLimits() API 调用的max_matches参数类似:... WHERE query='test;maxmatches=2000;'; </li><li>cutoff – 此查询最大允许的匹配数, 与 SetLimits() API 调用的参数cutoff类似:... WHERE query='test;cutoff=10000;'; </li><li>maxquerytme – 此查询最大允许的查询时间 (单位为毫秒), 如同 SetMaxQueryTime() API 调用:... WHERE query='test;maxquerytime=1000;'; </li><li>groupby – 分组(group-by)函数和属性, 对应 SetGroupBy() API 调用:... WHERE query='test;groupby=day:published_ts;';

... WHERE query='test;groupby=attr:group_id;'; </li><li>groupsort – 分组(group-by)排序子句:... WHERE query='test;groupsort=@count desc;'; </li><li>distinct – 分组(group-by)时用于计算COUNT(DISTINCT) 的属性名称,如同 SetGroupDistinct() API 调用:... WHERE query='test;groupby=attr:country_id;distinct=site_id'; </li><li>indexweights – 逗号分隔的列表,指定一系列索引名和搜索时这些索引对应的权值:... WHERE query='test;indexweights=idx_exact,2,idx_stemmed,1;'; </li><li>comment – 用于查询日志标记本次查询的字符串 (对应Query() API 调用的$comment参数):... WHERE query='test;comment=marker001;'; </li><li>select – 用于计算的表达式 (对应 SetSelect() API 调用):... WHERE query='test;select=2a+3b as myexpr;'; </li><li>host, port – 分别表示本地或者远端 searchd 主机名称和 TCP 端口:... WHERE query='test;host=sphinx-test.loc;port=7312;'; </li><li>ranker – 当匹配模式(查询语法)为extended时用于评分模式 , 对应 SetRankingMode() API 调用. 可用值包括 “proximity_bm25″, “bm25″, “none”, “wordcount”, “proximity”, “matchany”, 和 “fieldmask”.... WHERE query='testrmode=extended2;anker=bm25;'; </li><li>geoanchor – 地理坐标锚点,对应 SetGeoAnchor() API 调用. 参数有四个分别是维度与经度属性的名称以及定位点的坐标:... WHERE query='test;geoanchor=latattr,lonattr,0.123,0.456'; </li></ul><p> </p><p>一个非常重要的注意事项:让Sphinx来对结果集执行排序、过滤和切片(slice)要比提高最大匹配项数量然后在MySQL端用WHERE、ORDER BY和LIMIT子句完成对应的功能来得高效得多。这有两方面的原因。首先,Sphinx对这些操作做了一些优化,比MySQL效率更高一些。其次,searchd可以打包更少的数据,SphinxSE也可以传输和解包更少的数据。</p><p>从版本0.9.9-rc1开始,除了结果集,额外的查询信息可以用SHOW ENGINE SPHINX STATUS语句获得:</p><pre>mysql> SHOW ENGINE SPHINX STATUS;
TypeNameStatus
SPHINXstats<span><span>total:</span></span> <span><span>25</span></span>, total <span><span>found:</span></span> <span><span>25</span></span>, <span><span>time:</span></span> <span><span>126</span></span>, <span><span>words:</span></span> <span><span>2</span></span>
SPHINXwords<span><span>sphinx:</span></span><span><span>591</span></span>:<span><span>1256</span></span> <span><span>soft:</span></span><span><span>11076</span></span>:<span><span>15945</span></span>
<span><span>2</span></span> rows <span><span>in</span></span> set (<span><span>0.00</span></span> sec)</pre><p>查询状态信息可以通过状态变量名来访问。值得提醒的是,访问这些信息不需要超级用户权限。</p><pre>mysql> SHOW STATUS LIKE <span><span>'sphinx_%'</span></span>;
<span><span>Variable_name</span></span> Value <span><span>
</span></span> sphinx_total <span><span>25</span></span>
<span><span>sphinx_total_found</span></span> <span><span>25</span></span> <span><span>
</span></span> sphinx_time <span><span>126</span></span>
<span><span>sphinx_word_count</span></span> <span><span>2</span></span> <span><span>
</span></span> sphinx_words <span><span>sphinx:591:1256 soft:11076:15945</span></span>

<span><span>5</span></span> rows <span><span>in</span></span> set (<span><span>0</span></span>.<span><span>00</span></span> sec)</pre><p> </p><p>可以对SphinxSE搜索表和其他引擎的表之间使用JOIN,以下是一个例子,例中“documents”来自example.sql:</p><pre>mysql> SELECT content, date_added FROM test.documents docs
-> JOIN t1 ON (docs.id=t1.id)

-> WHERE query=<span><span>"one document;mode=any"</span></span>;
<span><span>content</span></span> docdate <span><span>
</span></span> this is my test document number two <span><span>2006-06-17 14:04:28</span></span>
<span><span>this is my test document number one</span></span> <span><span>2006</span></span>-<span><span>06</span></span>-<span><span>17</span></span> <span><span>14</span></span><span><span>:</span></span><span><span>04</span></span><span><span>:</span></span><span><span>28</span></span> <span><span>

2 rows </span><span><span><span>in</span></span></span><span> set (0.00 sec)

mysql> SHOW ENGINE SPHINX STATUS;
</span></span> Type <span><span>Name</span></span> Status <span><span>
</span></span> SPHINX <span><span>stats</span></span> <span><span>total:</span></span> <span><span>2</span></span>, total <span><span>found:</span></span> <span><span>2</span></span>, <span><span>time:</span></span> <span><span>0</span></span>, <span><span>words:</span></span> <span><span>2</span></span> <span><span>
</span></span> SPHINX <span><span>words</span></span> <span><span>one:</span></span><span><span>1</span></span><span><span>:</span></span><span><span>2</span></span> <span><span>document:</span></span><span><span>2</span></span><span><span>:</span></span><span><span>2</span></span> <span><span>

2 rows </span><span><span><span>in</span></span></span><span> set (0.00 sec)</span></span></pre><p> </p><h2>9.4. 通过 MySQL 生成片段 (摘要)</h2><p>从版本0.9.9-rc2开始,SphinxSE提供了一个UDF函数,允许用户通过MySQL创建摘要。这个功能的作用与API调用BuildExcerprts的功能非常相似,但可以通过MySQL+SphinxSE来访问。</p><p>提供这个UDF的二进制文件叫做sphinx.so,当安装SphinxSE本身的时候,这个文件会自动地被创建,并且安装到合适的位置。 但如果由于某种原因它没能自动安装,那就请在创建SphinxSE的目录中寻找sphinx.so文件,并把它拷贝到你的MySQL实例的plugins目录下。然后用下面语句来注册这个UDF:</p><pre><span><span>CREATE</span></span> <span><span>FUNCTION</span></span> sphinx_snippets <span><span>RETURNS</span></span> <span><span>STRING</span></span> <span><span>SONAME</span></span> <span><span>'sphinx.so'</span></span>;</pre><p> </p><p>函数的名字必须是sphinx_snippets,而不能随便取名。函数的参数表必须如下:</p><p>原型: function sphinx_snippets ( document, index, words, [options] );</p><p>Documents和words这两个参数可以是字符串或者数据库表的列。Options参数(额外选项)必须这样指定:‘值’ AS 选项名。关于支持的所有选项,可以参见API调用BuildExcerprts()。只有一个选项不被API支持而只能用于UDF,这个选项叫做'sphinx',用于指定searchd的位置(服务器和端口)。</p><p>使用示例:</p><pre><span><span>SELECT</span></span> sphinx_snippets(<span><span>'hello world doc'</span></span>, <span><span>'main'</span></span>, <span><span>'world'</span></span>,
<span><span>'sphinx://192.168.1.1/'</span></span> <span><span>AS</span></span> sphinx, <span><span>true</span></span> <span><span>AS</span></span> exact_phrase,
<span><span>'[b]'</span></span> <span><span>AS</span></span> before_match, <span><span>'[/b]'</span></span> <span><span>AS</span></span> after_match)
<span><span>FROM</span></span> documents;

<span><span>SELECT</span></span> title, sphinx_snippets(<span><span>text</span></span>, <span><span>'index'</span></span>, <span><span>'mysql php'</span></span>) <span><span>AS</span></span> <span><span>text</span></span>
<span><span>FROM</span></span> sphinx, documents
<span><span>WHERE</span></span> <span><span>query</span></span>=<span><span>'mysql php'</span></span> <span><span>AND</span></span> sphinx.id=documents.id;
</pre><p> </p><h2>第 10 章 报告BUG</h2><p>很不幸,Sphinx还没有达到100%无bug(尽管我们正向这个目标努力),因此您可能偶尔遇到些问题。</p><p>对于每个问题的报告越详细越好,这很重要——因为要想修复bug,我们必须重现bug并调试它,或者根据您提供的信息来推断出产生bug的原因。因此在此提供一些如何报告bug的指导。</p><h2>编译时的问题</h2><p>如果Sphinx构建失败,请您按照以下步骤进行:</p><ol><li>确认您的DBMS(数据库)的头文件和库文件都正确安装了(例如,检查mysql-devel包已经安装)</li><li>报告Sphinx的版本和配置文件(别忘了删除数据库连接密码),MySQL(或PostgreSQL)配置文件信息,gcc版本,操作系统版本和CPU类型(例如x86、x86-64、PowerPC等):mysql_config
gcc --version
uname -a </li><li>报告configure脚本或者gcc给出的错误信息(只需错误信息本身,不必附上整个构建日志)</li></ol><h2>运行时的问题</h2><p>如果Sphinx已经成功构建并能运行,但运行过程中出现了问题,请您按照以下步骤进行:</p><ol><li>描述您遇到的bug(即,您预期的行为和实际发生的行为),以及重现您遇到的问题需要的步骤;</li><li>附带Sphinx的版本和配置文件(别忘了删除密码),MySQL(或PostgreSQL)配置文件信息,gcc版本,操作系统版本和CPU类型(例如x86、x86-64、PowerPC等):mysql --version
gcc --version
uname -a </li><li>构建、安装和运行调试版本的全部Sphinx程序(这会启用很多内部校验,或称断言(assertions)):make distclean
./configure --with-debug
make install
killall -TERM searchd </li><li>重新索引,检查是否有断言(assertions)被触发(如果是,那很可能是索引损坏了并造成了问题);</li><li>如果bug在调试版本中没有重现,请回到非调试版本并在报告中说明这个情况;</li><li>如果bug可以在您的数据库的很小的子集(1-100条记录)上重现,请提供一个该子集的gzip压缩包;</li><li>如果问题与searchd有关,请在bug报告中提供searchd.log和query.log中的相关条目;</li><li>如果问题与searchd有关,请尝试在console模式下运行它并检查它是否因断言失败而退出。./searchd --console </li><li>如果任何一个程序因断言失败而退出,请提供断言(assertions)信息。</li></ol><h2>调试断言,崩溃和挂断</h2><p>如果任何一个程序因断言(assertions)失败而退出,崩溃或停止响应,您可以额外生成一个内存转储文件并检查它。</p><ol><li>启用内存转储。在大多数Linux系统上,可以用ulimit命令启用它:ulimit -c 32768 </li><li>运行程序,尝试重现bug;</li><li>如果程序崩溃(可能有断言失败的情况也可能没有),在当前目录下找到内存转储文件(一般会打印“Segmentation fault (core dumped)”消息);</li><li>如果程序停止响应,在另一个控制台上用kill -SEGV强制退出并获得内存转储:kill -SEGV HANGED-PROCESS-ID </li><li>使用gdb检查转储文件,查看backtrace:gdb ./CRASHED-PROGRAM-FILE-NAME CORE-DUMP-FILE-NAME
(gdb) bt
(gdb) quit </li></ol><p>提示: HANGED-PROCESS-ID(停止响应的进程ID),
CRASHED-PROGRAM-FILE-NAME(崩溃程序的文件名) and
CORE-DUMP-FILE-NAME(核心转储文件的文件名)应该被换成具体的数字和文件名。例如,一次对停止响应的searchd的调试会话看起来
应该像下面这样:</p><pre><span><span># kill -SEGV 12345</span></span>
<span><span># ls core</span></span>
core.12345
<span><span># gdb ./searchd core.12345</span></span>
(gdb) bt
<span><span>...</span></span>
(gdb) quit
</pre><p> </p><p>注意ulimit并不是整个服务器范围的,而是仅影响当前的shell会话。因此您不必还原任何服务器范围的限制——但是一旦重新登陆,您就需要再次设置ulimit。</p><p>核心内存转储文件会存放在当前工作目录下(Sphinx的各个程序不会改变工作目录),因此它们就在那。</p><p>不要立刻删除转储文件,从它里面可能获得更多有用的信息。您不需要把这个文件发送给我们(因为调试信息与您的系统本身紧密相关),但我们可能会向您询问一些与之相关的问题。</p><h2>第 11 章 sphinx.conf/csft.conf 配置选项参考</h2><p>目录</p><dl><dt>

     <a href="#confgroup-source">11.1. 数据源配置选项</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#conf-source-type">11.1.1. type:数据源类型</a> 
      </dt><dt> 
       <a href="#conf-sql-host">11.1.2. sql_host:数据库服务器</a> 
      </dt><dt> 
       <a href="#conf-sql-port">11.1.3. sql_port:数据库端口</a> 
      </dt><dt> 
       <a href="#conf-sql-user">11.1.4. sql_user:数据库用户名</a> 
      </dt><dt> 
       <a href="#conf-sql-pass">11.1.5. sql_pass:数据库密码</a> 
      </dt><dt> 
       <a href="#conf-sql-db">11.1.6. sql_db:数据库名称</a> 
      </dt><dt> 
       <a href="#conf-sql-sock">11.1.7. sql_sock:数据库Socket文件</a> 
      </dt><dt> 
       <a href="#conf-mysql-connect-flags">11.1.8. mysql_connect_flags:MySQL连接参数</a> 
      </dt><dt> 
       <a href="#conf-mysql-ssl">11.1.9. mysql_ssl_cert, mysql_ssl_key, mysql_ssl_ca:MySQL的SSL连接</a> 
      </dt><dt> 
       <a href="#conf-odbc-dsn">11.1.10. odbc_dsn:ODBC连接字符串(DSN)</a> 
      </dt><dt> 
       <a href="#conf-sql-query-pre">11.1.11. sql_query_pre:待索引数据获取前查询</a> 
      </dt><dt> 
       <a href="#conf-sql-query">11.1.12. sql_query:获取待索引数据查询</a> 
      </dt><dt> 
       <a href="#conf-sql-joined-field">11.1.13. sql_joined_field:SQL连接字段设置</a> 
      </dt><dt> 
       <a href="#conf-sql-query-range">11.1.14. sql_query_range:分区查询范围</a> 
      </dt><dt> 
       <a href="#conf-sql-range-step">11.1.15. sql_range_step:分区查询步进值</a> 
      </dt><dt> 
       <a href="#conf-sql-query-killlist">11.1.16. sql_query_killlist:Kill-list查询</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-uint">11.1.17. sql_attr_uint:整数属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-bool">11.1.18. sql_attr_bool:布尔属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-bigint">11.1.19. sql_attr_bigint:长整型属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-timestamp">11.1.20. sql_attr_timestamp:UNIX时间戳属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-str2ordinal">11.1.21. sql_attr_str2ordinal:字符串序数排序属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-float">11.1.22. sql_attr_float:浮点数属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-multi">11.1.23. sql_attr_multi:多值属性(MVA)属性</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-string">11.1.24. sql_attr_string:字符串属性(可返回原始文本信息)</a> 
      </dt><dt> 
       <a href="#conf-sql-attr-str2wordcount">11.1.25. sql_attr_str2wordcount:文档词汇数记录属性</a> 
      </dt><dt> 
       <a href="#conf-sql-column-buffers">11.1.26. sql_column_buffers:结果行缓冲大小</a> 
      </dt><dt> 
       <a href="#conf-sql-field-string">11.1.27. sql_field_string:字符串字段(可全文搜索,可返回原始文本信息)</a> 
      </dt><dt> 
       <a href="#conf-sql-field-str2wordcount">11.1.28. sql_field_str2wordcount:文档词汇数记录字段(可全文搜索,可返回原始信息)</a> 
      </dt><dt> 
       <a href="#conf-sql-file-field">11.1.29. sql_file_field:外部文件字段</a> 
      </dt><dt> 
       <a href="#conf-sql-query-post">11.1.30. sql_query_post:数据获取后查询</a> 
      </dt><dt> 
       <a href="#conf-sql-query-post-index">11.1.31. sql_query_post_index:数据索引后查询</a> 
      </dt><dt> 
       <a href="#conf-sql-ranged-throttle">11.1.32. sql_ranged_throttle:分区查询间隔时间</a> 
      </dt><dt> 
       <a href="#conf-sql-query-info-pre">11.1.33. sql_query_info_pre:命令行信息获取前查询</a> 
      </dt><dt> 
       <a href="#conf-sql-query-info">11.1.34. sql_query_info:命令行信息获取查询</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-command">11.1.35. xmlpipe_command:数据获取命令</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-field">11.1.36. xmlpipe_field:字段设置</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-field-string">11.1.37. xmlpipe_field_string:字符串字段</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-field-wordcount">11.1.38. xmlpipe_field_wordcount:词汇数存储字段</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-uint">11.1.39. xmlpipe_attr_uint:整数属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-bool">11.1.40. xmlpipe_attr_bool:布尔属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-timestamp">11.1.41. xmlpipe_attr_timestamp:UNIX时间戳属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-str2ordinal">11.1.42. xmlpipe_attr_str2ordinal:字符串序列属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-float">11.1.43. xmlpipe_attr_float:浮点数属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-multi">11.1.44. xmlpipe_attr_multi:多值属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-attr-string">11.1.45. xmlpipe_attr_string:字符串属性</a> 
      </dt><dt> 
       <a href="#conf-xmlpipe-fixup-utf8">11.1.46. xmlpipe_fixup_utf8:UTF-8修复设置</a> 
      </dt><dt> 
       <a href="#conf-mssql-winauth">11.1.47. mssql_winauth:Windows集成认证</a> 
      </dt><dt> 
       <a href="#conf-mssql-unicode">11.1.48. mssql_unicode:Unicode设置</a> 
      </dt><dt> 
       <a href="#conf-unpack-zlib">11.1.49. unpack_zlib:SQL数据源解压字段设置</a> 
      </dt><dt> 
       <a href="#conf-unpack-mysqlcompress">11.1.50. unpack_mysqlcompress:MySQL数据源解压字段设置</a> 
      </dt><dt> 
       <a href="#conf-unpack-mysqlcompress-maxsize">11.1.51. unpack_mysqlcompress_maxsize:MySQL数据源解压缓冲区设置</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#confgroup-index">11.2. 索引配置选项</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#conf-index-type">11.2.1. type:索引类型设置</a> 
      </dt><dt> 
       <a href="#conf-source">11.2.2. source:文档源</a> 
      </dt><dt> 
       <a href="#conf-path">11.2.3. path:索引文件路径</a> 
      </dt><dt> 
       <a href="#conf-docinfo">11.2.4. docinfo:文档信息存储模式</a> 
      </dt><dt> 
       <a href="#conf-mlock">11.2.5. mlock:缓冲数据内存锁定</a> 
      </dt><dt> 
       <a href="#conf-morphology">11.2.6. morphology:词形处理</a> 
      </dt><dt> 
       <a href="#conf-dict">11.2.7. dict:关键字词典类型</a> 
      </dt><dt> 
       <a href="#conf-index-sp">11.2.8. index_sp:索引句子和段落信息</a> 
      </dt><dt> 
       <a href="#conf-index-zones">11.2.9. index_zones:索引标签区域信息</a> 
      </dt><dt> 
       <a href="#conf-min-stemming-len">11.2.10. min_stemming_len:词干化最小词长</a> 
      </dt><dt> 
       <a href="#conf-stopwords">11.2.11. stopwords:停止词</a> 
      </dt><dt> 
       <a href="#conf-wordforms">11.2.12. wordforms:词形字典</a> 
      </dt><dt> 
       <a href="#conf-exceptions">11.2.13. exceptions:词汇特例处理</a> 
      </dt><dt> 
       <a href="#conf-min-word-len">11.2.14. min_word_len:最小索引词汇长度</a> 
      </dt><dt> 
       <a href="#conf-charset-type">11.2.15. charset_type:字符集编码</a> 
      </dt><dt> 
       <a href="#conf-charset-table">11.2.16. charset_table:字符表和大小写转换规则</a> 
      </dt><dt> 
       <a href="#conf-ignore-chars">11.2.17. ignore_chars:忽略字符表</a> 
      </dt><dt> 
       <a href="#conf-min-prefix-len">11.2.18. min_prefix_len:最小索引前缀长度</a> 
      </dt><dt> 
       <a href="#conf-min-infix-len">11.2.19. min_infix_len:最小索引中缀长度</a> 
      </dt><dt> 
       <a href="#conf-prefix-fields">11.2.20. prefix_fields:前缀索引字段列表</a> 
      </dt><dt> 
       <a href="#conf-infix-fields">11.2.21. infix_fields:中缀索引字段列表</a> 
      </dt><dt> 
       <a href="#conf-enable-star">11.2.22. enable_star:星号语法</a> 
      </dt><dt> 
       <a href="#conf-ngram-len">11.2.23. ngram_len:N-gram长度</a> 
      </dt><dt> 
       <a href="#conf-ngram-chars">11.2.24. ngram_chars:N-gram字符列表</a> 
      </dt><dt> 
       <a href="#conf-phrase-boundary">11.2.25. phrase_boundary:词组边界符列表</a> 
      </dt><dt> 
       <a href="#conf-phrase-boundary-step">11.2.26. phrase_boundary_step:词组边界位置增量</a> 
      </dt><dt> 
       <a href="#conf-html-strip">11.2.27. html_strip:HTMl标记清理</a> 
      </dt><dt> 
       <a href="#conf-html-index-attrs">11.2.28. html_index_attrs:HTML标签属性索引设置</a> 
      </dt><dt> 
       <a href="#conf-html-remove-elements">11.2.29. html_remove_elements:HTML元素清理</a> 
      </dt><dt> 
       <a href="#conf-local">11.2.30. local:本地索引声明</a> 
      </dt><dt> 
       <a href="#conf-agent">11.2.31. agent:远程索引声明</a> 
      </dt><dt> 
       <a href="#conf-agent-blackhole">11.2.32. agent_blackhole:远程黑洞代理</a> 
      </dt><dt> 
       <a href="#conf-agent-connect-timeout">11.2.33. agent_connect_timeout:远程查询时间</a> 
      </dt><dt> 
       <a href="#conf-agent-query-timeout">11.2.34. agent_query_timeout:远程查询超时时间</a> 
      </dt><dt> 
       <a href="#conf-preopen">11.2.35. preopen:索引文件预开启</a> 
      </dt><dt> 
       <a href="#conf-ondisk-dict">11.2.36. ondisk_dict:字典文件保持设置</a> 
      </dt><dt> 
       <a href="#conf-inplace-enable">11.2.37. inplace_enable:原地索引倒转设置</a> 
      </dt><dt> 
       <a href="#conf-inplace-hit-gap">11.2.38. inplace_hit_gap:原地索引倒转匹配点空隙设置</a> 
      </dt><dt> 
       <a href="#conf-inplace-docinfo-gap">11.2.39. inplace_docinfo_gap:原地索引倒转文档信息空隙设置</a> 
      </dt><dt> 
       <a href="#conf-inplace-reloc-factor">11.2.40. inplace_reloc_factor:原地索引倒转重定位内存设置</a> 
      </dt><dt> 
       <a href="#conf-inplace-write-factor">11.2.41. inplace_write_factor:原地索引倒转写缓冲内存设置</a> 
      </dt><dt> 
       <a href="#conf-index-exact-words">11.2.42. index_exact_words:词干化后原词索引</a> 
      </dt><dt> 
       <a href="#conf-overshort-step">11.2.43. overshort_step:短词位置增量</a> 
      </dt><dt> 
       <a href="#conf-stopword-step">11.2.44. stopword_step:通用词位置增量</a> 
      </dt><dt> 
       <a href="#conf-hitless-words">11.2.45. hitless_words:位置忽略词汇列表</a> 
      </dt><dt> 
       <a href="#conf-expand-keywords">11.2.46. expand_keywords:词汇展开</a> 
      </dt><dt> 
       <a href="#conf-blend-chars">11.2.47. blend_chars:混合字符列表</a> 
      </dt><dt> 
       <a href="#conf-blend-mode">11.2.48. blend_mode:混合类型</a> 
      </dt><dt> 
       <a href="#conf-rt-mem-limit">11.2.49. rt_mem_limit:RT索引内存限制</a> 
      </dt><dt> 
       <a href="#conf-rt-field">11.2.50. rt_field:字段设置</a> 
      </dt><dt> 
       <a href="#conf-rt-attr-uint">11.2.51. rt_attr_uint:整数属性</a> 
      </dt><dt> 
       <a href="#conf-rt-attr-bigint">11.2.52. rt_attr_bigint:长整数属性</a> 
      </dt><dt> 
       <a href="#conf-rt-attr-float">11.2.53. rt_attr_float:浮点数属性</a> 
      </dt><dt> 
       <a href="#conf-rt-attr-timestamp">11.2.54. rt_attr_timestamp:UNIX时间戳属性</a> 
      </dt><dt> 
       <a href="#conf-rt-attr-string">11.2.55. rt_attr_string:字符串属性</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#confgroup-indexer">11.3.&nbsp;<code>indexer</code>&nbsp;程序配置选项</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#conf-mem-limit">11.3.1. mem_limit:索引内存限制</a> 
      </dt><dt> 
       <a href="#conf-max-iops">11.3.2. max_iops:每秒IO操作限制</a> 
      </dt><dt> 
       <a href="#conf-max-iosize">11.3.3. max_iosize:最大IO操作限制</a> 
      </dt><dt> 
       <a href="#conf-max-xmlpipe2-field">11.3.4. max_xmlpipe2_field:最大字段大小</a> 
      </dt><dt> 
       <a href="#conf-write-buffer">11.3.5. write_buffer:写缓冲大小</a> 
      </dt><dt> 
       <a href="#conf-max-file-field-buffer">11.3.6. max_file_field_buffer:外部文件缓冲大小</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#confgroup-searchd">11.4.&nbsp;<code>searchd</code>&nbsp;程序配置选项</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#conf-listen">11.4.1. listen:监听设置</a> 
      </dt><dt> 
       <a href="#conf-address">11.4.2. address:监听地址</a> 
      </dt><dt> 
       <a href="#conf-port">11.4.3. port:监听端口</a> 
      </dt><dt> 
       <a href="#conf-log">11.4.4. log:搜索系统日志</a> 
      </dt><dt> 
       <a href="#conf-query-log">11.4.5. query_log:搜索查询日志</a> 
      </dt><dt> 
       <a href="#conf-query-log-format">11.4.6. query_log_format:查询日志格式</a> 
      </dt><dt> 
       <a href="#conf-read-timeout">11.4.7. read_timeout:远程读取超时时间</a> 
      </dt><dt> 
       <a href="#conf-client-timeout">11.4.8. client_timeout:客户端超时时间</a> 
      </dt><dt> 
       <a href="#conf-max-children">11.4.9. max_children:子进程数目限制</a> 
      </dt><dt> 
       <a href="#conf-pid-file">11.4.10. pid_file:PID文件</a> 
      </dt><dt> 
       <a href="#conf-max-matches">11.4.11. max_matches:最大返回匹配数</a> 
      </dt><dt> 
       <a href="#conf-seamless-rotate">11.4.12. seamless_rotate:无缝轮换</a> 
      </dt><dt> 
       <a href="#conf-preopen-indexes">11.4.13. preopen_indexes:索引预开启</a> 
      </dt><dt> 
       <a href="#conf-unlink-old">11.4.14. unlink_old:旧索引清理</a> 
      </dt><dt> 
       <a href="#conf-attr-flush-period">11.4.15. attr_flush_period:属性刷新周期</a> 
      </dt><dt> 
       <a href="#conf-ondisk-dict-default">11.4.16. ondisk_dict_default:索引字典存储方式</a> 
      </dt><dt> 
       <a href="#conf-max-packet-size">11.4.17. max_packet_size:最大包大小</a> 
      </dt><dt> 
       <a href="#conf-mva-updates-pool">11.4.18. mva_updates_pool:MVA更新共享内存</a> 
      </dt><dt> 
       <a href="#conf-crash-log-path">11.4.19. crash_log_path:崩溃日志</a> 
      </dt><dt> 
       <a href="#conf-max-filters">11.4.20. max_filters:最大过滤器数目</a> 
      </dt><dt> 
       <a href="#conf-max-filter-values">11.4.21. max_filter_values:单个过滤器最大过滤值数目</a> 
      </dt><dt> 
       <a href="#conf-listen-backlog">11.4.22. listen_backlog:带处理监听队列</a> 
      </dt><dt> 
       <a href="#conf-read-buffer">11.4.23. read_buffer:读缓冲区</a> 
      </dt><dt> 
       <a href="#conf-read-unhinted">11.4.24. read_unhinted:无匹配时读取大小</a> 
      </dt><dt> 
       <a href="#conf-max-batch-queries">11.4.25. max_batch_queries:最大批量查询</a> 
      </dt><dt> 
       <a href="#conf-subtree-docs-cache">11.4.26. subtree_docs_cache:子树优化文档缓存</a> 
      </dt><dt> 
       <a href="#conf-subtree-hits-cache">11.4.27. subtree_hits_cache:子树优化命中缓存</a> 
      </dt><dt> 
       <a href="#conf-workers">11.4.28. workers:MPM模式</a> 
      </dt><dt> 
       <a href="#conf-dist-threads">11.4.29. dist_threads:并发查询线程数</a> 
      </dt><dt> 
       <a href="#conf-binlog-path">11.4.30. binlog_path:二进制日志路径</a> 
      </dt><dt> 
       <a href="#conf-binlog-flush">11.4.31. binlog_flush:二进制日志刷新</a> 
      </dt><dt> 
       <a href="#conf-binlog-max-log-size">11.4.32. binlog_max_log_size:二进制日志大小限制</a> 
      </dt><dt> 
       <a href="#conf-collation-server">11.4.33. collation_server:服务端默认字符集</a> 
      </dt><dt> 
       <a href="#conf-collation-libc-locale">11.4.34. collation_libc_locale:服务端libc字符集</a> 
      </dt><dt> 
       <a href="#conf-plugin-dir">11.4.35. plugin_dir:插件目录</a> 
      </dt><dt> 
       <a href="#conf-mysql-version-string">11.4.36. mysql_version_string:MySQL版本设置</a> 
      </dt><dt> 
       <a href="#conf-rt-flush-period">11.4.37. rt_flush_period:RT索引刷新周期</a> 
      </dt><dt> 
       <a href="#conf-thread-stack">11.4.38. thread_stack:线程堆栈</a> 
      </dt><dt> 
       <a href="#conf-expansion-limit">11.4.39. expansion_limit:关键字展开限制</a> 
      </dt><dt> 
       <a href="#conf-compat-sphinxql-magics">11.4.40. compat_sphinxql_magics</a> 
      </dt><dt> 
       <a href="#conf-watchdog">11.4.41. watchdog</a> 
      </dt></dl> 
    </dd></dl><h2>11.1.&nbsp;数据源配置选项</h2><h3>11.1.1.&nbsp;type:数据源类型</h3><p>数据源类型。必须选项,无默认值。 可用的类型包括&nbsp;mysql,&nbsp;pgsql,&nbsp;mssql,&nbsp;xmlpipe&nbsp;and&nbsp;xmlpipe2,&nbsp;odbc,以及python.</p><p>在CoreSeek的分发版本中,新增了python数据源类型,从而得以启用Python数据源支持。</p><p>所有其他与数据源相关的选项都依赖于这个选项指定的源类型。与SQL数据源(即MSSQL、MySQL和PostgreSQL)相关的选项以“sql_”开头,而与xmlpipe和xmlpipe2数据源相关的选项则以“xmlpipe_”开头。 除了xmlpipe是默认支持外,其他数据源类型的支持是有前提条件的;依赖与您的设置和已安装的数据库客户端库文件,它们可能被支持或者不被支持。例如,mssql仅在Windows系统提供支持。odbc在Windows系统上是原生支持,而在Linux系统上通过<a href="http://www.unixodbc.org/" target="_top">UnixODBC library</a>支持。</p><p>在CoreSeek的分发版本中,python通过Python提供支持,在安装了Pythin的Windows系统和Linux系统上都可以支持。</p><h4>示例:</h4><pre><code><span><span><span><span>type</span></span></span><span> = mysql</span></span></code></pre><h3>11.1.2.&nbsp;sql_host:数据库服务器</h3><p>要连接的SQL服务器主机地址。必须选项,无默认值。仅对SQL数据源(mysql,&nbsp;pgsql,&nbsp;mssql)有效。</p><p>最简单的情形下,Sphinx与MySQL或PostgreSQL服务器安装在同一台主机上,此时您只须设置为localhost即可。注

意,MySQL客户端库根据主机名决定是通过TCP/IP还是UNIX
socket连接到服务器。一般来说,“localhost”使之强制使用UNIX
socket连接(这是默认的也是推荐的模式),而“127.0.01”会强制使用TCP/IP。细节请参考 MySQL manual</p><h4>示例:</h4><pre><span><span>sql_host</span></span> = localhost</pre><h3>11.1.3. sql_port:数据库端口</h3><p>要连接的SQL服务器的IP端口。可选选项,默认值为mysql端口3306,pgsql端口5432。仅适用于SQL数据源(mysql, pgsql, mssql)。注意,此选项是否实际被使用依赖于sql_host选项。</p><h4>示例:</h4><pre><span><span>sql_port</span></span> = <span><span>3306</span></span></pre><h3>11.1.4. sql_user:数据库用户名</h3><p>连接到sql_host时使用的SQL用户名。必须选项,无默认值。仅适用于SQL数据源(mysql, pgsql, mssql)。</p><h4>示例:</h4><pre><span><span>sql_user</span></span> = test</pre><h3>11.1.5. sql_pass:数据库密码</h3><p>连接到sql_host时使用的SQL用户密码。必须选项,无默认值。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><h4>示例:</h4><pre><span><span>sql_pass</span></span> = mysecretpassword</pre><h3>11.1.6. sql_db:数据库名称</h3><p>连接到SQL数据源之后使用的SQL数据库,此后的查询均在此数据库上进行。必须选项,无默认值。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><h4>示例:</h4><pre><span><span>sql_db</span></span> = test</pre><h3>11.1.7. sql_sock:数据库Socket文件</h3><p>连接到本地SQL服务器时使用的UNIX socket名称。可选选项,默认值为空(使用客户端库的默认设置)。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>在Linux上,通常是/var/lib/mysql/mysql.sock。 而在FreeBSD上通常是/tmp/mysql.sock。注意此选项是否实际被使用依赖与sql_host的设置。</p><h4>示例:</h4><pre><span><span>sql_sock</span></span> = /tmp/mysql.sock</pre><h3>11.1.8. mysql_connect_flags:MySQL连接参数</h3><p>MySQL客户端的连接标志(connection flags)。可选选项,默认值为0(不设置任何标志)。仅适用于mysql数据源。</p><p>此选项必须包含各标志相加所得的整型值。此整数将被原样传递给mysql_real_connect() 。 可用的标志在mysql_com.h中列举。下面列举的是几个与索引相关的标志和它们的值:</p><ul><li>CLIENT_COMPRESS = 32; 允许使用压缩协议 protocol</li><li>CLIENT_SSL = 2048; 握手后切换到SSL</li><li>CLIENT_SECURE_CONNECTION = 32768; 新的MySQL 4.1版本身份认证</li></ul><p>例如,标志2080(2048+32)代表同时使用压缩和SSL,32768代表仅使用新的身份验证。起初这个选项是为了在indexer和mysql位

于不同主机的情况下使用压缩协议而引入的。尽管降低了网络带宽消耗,但不管在理论上还是在现实中,在1Gbps的链路上启用压缩很可能恶化索引时间。然而

在100Mbps的连输上启用压缩可能会明显地改善索引时间(有报告说总的索引时间降低了20-30%)。根据您网络的连接情况,您获得的改善程度可能会
有所不同。</p><h4>示例:</h4><pre><span><span>mysql_connect_flags</span></span> = <span><span>32</span></span> <span><span># 启用压缩</span></span></pre><h3>11.1.9. mysql_ssl_cert, mysql_ssl_key, mysql_ssl_ca:MySQL的SSL连接</h3><p>连接MySQL服务器时使用的SSL认证选项。可选参数,默认值是空串(即不使用SSL认证)。 仅适用于mysql数据源。</p><p>这些指令用来在indexer和MySQL之间建立安全的SSL连接。关于怎样建立认证机制和设置MySQL服务器的信息可以参考MySQL文档。</p><h4>示例:</h4><pre><span><span>mysql_ssl_cert</span></span> = /etc/ssl/client-cert.pem
<span><span>mysql_ssl_key</span></span> = /etc/ssl/client-key.pem
<span><span>mysql_ssl_ca</span></span> = /etc/ssl/cacert.pem
</pre><h3>11.1.10. odbc_dsn:ODBC连接字符串(DSN)</h3><p>要连接的ODBC DSN。必须选项,没有默认值。 仅适用于odbc数据源。</p><p>DBC DSN(数据源名字,Data Source Name)指定了连接ODBC数据源时使用的认证选项(主机地址,用户名,密码等)。具体的格式与ODBC的具体驱动有关。</p><h4>示例:</h4><pre><span><span>odbc_dsn</span></span> = Driver={Oracle ODBC Driver};Dbq=myDBName;Uid=myUsername;Pwd=myPassword</pre><h3>11.1.11. sql_query_pre:待索引数据获取前查询</h3><p>索引数据获取前执行的查询(pre-fetch query),或预查询(pre-query)。多值选项,可选选项,默认为一个空的查询列表。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>多值意思是您可以多次设置该指令,从而指定多个预查询。它们在索引数据获取查询sql_query之前执行,而且会严格按照在配置文件中出现的顺序执行。预查询的结果会被忽略。</p><p>预查询在很多时候有用。它们被用来设置字符集编码,标记待索引的记录,更新内部计数器,设置SQL服务器连接选项和变量等等。</p><p>也许预查询最常用的一个应用就是用来指定服务器返回行时使用的字符编码。这必须与Sphinx期待的编码相同(在charset_type 和charset_table 选项中设置)。以下是两个与MySQL有关的设置示例:</p><pre><span><span>sql_query_pre</span></span> = SET CHARACTER_SET_RESULTS=cp1251
<span><span>sql_query_pre</span></span> = SET NAMES utf8
</pre><p>对于MySQL数据源,在预查询中禁用查询缓冲(query cache)(仅对indexer连接)是有用的,因为索引查询一般并会频繁地重新运行,缓冲它们的结果是没有意义的。这可以按如下方法实现:</p><pre><span><span>sql_query_pre</span></span> = SET SESSION query_cache_type=<span><span>OFF</span></span></pre><p> </p><h4>示例:</h4><pre><span><span>sql_query_pre</span></span> = SET NAMES utf8
<span><span>sql_query_pre</span></span> = SET SESSION query_cache_type=<span><span>OFF</span></span>
</pre><h3>11.1.12. sql_query:获取待索引数据查询</h3><p>获取即将索引的文档(数据)的主查询。必须的选项,无默认选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>只能有一个主查询。它被用来从SQL服务器获取文档(文档列表)。可以指定多达32个全文数据字段(严格来说是在sphinx.h中定义的SPH_MAX_FIELDS个)和任意多个属性。所有既不是文档ID(第一列)也不是属性的列的数据会被用于建立全文索引。</p><p>文档ID必须是第一列,而且必须是唯一的正整数值(不能是0也不能是负数),既可以是32位的也可以是64位的,这要根据Sphinx是如何被构建的,默认情况下文档ID是32位的,但在运行configure脚本时指定--enable-id64选项会打开64位文档ID和词ID的支持。</p><h4>示例:</h4><pre>sql_query = \
<span><span>SELECT</span></span> <span><span>id</span></span>, <span><span>group_id</span></span>, <span><span>UNIX_TIMESTAMP</span></span>(date_added) <span><span>AS</span></span> date_added, \
title, <span><span>content</span></span> \
<span><span>FROM</span></span> documents
</pre><h3>11.1.13. sql_joined_field:SQL连接字段设置</h3><p>连接/有效载荷字段获取查询。 多值选项,可选,默认值为空。 仅对SQL数据源有效 (mysql, pgsql, mssql) .</p><p>sql_joined_field 提供两种不同的方式:连接字段,或者有效载荷(有效载荷字段)。其语法格式如下:</p><pre>sql_joined_field = FIELD-NAME <span><span>'from'</span></span> ( <span><span>'query'</span></span> | <span><span>'payload-query'</span></span> ); \
QUERY [ ; RANGE-QUERY ]
</pre><p>where</p><ul><li>FIELD-NAME 是 连接/有效载荷 字段名称;</li><li>QUERY 是一个用于获取数据到索引的SQL查询.</li><li>RANGE-QUERY 是一个可选的用于获取范围知道索引的SQL查询. (版本2.0.1-beta增加.)</li></ul><p> </p><p>Joined fields let you avoid JOIN and/or
GROUP_CONCAT statements in the main document fetch query (sql_query).
This can be useful when SQL-side JOIN is slow, or needs to be offloaded
on Sphinx side, or simply to emulate MySQL-specific GROUP_CONCAT
funcionality in case your database server does not support it.</p><p>The query must return exactly 2 columns: document ID, and
text to append to a joined field. Document IDs can be duplicate, but
they must be in ascending order. All the text rows
fetched for a given ID will be concatented together, and the
concatenation result will be indexed as the entire contents of a joined
field. Rows will be concatenated in the order returned from the query,
and separating whitespace will be inserted between them. For instance,
if joined field query returns the following rows:</p><pre>( <span><span>1</span></span>, 'red' )
( <span><span>1</span></span>, 'right' )
( <span><span>1</span></span>, 'hand' )
( <span><span>2</span></span>, 'mysql' )
( <span><span>2</span></span>, 'sphinx' )
</pre><p>then the indexing results would be equivalent to that of
adding a new text field with a value of ‘red right hand’ to document 1
and ‘mysql sphinx’ to document 2.</p><p>Joined fields are only indexed differently. There are no other differences between joined fields and regular text fields.</p><p>Starting with 2.0.1-beta, ranged queries can
be used when a single query is not efficient enough or does not work
because of the database driver limitations. It works similar to the
ranged queries in the main indexing loop, 参见 第 3.7 节 “区段查询”. The range will be queried for and fetched upfront once, then multiple queries with different $start&nbsp;and&nbsp;$endsubstitutions will be run to fetch the actual data.</p><p>Payloads let you create a special field in
which, instead of keyword positions, so-called user payloads are stored.
Payloads are custom integer values attached to every keyword. They can
then be used in search time to affect the ranking.</p><p>The payload query must return exactly 3 columns: document ID;
keyword; and integer payload value. Document IDs can be duplicate, but
they must be in ascending order. Payloads must be
unsigned integers within 24-bit range, ie. from 0 to 16777215. For
reference, payloads are currently internally stored as in-field keyword
positions, but that is not guaranteed and might change in the future.</p><p>Currently, the only method to account for payloads is to use
SPH_RANK_PROXIMITY_BM25 ranker. On indexes with payload fields, it will
automatically switch to a variant that matches keywords in those fields,
computes a sum of matched payloads multiplied by field wieghts, and
adds that sum to the final rank.</p><h4>示例:</h4><pre>sql_joined_field = \
tagstext from query; \
<span><span>SELECT</span></span> docid, <span><span>CONCAT</span></span>(<span><span>'tag'</span></span>,tagid) <span><span>FROM</span></span> tags <span><span>ORDER</span></span> <span><span>BY</span></span> docid <span><span>ASC</span></span>
</pre><h3>11.1.14. sql_query_range:分区查询范围</h3><p>分区查询设置。可选选项,默认为空。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>设置这个选项会启用文档的区段查询(参看第 3.7 节 “区段查询”)。分区段查询有助于避免在索引大量数据时发生MyISAM表臭名昭著的死锁问题。(同样有助于解决其他不那么声名狼藉的问题,比如大数据集上的性能下降问题,或者InnoDB对多个大型读事务(read transactions)进行序列化时消耗额外资源的问题。)</p><p>此选项指定的查询语句必须获取用于分区的最小和最大文档ID。它必须返回正好两个整数字段,先是最小ID然后是最大ID,字段的名字会被忽略。</p><p>当启用了分区段查询时,sql_query要求包括$start&nbsp;和&nbsp;$end宏(因为重复多次索引整个表显然是个错误)。注意,$start&nbsp;..&nbsp;$end所指定的区间不会重叠,因此不会在查询中删除ID正好等于$start&nbsp;或&nbsp;$end的文档。第 3.7 节 “区段查询”中的例子解释了这个问题,注意大于等于或小于等于比较操作是如何被使用的。</p><h4>示例:</h4><pre>sql_query_range = <span><span>SELECT</span></span> <span><span>MIN</span></span>(<span><span>id</span></span>),<span><span>MAX</span></span>(<span><span>id</span></span>) <span><span>FROM</span></span> documents</pre><h3>11.1.15. sql_range_step:分区查询步进值</h3><p>区段查询的步进值。可选选项,默认为1024。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>仅当启用ranged queries 时有效。用sql_query_range 取得的文档ID区间会被以这个不小的间隔步数跳跃遍历。例如,如果取得的最小和最大ID分别是12和3456,而间隔步数是1000,那么indexer会用下面这些值重复调用几次sql_query:</p><ul><li>$start=12, $end=1011</li><li>$start=1012, $end=2011</li><li>$start=2012, $end=3011</li><li>$start=3012, $end=3456</li></ul><p> </p><h4>示例:</h4><pre><span><span>sql_range_step</span></span> = <span><span>1000</span></span></pre><h3>11.1.16. sql_query_killlist:Kill-list查询</h3><p>用于得到Kill-list的查询。可选选项,默认为空(不设定查询)。 仅适用于SQL数据源(mysql, pgsql, mssql)。 版本0.9.9-rc1引入.</p><p>这个查询返回的结果集应该只有一列,每行是一个文档ID。返回的这些文档ID将被存储在一个索引里。根据查询中提到的索引的顺序,一个索引的kill-list会抑制来自其他(顺序在其前面)索引的结果。这个设计的目的是要帮助用户实现在现有索引上的删除或者更新,而不用重建索引(甚至根本不用访问这个索引),尤其是为了结果解决“幽灵结果”问题。</p><p>让我们来分析一个实际的例子。假设我们有两个索引,‘main’和‘delta’。假设文档2、3和5在上一次重建索引‘main’的时候就被删除

了,而文档7和文档11则被更新了(即他们的文字内容发生了变化)。假设在建立索引‘main’的时候,关键字‘test’在所有这些提到的文档中都出现
了。而当我们建立索引‘delta’的时候文档7中也出现了关键字‘test’,但是文档11中不再有关键字‘test’了。现在我们重新建立索引
‘delta’,然后以合适的顺序(较旧的排在较新的之前)对这两个索引进行检索:</p><pre>$res = $cl->Query ( <span><span>"test"</span></span>, <span><span>"main delta"</span></span> );</pre><p> </p><p>首先,我们要正确地处理删除的情况。结果集合不应该包含文档2、3或5。其次,我们也要避免出现幽灵结果。如果我们不做点什么,文档11就会出现在搜索结果中。因为它会被在‘main’中查到(但在‘delta’中查不到它),并出现在最终的结果集合中,除非我们做点什么防止这种情况的发生。</p><p>Kill-list,或者缩写成K-list就是我们要做的。附加在‘delta’索引上的Kill-list会屏蔽掉前面所有各索引中检索到的特定行,在这个例子中,也就是‘main’中的行。因此,想要得到预期的结果,我们应该将更新了的和删除了的文档ID都放进Kill-list。</p><h4>示例:</h4><pre>sql_query_killlist = \
<span><span>SELECT</span></span> <span><span>id</span></span> <span><span>FROM</span></span> documents <span><span>WHERE</span></span> updated_ts>=@last_reindex <span><span>UNION</span></span> \
<span><span>SELECT</span></span> <span><span>id</span></span> <span><span>FROM</span></span> documents_deleted <span><span>WHERE</span></span> deleted_ts>=@last_reindex
</pre><h3>11.1.17. sql_attr_uint:整数属性</h3><p>声明无符号整数属性(attribute)。可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>被声明的列的值必须在32位无符号整型可表示的范围内。超出此范围的值也会被接受,但会溢出。例如-1会变成 2^32-1 或者说4,294,967,295。</p><p>您可以在属性名后面附加“:BITCOUNT”(见下面的示例)以便指定整型属性的位数。属性小于默认32位(此时称为位域)会有损性能。但它们在外部存储(extern storage)模式下可以节约内存:这些位域被组合成32位的块存储在.spa属性数据文件中。如果使用内联存储(inline storage),则位宽度的设置会被忽略。</p><h4>示例:</h4><pre><span><span>sql_attr_uint</span></span> = group_id
<span><span>sql_attr_uint</span></span> = forum_id:<span><span>9</span></span> # <span><span>9</span></span> bits for forum_id
</pre><h3>11.1.18. sql_attr_bool:布尔属性</h3><p>声明布尔属性(attribute)。可声明同一类型的多个不同名称的属性,可选项。仅适用于SQL数据源(mysql和pgsql)。 仅适用于SQL数据源(mysql, pgsql, mssql)。 等价于用sql_attr_uint声明为1位。</p><h4>示例:</h4><pre><span><span>sql_attr_bool</span></span> = is_deleted <span><span># 将被编码为1个bit</span></span></pre><h3>11.1.19. sql_attr_bigint:长整型属性</h3><p>64位整数属性(attribute)声明。多个值(可以同时声明多个属性),可选选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。 注意,与sql_attr_uint不同,这些值是有符号的。于版本0.9.9-rc1引入。</p><h4>示例:</h4><pre><span><span>sql_attr_bigint</span></span> = my_bigint_id</pre><h3>11.1.20. sql_attr_timestamp:UNIX时间戳属性</h3><p>声明UNIX时间戳属性(attribute)。可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>这个列的值必须是UNIX格式的时间戳,即32位无符号整数表示的自格林尼治平时1970年1月1日午夜起过去的秒数。时间戳在内部是按整数值存储
和处理的。但除了将时间戳按整数使用,还可以对它们使用多种与日期相关的函数——比如时间段排序模式,或为分组(GROUP
BY)抽取天/星期/月/年。注意MySQL中的DATE和DATETIME列类型不能直接作为时间戳使用,必须使用UNIX_TIMESTAMP函数将这些列做显式转换。</p><p>请注意MySQL的DATE或者DATETIME字段类型不能直接在Sphinx之中作为timestamp属性使用;如果这样的字段需要在Sphinx中进行范围过滤,在sql_query中你需要明确使用MySQL的UNIX_TIMESTAMP函数来转换这样的字段。</p><p>还必须注意的是UNIX时间戳不支持1970年1月1日之前的日期,在MySQL中使用UNIX_TIMESTAMP()时将不会返回预期的结果。
如果你只需要处理日期而不是时间(小时或者分钟或者秒),可以考虑使用MySQL的TO_DAYS()函数(从年份0开始的天数)。</p><h4>示例:</h4><pre>sql_attr_timestamp = UNIX_TIMESTAMP(<span><span>added_datetime</span></span>) AS added_ts</pre><h3>11.1.21. sql_attr_str2ordinal:字符串序数排序属性</h3><p>声明字符串序数属性(属性 )。可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>这个属性类型(简称为字串序数)的设计是为了允许按字符串值排序,但不存储字符串本身。对字串序数做索引时,字符串值从数据库中取出、暂存、排序然后用它们在该有序数组中的序数代替它们自身,因此字串序数是个整型,对它们的大小比较与在原字串上做字典序比较结果相同。</p><p>早期版本上,对字串序数做索引可能消耗大量的RAM。自svn r1112起,字串序数的积累和排序也可在固定大小的内存中解决了(代价是额外的临时磁盘空间),并受 mem_limit 设置限制。</p><p>理想中字符串可以根据字符编码和本地字符集(locale)排序。例如,如果已知字符串为KOI8R编码下的俄语字串,那么对字节

0xE0,0xE1和0xE2排序结果应为0xE1,0xE2和0xE0,因为0xE0在KOI8R中代表的字符明显应在0xE1和0xE2之后。但很不
幸,Sphinx目前不支持这个功能,而是简单地按字节值大小排序。</p><p>请注意,这里的序号是每个索引根据自身数据计算的,因此在同时读取多个索引事实无法同时保留正确的顺序进行合并的。处理后的字符串被替换为处理时其
在索引中的序列号,但是不同的索引具有不同的字符串集。例如,如果’main’索引包含字符串”aaa”, “bbb”, “ccc”, 直到
“zzz”,它们将会被分别分配数值为1,2,3,直到26。但是’delta’如果仅包含”zzz”,则会被分配数值1。那么在合并后,该顺序将被打
乱。不幸的是,在不存储原始字符串的情况下,这个问题无法解决(一旦存储原始字符串,序号将没有任何用处了)。</p><h4>示例:</h4><pre><span><span>sql_attr_str2ordinal</span></span> = author_name</pre><h3>11.1.22. sql_attr_float:浮点数属性</h3><p>声明浮点型属性 attribute 。 可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>属性值按单精度32位IEEE754格式存储。可表示的范围大约是1e-38到1e+38。可精确表示的小数大约是7位。浮点属性的一个重要应用是存储经度和纬度值(以角度为单位),经纬度值在查询时的地理位置距离计算中有用。</p><h4>示例:</h4><pre><span><span>sql_attr_float</span></span> = lat_radians
<span><span>sql_attr_float</span></span> = long_radians
</pre><h3>11.1.23. sql_attr_multi:多值属性(MVA)属性</h3><p>声明多值属性(多值属性 ,MVA)). 可声明同一类型的多个不同名称的属性,可选项。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>简单属性每篇文档只允许一个值。然而有很多情况(比如tags或者类别)需要将多个值附加给同一个属性,而且要对这个属性值列表做过滤或者分组。</p><p>声明格式如下(用反斜线只是为了清晰,您仍可以在一行之内完成声明):</p><pre>sql_attr_multi = ATTR-TYPE ATTR-NAME <span><span>'from'</span></span> <span><span>SOURCE</span></span>-TYPE \
[;QUERY] \
[;RANGE-QUERY]
</pre><p>其中</p><ul><li>ATTR-TYPE 是 ‘uint’ 或者 ‘timestamp’ 之一</li><li>SOURCE-TYPE 是 ‘field’, ‘query’, 或者 ‘ranged-query’ 之一</li><li>QUERY 是用来取得全部(文档ID,属性值)序对的SQL查询</li><li>RANGE-QUERY 是用来取得文档ID的最小值与最大值的SQL查询,与’sql_query_range‘类似</li></ul><p> </p><h4>示例:</h4><pre>sql_attr_multi = uint tag from query; <span><span>SELECT</span></span> <span><span>id</span></span>, tag <span><span>FROM</span></span> tags
sql_attr_multi = uint tag <span><span>from</span></span> ranged-<span><span>query</span></span>; \
<span><span>SELECT</span></span> <span><span>id</span></span>, tag <span><span>FROM</span></span> tags <span><span>WHERE</span></span> <span><span>id</span></span>>=$<span><span>start</span></span> <span><span>AND</span></span> <span><span>id</span></span>&lt;=$<span><span>end</span></span>; \
<span><span>SELECT</span></span> <span><span>MIN</span></span>(<span><span>id</span></span>), <span><span>MAX</span></span>(<span><span>id</span></span>) <span><span>FROM</span></span> tags
</pre><h3>11.1.24. sql_attr_string:字符串属性(可返回原始文本信息)</h3><p>字符串属性定义。 多值选项(即可以有一个或多个这样子的定义),可选项。仅对SQL数据源类型有效 (mysql, pgsql, mssql) 。 版本2.0.1-beta引入。</p><p>String attributes can store arbitrary strings attached to every document. There’s a fixed size limit of 4 MB per value. Also, searchd will currently cache all the values in RAM, which is an additional implicit limit.</p><p>As of 1.10-beta, strings can only be used for storage and
retrieval. They can not participate in expressions, be used for
filtering, sorting, or grouping (ie. in WHERE, ORDER or GROUP clauses).
Note that attributes declared using sql_attr_string will not be full-text indexed; you can use sql_field_string directive for that.</p><h4>示例:</h4><pre><span><span>sql_attr_string</span></span> = title <span><span># will be stored but will not be indexed</span></span></pre><h3>11.1.25. sql_attr_str2wordcount:文档词汇数记录属性</h3><p>词汇数属性定义。多值选项(即可以有一个或多个这样子的定义),可选项。仅对SQL数据源类型有效 (mysql, pgsql, mssql) 。 版本2.0.1-beta引入。</p><p>Word-count attribute takes a string column, tokenizes it
according to index settings, and stores the resulting number of tokens
in an attribute. This number of tokens (“word count”) is a normal
integer that can be later used, for instance, in custom ranking
expressions (boost shorter titles, help identify exact field matches,
etc).</p><h4>示例:</h4><pre><span><span>sql_attr_str2wordcount</span></span> = title_wc</pre><h3>11.1.26. sql_column_buffers:结果行缓冲大小</h3><p>每行缓冲大小。 可选项,默认值为空(自动计算大小)。 仅对SQL数据源类型有效 (mysql, pgsql, mssql) 。 版本2.0.1-beta引入。</p><p>ODBC and MS SQL drivers sometimes can not return the maximum
actual column size to be expected. For instance, NVARCHAR(MAX) columns
always report their length as 2147483647 bytes to indexer even
though the actually used length is likely considerably less. However,
the receiving buffers still need to be allocated upfront, and their
sizes have to be determined. When the driver does not report the column
length at all, Sphinx allocates default 1 KB buffers for each non-char
column, and 1 MB buffers for each char column. Driver-reported column
length also gets clamped by an upper limie of 8 MB, so in case the
driver reports (almost) a 2 GB column length, it will be clamped and a 8
MB buffer will be allocated instead for that column. These hard-coded
limits can be overridden using the sql_column_buffers directive,
either in order to save memory on actually shorter columns, or overcome
the 8 MB limit on actually longer columns. The directive values must be
a comma-separated lists of selected column names and sizes:</p><pre>sql_column_buffers = <span><span><</span><span><span><span>colname</span></span></span><span>></span></span>=<span><span><</span><span><span><span>size</span></span></span><span>></span></span>[K|M] [, ...]</pre><p> </p><h4>示例:</h4><pre><span><span>sql_query</span></span> = SELECT id, mytitle, mycontent FROM documents
<span><span>sql_column_buffers</span></span> = mytitle=<span><span>64</span></span>K, mycontent=<span><span>10</span></span>M
</pre><h3>11.1.27. sql_field_string:字符串字段(可全文搜索,可返回原始文本信息)</h3><p>组合字符串属性和全文字段定义。 Combined string attribute and full-text field declaration. 多值选项(即可以有一个或多个这样子的定义),可选项。 仅对SQL数据源类型有效 (mysql, pgsql,mssql) 。 版本2.0.1-beta引入。</p><p>sql_attr_string only
stores the column value but does not full-text index it. In some cases
it might be desired to both full-text index the column and store it as
attribute. sql_field_string lets you do exactly that. Both the field and the attribute will be named the same.</p><h4>示例:</h4><pre><span><span>sql_field_string</span></span> = title <span><span># will be both indexed and stored</span></span></pre><h3>11.1.28. sql_field_str2wordcount:文档词汇数记录字段(可全文搜索,可返回原始信息)</h3><p>组合词汇数属性与全文字段定义。 多值选项(即可以有一个或多个这样子的定义),可选项。 仅对SQL数据源类型有效 (mysql, pgsql, mssql) 。 版本2.0.1-beta引入。</p><p>sql_attr_str2wordcount only
stores the column word count but does not full-text index it. In some
cases it might be desired to both full-text index the column and also
have the count.sql_field_str2wordcount lets you do exactly that. Both the field and the attribute will be named the same.</p><h4>示例:</h4><pre><span><span>sql_field_str2wordcount</span></span> = title <span><span># will be indexed, and counted/stored</span></span></pre><h3>11.1.29. sql_file_field:外部文件字段</h3><p>实际数据存储于文件的字段定义。 仅对SQL数据源类型有效 (mysql, pgsql, mssql) 。 版本2.0.1-beta引入。</p><p>This directive makes indexer interpret field contents as a file name, and load and index the referred file. Files larger than max_file_field_buffer in
size are skipped. Any errors during the file loading (IO errors, missed
limits, etc) will be reported as indexing warnings and will not early terminate the indexing. No content will be indexed for such files.</p><h4>示例:</h4><pre>sql_file_field = my_file_path # <span><span>load</span></span> <span><span>and</span></span> index files referred to by my_file_path</pre><h3>11.1.30. sql_query_post:数据获取后查询</h3><p>取后查询。可选项,默认值为空。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>此查询在sql_query成功执行后立即执行。如果取后取查询产生了错误,该错误被当作警告被报告,但索引不会因此终止。取后查询的结果会被忽略。注意当取后查询执行时索引还尚未完成,而后面的索引仍然可能失败。因此在这个查询中不应进行任何永久性的更新。例如,不应在此查询中更新辅助表中存储的最近成功索引的文档ID值,请在后索引查询(索引后查询sql_query_post_index )中操作。</p><h4>示例:</h4><pre><span><span>sql_query_post</span></span> = DROP TABLE my_tmp_table</pre><h3>11.1.31. sql_query_post_index:数据索引后查询</h3><p>索引后查询。可选项,默认值为空。 仅适用于SQL数据源(mysql, pgsql, mssql)。</p><p>此查询在索引完全成功结束后执行。如果此查询产生错误,该错误会被当作警告报告,但索引不会因此而终止。该查询的结果集被忽略。此查询中可以使用宏$maxid,它会被扩展为索引过程中实际得到的最大的文档ID。如果没有文档被索引,则$maxid会设置为0。</p><h4>示例:</h4><pre>sql_query_post_index = <span><span>REPLACE</span></span> <span><span>INTO</span></span> counters ( <span><span>id</span></span>, val ) \
<span><span>VALUES</span></span> ( <span><span>'max_indexed_id'</span></span>, $maxid )</code></pre><h3>11.1.32.&nbsp;sql_ranged_throttle:分区查询间隔时间</h3><p>分区查询的间隔时间(throttling),单位是毫秒。可选选项,默认值为0(无间隔时间)。 仅适用于SQL数据源(mysql,&nbsp;pgsql,&nbsp;mssql)。</p><p>此选项旨在避免indexer对数据库服务器构成了太大的负担。它会使indexer在每个分区查询的步之后休眠若干毫秒。休眠无条件执行,并在取结果的查询之前执行。</p><h4>示例:</h4><pre><code>sql_ranged_throttle = <span><span>1000</span></span> # sleep <span><span>for</span></span> <span><span>1</span></span> sec before <span><span>each</span></span> query <span><span>step</span></span></code></pre><h3>11.1.33.&nbsp;sql_query_info_pre:命令行信息获取前查询</h3><p>命令行查询前查询。 可选选项,默认为空。 仅对&nbsp;mysql&nbsp;数据源有效。</p><p>仅被命令行搜索所用,用来在命令行查询之前执行查询,一般用于设置查询的字符集编码</p><h4>示例:</h4><pre><code><span><span>sql_query_info_pre</span></span> = SET NAMES utf8</code></pre><h3>11.1.34.&nbsp;sql_query_info:命令行信息获取查询</h3><p>文档信息查询。 可选选项,默认为空。 仅对&nbsp;mysql&nbsp;数据源有效。</p><p>仅被命令行搜索所用,用来获取和显示文档信息,目前仅对MySQL有效,且仅用于调试目的。此查询为每个文档ID获取CLI搜索工具要显示的文档信息。 它需要包含$id宏,以此来对应到查询的文档的ID。</p><h4>示例:</h4><pre>sql_query_info = <span><span>SELECT</span></span> * <span><span>FROM</span></span> documents <span><span>WHERE</span></span> <span><span>id</span></span>=$<span><span>id</span></span></pre><h3>11.1.35. xmlpipe_command:数据获取命令</h3><p>调用xmlpipe流提供者的Shell命令。必须选项。仅对xmlpipe 和 xmlpipe2数据源有效。</p><p>指定的命令会被运行,其输出被当作XML文档解析。具体格式描述请参考 第 3.8 节 “xmlpipe 数据源” 和 第 3.9 节 “xmlpipe2 数据源” 。</p><h4>示例:</h4><pre><span><span>xmlpipe_command</span></span> = cat /home/sphinx/test.xml</pre><h3>11.1.36. xmlpipe_field:字段设置</h3><p>声明xmlpipe数据字段。可声明同一类型的多个不同名称的属性,可选项。仅对xmlpipe2数据源有效。参考 第 3.9 节 “xmlpipe2 数据源”.</p><h4>示例:</h4><pre><span><span>xmlpipe_field</span></span> = subject
<span><span>xmlpipe_field</span></span> = content
</pre><h3>11.1.37. xmlpipe_field_string:字符串字段</h3><p>xmlpipe字段和字符串属性定义。 多值,可选项。 仅对 xmlpipe2 数据源来性有效。参见 第 3.9 节 “xmlpipe2 数据源”. 版本2.0.1-beta引入。</p><p>Makes the specified XML element indexed as both a full-text
field and a string attribute. Equivalent to <sphinx:field
name=”field” attr=”string”/> declaration within the XML file.</p><h4>示例:</h4><pre><span><span>xmlpipe_field_string</span></span> = subject</pre><h3>11.1.38. xmlpipe_field_wordcount:词汇数存储字段</h3><p>xmlpipe字段和词汇数属性定义。 多值,可选项。 仅对 xmlpipe2 数据源来性有效。参见 第 3.9 节 “xmlpipe2 数据源”. 版本2.0.1-beta引入。</p><p>Makes the specified XML element indexed as both a full-text
field and a word count attribute. Equivalent to <sphinx:field
name=”field” attr=”wordcount”/> declaration within the XML file.</p><h4>示例:</h4><pre><span><span>xmlpipe_field_wordcount</span></span> = subject</pre><h3>11.1.39. xmlpipe_attr_uint:整数属性</h3><p>声明xmlpipe整型属性。可声明同一类型的多个不同名称的属性,可选项。仅对xmlpipe2数据源有效。语法与 sql_attr_uint相同。</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_uint</span></span> = author</pre><h3>11.1.40. xmlpipe_attr_bool:布尔属性</h3><p>声明xmlpipe布尔型属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2数据源有效。语法与 sql_attr_bool相同。</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_bool</span></span> = is_deleted <span><span># will be packed to 1 bit</span></span></pre><h3>11.1.41. xmlpipe_attr_timestamp:UNIX时间戳属性</h3><p>声明xmlpipe UNIX时间戳属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2数据源有效。语法与 sql_attr_timestamp相同。</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_timestamp</span></span> = published</pre><h3>11.1.42. xmlpipe_attr_str2ordinal:字符串序列属性</h3><p>声明xmlpipe字符序数属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2数据源有效。语法与 sql_attr_str2ordinal相同。</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_str2ordinal</span></span> = author_sort</pre><h3>11.1.43. xmlpipe_attr_float:浮点数属性</h3><p>声明xmlpipe浮点型属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2数据源有效。语法与 sql_attr_float相同。</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_float</span></span> = lat_radians
<span><span>xmlpipe_attr_float</span></span> = long_radians
</pre><h3>11.1.44. xmlpipe_attr_multi:多值属性</h3><p>声明xmlpipe MVA属性。可声明同一类型的多个不同名称的属性,可选项。 仅对xmlpipe2数据源有效。</p><p>这个选项为xmlpipe2流声明一个MVA属性标签。该标签的内容会被试图解析成一个整型值的列表(数组),此列表构成一个MVA属性值,这与把MVA属性的数据源设置为“字段”时sql_attr_multi分析SQL列内容的方式类似。</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_multi</span></span> = taglist</pre><h3>11.1.45. xmlpipe_attr_string:字符串属性</h3><p>xmlpipe字符串定义。 多值,可选项。 Applies to xmlpipe2 source type only. 版本2.0.1-beta引入。</p><p>This setting declares a string attribute tag in xmlpipe2
stream. The contents of the specified tag will be parsed and stored as a
string value.</p><h4>示例:</h4><pre><span><span>xmlpipe_attr_string</span></span> = subject</pre><h3>11.1.46. xmlpipe_fixup_utf8:UTF-8修复设置</h3><p>在Sphinx端进行UTF-8验证和过滤,防止XML分析器因为碰上非UTF-8文档而犯疯卡死。可选选项,默认值为0。只适用于xmlpipe2数据源。 仅对xmlpipe2数据源有效。</p><p>在某些特定情况下很难甚至不可能保障输入的xmlpipe2文档体都是完美有效一致的UTF-8编码。例如,输入流中可能溜进一些特定国家的单字节
编码文本。Libexpat这个XML分析器非常脆弱,遇到这种情况就会停止工作。UTF-8修复(UTF-8
fixup)功能能让这种情况得到避免。当启动了修复选项的时候,Sphinx会对输入留进行预处理,其后再传给XML分析器,其间非法的UTF-8序列
全部被替换成空格。</p><h4>示例:</h4><pre><span><span>xmlpipe_fixup_utf8</span></span> = <span><span>1</span></span></pre><h3>11.1.47. mssql_winauth:Windows集成认证</h3><p>标志位,代表是否使用MS SQL的windows身份认证。布尔型,可选选项,默认值是0(假)。只适用于mssql数据源。于版本0.9.9-rc1引入。</p><p>这个选项指出在连接到MS SQL Server时时候使用现在正登录的windows账户的凭据作来进行身份验证。注意当searchd作为服务运行时,账户的用户名可能与安装这个服务的账户不同。</p><h4>示例:</h4><pre><span><span>mssql_winauth</span></span> = <span><span>1</span></span></pre><h3>11.1.48. mssql_unicode:Unicode设置</h3><p>MS SQL编码类型标志位。布尔型,可选选项,默认值是0(假)。只适用于mssql数据源。于版本0.9.9-rc1引入。</p><p>这个选项指出在对MS SQL Server进行查询时,是使用Unicode还是单字节数据。这个标志位必须与charset_type指令同步,也就是说,要索引Unicode数据,则既要设置charset_type选项(设为‘utf-8’),又要设置数据源的mssql_unicode选项(设为1)。多说一句:MS SQL实质上返回UCS-2编码的数据,而不是UTF-8,但Sphinx可以自动处理这个情况。</p><h4>示例:</h4><pre><span><span>mssql_unicode</span></span> = <span><span>1</span></span></pre><h3>11.1.49. unpack_zlib:SQL数据源解压字段设置</h3><p>使用zlib(即gnuzip)来解压(unpack,deflate)的列。多个值,可选选项,默认值是列的空列表。仅适用于SQL数据源(mysql, pgsql, mssql)。于版本0.9.9-rc1引入。</p><p>indexer会使用标准zlib算法(称作deflate,gunzip也实现了这个算法)对这个选项指定的那些列进行解压缩。当建立索引的动作发生在数据库所在机器以外的机器时,这个选项会降低数据库的负载,并节约网络带宽。要想使用这个特性,就必须保证在建立时zlib和zlib-devel都是可用的。</p><h4>示例:</h4><pre><span><span>unpack_zlib</span></span> = col1
<span><span>unpack_zlib</span></span> = col2
</pre><h3>11.1.50. unpack_mysqlcompress:MySQL数据源解压字段设置</h3><p>使用MySQL UNCOMPRESS()算法解压的列。多个值,可选选项,默认值是列的空列表。仅适用于SQL数据源(mysql, pgsql, mssql)。于版本0.9.9-rc1引入。</p><p>indexer会使用MySQL
COMPRESS()和UNCOMPRESS()使用的修改过的zlib算法对这个选项指定的那些列进行解压缩。
当建立索引的动作发生在数据库所在机器以外的机器时,这个选项会降低数据库的负载,并节约网络带宽。要想使用这个特性,就必须保证在建立时zlib和
zlib-devel都是可用的。</p><h4>示例:</h4><pre><span><span>unpack_mysqlcompress</span></span> = body_compressed
<span><span>unpack_mysqlcompress</span></span> = description_compressed
</pre><h3>11.1.51. unpack_mysqlcompress_maxsize:MySQL数据源解压缓冲区设置</h3><p>用于UNCOMPRESS()解压后数据的缓冲区大小。可选选项,默认值是16M。于版本0.9.9-rc1引入。</p><p>当使用unpack_mysqlcompress选项时,由于实现方法本质上的限制,不可能减小缓冲区大小方面的需求。因此缓冲区必须预先分配好,解压出的数据也不能超过缓冲区大小。这个选项控制这个缓冲区大小值,既可以用于限制indexer的内存使用,也可以用于在需要的时候使解压非常大的数据变为可能。</p><h4>示例:</h4><pre><span><span>unpack_mysqlcompress_maxsize</span></span> = <span><span>1</span></span>M</pre><h2>11.2. 索引配置选项</h2><h3>11.2.1. type:索引类型设置</h3><p>索引类型。可用的值包括plain(普通本地索引)、distributed(分布式)或rt(实时索引)。可选选项,默认值为plain(索引为普通本地索引)。</p><p>Sphinx支持几种不同的索引类型。 版本0.9.x支持两种索引类型:普通本地索引--在本机上存储和处理,和分布式索引--不仅涉及本地搜索,而且同时通过网络向远程searchd实例做查询(查看第 5.8 节 “分布式搜索”了解详情)。 版本1.10-beta也增加了被称为实时索引(简称为RT索引)的索引类型,它也支持在本机上存储和处理,除此之外还支持全文索引数据的即时更新(查看第 4 章 RT实时索引了解详情)。 需要提醒的是attributes值在普通本地索引或者RT索引中都可以被即时更新。</p><p>你可以根据需要设置索引内行。索引默认是普通本地索引。</p><h4>示例:</h4><pre><span><span><span><span>type</span></span></span><span> = distributed</span></span></pre><h3>11.2.2. source:文档源</h3><p>向本地索引增加文档源。可以出现多次,必须选项。</p><p>为当前索引指定一个从中可以获取文档的文档源。必须至少有一个文档源。可以有多个文档源,任何数据源类型都可接受:即您可以从MySQL服务器中获取一部分数据,从PostgreSQL中获取另一部分,再在文件系统上使用xmlpipe2获取一部分。</p><p>然而,对源数据却有一些限制。首先,文档ID必须在所有源的总体上是唯一的。如果这个条件不满足,那可能导致非预期的搜索结果。其次,源的模式必须相同,以便在同一个索引中存储。</p><p>数据来源的ID不会被自动存储。因此,为了获知匹配的文档是从哪个数据源中来的,需要手工存储一些额外的信息。通常有两种方法:</p><ol><li>修改文档ID,将源ID编码进去:source src1
{
sql_query = SELECT id*10+1, ... FROM table1
...
}

source src2
{
sql_query = SELECT id*10+2, ... FROM table2
...
} </li><li>将数据来源存储为一个属性:source src1
{
sql_query = SELECT id, 1 AS source_id FROM table1
sql_attr_uint = source_id
...
}

source src2
{
sql_query = SELECT id, 2 AS source_id FROM table2
sql_attr_uint = source_id
...
} </li></ol><p> </p><h4>示例:</h4><pre><span><span>source</span></span> = srcpart1
<span><span>source</span></span> = srcpart2
<span><span>source</span></span> = srcpart3
</pre><h3>11.2.3. path:索引文件路径</h3><p>索引文件的路径和文件名(不包括扩展名)。必须选项。</p><p>path既包括文件夹也包括文件名,但不包括扩展名。indexer在产生永久和临时索引文件的最终名字时会附加上不同的扩展名。永久数据文件有几个不同的扩展名,都以“.sp”开头,临时文件的扩展名以“.tmp”开头。如果indexer没有成功地自动删除.tmp*文件,手工删除是安全的。</p><p>以下是不同索引文件所存储的数据种类,供参考:</p><ul><li>.spa 存储文档属性(仅在extern 文档信息存储模式中使用);</li><li>.spd 存储每个词ID可匹配的文档ID列表;</li><li>.sph 存储索引头信息;</li><li>.spi 存储词列表(词ID和指向.spd文件的指针);</li><li>.spk 存储kill-lists;</li><li>.spm 存储MVA数据;</li><li>.spp 存储每个词ID的命中(或者说记账,或者词的出现)列表;</li><li>.sps 存储字符串属性数据.</li></ul><p> </p><h4>示例:</h4><pre><span><span>path</span></span> = /var/<span><span><span><span>data</span></span></span><span>/test1</span></span></pre><h3>11.2.4. docinfo:文档信息存储模式</h3><p>文档信息(docinfo)的存储模式。可选选项,默认是“extern”,可用的值包括’none’, ‘extern’ 和 ‘inline’.。</p><p>此选项确切定义了文档信息在磁盘和RAM中的物理存储方式。“none”意思是根本不存储文档信息(没有任何属性)。通常并不需要显式设置为
“none”因为当没有配置任何属性时Sphinx会自动选择“none”。“inline”代表文档信息与文档ID列表一同存储在在.spd文件中。“extern”代表文档信息与文档ID分开(在外部)存储(在.spa文件中)。</p><p>基本上,外部存储的文档信息在查询时必须保持在内存中。这是性能的原因。因此有时候“inline”是唯一的选择。然而这种情况并不多见,文档信息默认是“extern”存储的。深入的探讨和RAM使用的估计请参见第 3.2 节 “属性”。</p><h4>示例:</h4><pre><span><span>docinfo</span></span> = inline</pre><h3>11.2.5. mlock:缓冲数据内存锁定</h3><p>已缓冲数据的内存锁定。可选选项,默认为0(不调用mlock())</p><p>为提高性能,searchd将.spa和.spi文件预取到内存中,并一直在内存中保存它们的拷贝。但如果一段时间内没有对该索引的搜索,则对这份缓冲的拷贝没有内存访问,而操作系统可能会决定将它交换到磁盘上去。对这些“冷却”了的索引的访问会导致其交换回内存并得到一个较大的延迟。</p><p>将mlock选项设置为1会使Sphinx使用mlock(2)系统调用将存储上述缓冲了的数据的系统内存锁定,这将避免内存交换(详情参见man 2 mlock)。mlock(2)是特权调用,因此可能需要searchd以root账户运行或通过其他办法赋予足够的权限。如果mlock()失败会发出警告,但索引会继续进行。</p><h4>示例:</h4><pre><span><span>mlock</span></span> = <span><span>1</span></span></pre><h3>11.2.6. morphology:词形处理</h3><p>词形处理器的列表。可选选项,默认为空(不使用任何词形处理器)。</p><p>词形处理器可以将待索引的词从各种形态变成基本的规则的形态。例如,英语词干提取器(English stemmer)可以将“dogs”和“dog”都变成“dog”,这使搜索这两个词的结果都相同。</p><p>内置的词形处理器包括英语词干提取器,俄语词干提取器(支持UTF-8和Windows-1251编码),Soundex和Metaphone。后面两个会将词替换成特殊的语音编码,这会使发音相近的词表示形式相同。Snowball 项目的libstemmer 库提供的额外词干提取器可以通过在编译期对configure 脚本使用--with-libstemmer选
项来启用。内建的英语和俄语词干提取器要比它们在libstemmer中的对应物模块运行更快,但它们的结果可能略有不同,因为内建的版本基于较旧的版
本。Metaphone基于Double Metaphone算法实现。Metaphone是 基于Double
Metaphone的算法和索引的主要代码实现的。</p><p>在morphology选项中可使用的内建值包括</p><ul><li>none – 不做任何词形处理,保持原样;</li><li>stem_en – 应用实现的英语词干;</li><li>stem_ru – 应用实现的俄语词干;</li><li>stem_enru – 应用实现的英语和俄语词干;</li><li>stem_cz – 应用实现的捷克语词干;</li><li>soundex – 用关键字的SOUNDEX编码取代它;</li><li>metaphone – 用关键字的METAPHONE编码取代它.</li></ul><p>libstemmer提供的额外值格式为“libstemmer_XXX”,XXX指libstemmer算法的代号。(完整列表参见libstemmer_c/libstemmer/modules.txt)</p><p>可以指定多个词干提取器(以逗号分隔)。这些提取器按列出的顺序应用于输入词串,整个处理会在第一个真正修改了原词的词干提取器之后停止。另外,当wordforms 特性启用时,词会现在词形字典中查询,如果词典中有对应的条目,那么词干提取器干脆不会被使用。换个说法,wordforms选项可以用来补充指定词干提取器的例外情况。</p><h4>示例:</h4><pre><span><span>morphology</span></span> = stem_en, libstemmer_sv</pre><h3>11.2.7. dict:关键字词典类型</h3><p>关键字词典的类型。 可用值为crc或者keywords。 可选项,默认为crc。 版本2.0.1-beta引入。</p><p>The default dictionary type in Sphinx, and the only one
available until version 2.0.1-beta, is a so-called CRC dictionary which
never stores the original keyword text in the index. Instead, keywords
are replaced with their control sum value (either CRC32 or FNV64,
depending whether Sphinx was built with --enable-id64) both when searching and indexing, and that value is used internally in the index.</p><p>That approach has two drawbacks. First, in CRC32 case there
is a chance of control sum collision between several pairs of different
keywords, growing quadratically with the number of unique keywords in
the index. (FNV64 case is unaffected in practice, as a chance of a
single FNV64 collision in a dictionary of 1 billion entries is
approximately 1:16, or 6.25 percent. And most dictionaries will be much
more compact that a billion keywords, as a typical spoken human language
has in the region of 1 to 10 million word forms.) Second, and more
importantly, substring searches are not directly possible with control
sums. Sphinx alleviated that by pre-indexing all the possible substrings
as separate keywords (参见 第 11.2.18 节 “min_prefix_len:最小索引前缀长度”第 11.2.19 节 “min_infix_len:最小索引中缀长度” directives).
That actually has an added benefit of matching substrings in the
quickest way possible. But at the same time pre-indexing all substrings
grows the index size a lot (factors of 3-10x and even more would not be
unusual) and impacts the indexing time respectively, rendering substring
searches on big indexes rather impractical.</p><p>Keywords dictionary, introduced in 2.0.1-beta, fixes both
these drawbacks. It stores the keywords in the index and performs
search-time wildcard expansion. For example, a search for a ‘test*’
prefix could internally expand to ‘test|tests|testing’ query based on
the dictionary contents. That expansion is fully transparent to the
application, except that the separate per-keyword statistics for all the
actually matched keywords would now also be reported.</p><p>Indexing with keywords dictionary should be 1.1x to 1.3x
slower compared to regular, non-substring indexing – but times faster
compared to substring indexing (either prefix or infix). Index size
should only be slightly bigger that than of the regular non-substring
index, with a 1..10% percent total difference Regular keyword searching
time must be very close or identical across all three discussed index
kinds (CRC non-substring, CRC substring, keywords). Substring searching
time can vary greatly depending on how many actual keywords match the
given substring (in other words, into how many keywords does the search
term expand). The maximum number of keywords matched is restricted by
the expansion_limitdirective.</p><p>Essentially, keywords and CRC dictionaries represent the two
different trade-off substring searching decisions. You can choose to
either sacrifice indexing time and index size in favor of top-speed
worst-case searches (CRC dictionary), or only slightly impact indexing
time but sacrifice worst-case searching time when the prefix expands
into very many keywords (keywords dictionary).</p><h4>示例:</h4><pre><span><span>dict</span></span> = keywords</pre><h3>11.2.8. index_sp:索引句子和段落信息</h3><p>是否检测并索引句子和段落边界。 可选值,默认为0(不检测和索引)。 版本2.0.1-beta引入。</p><p>This directive enables sentence and paragraph boundary
indexing. It’s required for the SENTENCE and PARAGRAPH operators to
work. Sentence boundary detection is based on plain text analysis, so
you only need to set index_sp = 1 to enable it. Paragraph detection is however based on HTML markup, and happens in the HTML stripper. So to index paragraph locations you also need to enable the stripper by specifying html_strip = 1. Both types of boundaries are detected based on a few built-in rules enumerated just below.</p><p>Sentence boundary detection rules are as follows.</p><ul><li>Question and excalamation signs (? and !) are always a sentence boundary.</li><li>Trailing dot (.) is a sentence boundary, except:

        
         
         When followed by a letter. That’s considered a part of an abbreviation (as in “S.T.A.L.K.E.R” or “Goldman Sachs S.p.A.”). 
         When followed by a comma. That’s considered an 

abbreviation followed by a comma (as in “Telecom Italia S.p.A., founded
in 1994″).

         When followed by a space and a small letter. That’s 

considered an abbreviation within a sentence (as in “News Corp.
announced in Februrary”).

         When preceded by a space and a capital letter, and 

followed by a space. That’s considered a middle initial (as in “John D.
Doe”).

         
        </li></ul><p>&nbsp;</p><p>Paragraph boundaries are inserted at every block-level HTML 

tag. Namely, those are (as taken from HTML 4 standard) ADDRESS,
BLOCKQUOTE, CAPTION, CENTER, DD, DIV, DL, DT, H1, H2, H3, H4, H5, LI,
MENU, OL, P, PRE, TABLE, TBODY, TD, TFOOT, TH, THEAD, TR, and UL.</p><p>Both sentences and paragraphs increment the keyword position counter by 1.</p><h4>示例:</h4><pre><span><span>index_sp</span></span> = <span><span>1</span></span></pre><h3>11.2.9. index_zones:索引标签区域信息</h3><p>字段内需要索引的HTML/XML区域的标签列表。 可选项,默认为空(不索引区域)。 版本2.0.1-beta引入。</p><p>Zones can be formally defined as follows. Everything between
an opening and a matching closing tag is called a span, and the
aggregate of all spans corresponding sharing the same tag name is called
a zone. For instance, everything between the occurrences of <H1>
and </H1> in the document field belongs to H1 zone.</p><p>Zone indexing, enabled by index_zones directive, is an optional extension of the HTML stripper. So it will also require that the stripper is enabled (with html_strip = 1). The value of theindex_zones should be a comma-separated list of those tag names and wildcards (ending with a star) that should be indexed as zones.</p><p>Zones can nest and overlap arbitrarily. The only requirement
is that every opening tag has a matching tag. You can also have an
arbitrary number of both zones (as in unique zone names, such as H1) and
spans (all the occurrences of those H1 tags) in a document. Once
indexed, zones can then be used for matching with the ZONE operator, 参见 第 5.3 节 “扩展查询语法”.</p><h4>示例:</h4><pre><span><span>index_zones</span></span> = h*, th, title</pre><h3>11.2.10. min_stemming_len:词干化最小词长</h3><p>启用词干化的最小词长。可选选项,默认为1(对任何词都进行词干化)。于版本0.9.9-rc1引入。</p><p>词干化方法并不完美,有时会产生用户不想要的结果。例如,如果用英语的Porter stemmer词干化算法处理关键词“gps”,得到的结果是“gp”,显然这是不对的。min_stemming_len这个特性允许根据词的长度来决定是否跳过词干化,即不对较短的词进行词干化。注意,词长等于这个选项设置的值的词会被词干化。因此要避免对3个字符长的关键词进行词干化,必须指定这个选项的值为4。要活的更细粒度的控制,请参考wordforms这个特性。</p><h4>示例:</h4><pre><span><span>min_stemming_len</span></span> = <span><span>4</span></span></pre><h3>11.2.11. stopwords:停止词</h3><p>停用词文件列表(空格分隔)。可选选项,默认为空。</p><p>停用词是不被索引的词。停用词表一般包括最常用的高频词,因为它们对搜索结果没有多大帮助却消耗很多处理资源。</p><p>可以指定多个文件名,用空格分隔。所有文件都会被载入。停用词文件的格式是简单的纯文本。其编码必须与charset_type选项所指定的索引编码相匹配。文件数据会根据charset_type选项的设置进行切分,因此您可以使用与待索引数据相同的分隔符。词干提取器(stemmers)也会在停用词文件的分析中使用。</p><p>尽管停用词不会被索引,它们却影响关键词的位置。例如,假设“the”是一个停用词,文档1包含一行“in office”,而文档2包含“in the office”。将“in office”作为确切词组搜索则只会得到文档1,虽然文档2里的the是停用的。</p><h4>示例:</h4><pre><span><span>stopwords</span></span> = /usr/local/sphinx/data/stopwords.txt
<span><span>stopwords</span></span> = stopwords-ru.txt stopwords-en.txt
</pre><h3>11.2.12. wordforms:词形字典</h3><p>词形字典。 可选选项,默认为空。</p><p>词形字典在输入文档根据charset_table
碎后使用。本质上,它使您可以将一个词替换成另一个。这通常被用来将不同的词形变成一个单一的标准形式(即将词的各种形态如
“walks”,“walked”,“walking”变为标准形式“walk”)。也可以用来实现取词根的例外情况,因为词形字典中可以找到的词不会经
过词干提取器的处理。</p><p>索引和搜索中的输入词都会利用词典做规则化。因此要使词形字典的更改起作用,需要重新索引并重启searchd。</p><p>Sphnix的词形支持被设计成可以很好地支持很大的字典。它们轻微地影响索引速度:例如,1M个条目的字典会使索引速度下降1.5倍。搜索速度则

完全不受影响。额外的内存占用大体上等于字典文件的大小,而且字典是被多个索引共享的,即如果一个50MB的词形字典文件被10个不同的索引使用了,那么
额外的searchd内存占用就是大约50MB。</p><p>字典文件的格式是简单的纯文本。每行包括一个源词形和一个目标词形,编码应与charset_type选项所指定的完全相同,二者用大于号分隔。文件载入时会经过charset_table选项指定的规则的处理。因此基本上在大小写是否敏感这个问题上它是与待索引的全文数据相同的,即通常是大小写无关的。一下是个文件内容的例子:</p><pre><span><span>walks</span></span> > walk
walked > walk
walking > walk
</pre><p> </p><p>我们提供了一个spelldump工具,它可以帮您从ispell 和 MySpell(OpenOffice提供)格式的.dict和.aff字典文件生成Sphinix可接受的格式。</p><p>从版本0.9.9-rc1开始,可以将好几个源词对应到同一个目标词上。由于这个过程作用于符号化之后的结果而不是原始文本,空白字符和标记语言都被忽略。</p><pre><span><span>core</span></span> <span><span>2</span></span> duo > c2d
e6600 > c2d
core 2duo > c2d
</pre><p> </p><p>Notice however that the destination wordforms are still always interpreted as a single keyword! Having a mapping like “St John > Saint John” will result in not matching
“St John” when searching for “Saint” or “John”, because the destination
keyword will be “Saint John” with a space character in it (and it’s
barely possible to input a destination keyword with a space).</p><h4>示例:</h4><pre>wordforms = <span><span>/usr/local</span></span><span><span>/sphinx/data</span></span><span><span>/wordforms.txt</span></span></pre><h3>11.2.13. exceptions:词汇特例处理</h3><p>Token特例文件。 可选选项,默认为空。</p><p>对于使用Coreseek的中文用户,这一选项无效。Coreseek为Sphinx贡献的中文分词法内置了Token特例化支持,具体参阅Coreseek MMSeg分词法的文档。不过,值得高兴的是,Token特例化的文件格式两者是同样的。</p><p>此选项允许将一个或多个Token(Token中,可以包括在正常情况下会被过滤的字符)映射成一个单独的关键词。exceptions选项与wordforms选项很类似,它们都代表某种映射,但有一些重要的不同点。</p><p>这些不同点简要总结如下:</p><ul><li>exceptions 大小写敏感, wordforms大小写无关;</li><li>exceptions 允许检测一串记号, wordforms仅对单独的词有效;</li><li>exceptions 可以使用charset_table中没有的特殊符号,wordforms完全遵从charset_table;</li><li>exceptions 在大字典上性能会下降,wordforms则对百万级的条目应对自如。</li></ul><p> </p><p>输入文件的格式仍然是纯文本,每行一个分词例外,而行的格式如下:</p><pre><span><span>map</span></span>-from-tokens => <span><span>map</span></span>-to-token</pre><p>示例文件:</p><pre>AT & T => AT&T
AT&T => AT&T
Standarten Fuehrer => standartenfuhrer
Standarten Fuhrer => standartenfuhrer
MS Windows => ms windows
Microsoft Windows => ms windows
C++ => cplusplus
c++ => cplusplus
C plus plus => cplusplus
</pre><p>这里全部的符号都是大小写敏感的:它们不会按charset_table选项的规则处理。因此,在上述例外文件下,“At&t”会被分成两个关键字“at”和“t”,因为其中的小写字母。而“AT&T”却被精确匹配并产生一个单独的关键字“AT&T”。</p><p>需要注意的是,前述映射文件的目标关键词(右侧)a)总是被解释成一个单独的词,而且b)不仅是大小写敏感的,而且是空白符号敏感的!在上述样例中,查询“ms windows”不会匹配包含“MS Windows”的文档。这个查询会被解释成两个词“ms”和“Windows”。而“MS Windows”映射到的是一个单独的
关键字“ms windows”,包括中间的空格。另一方面“standartenfuhrer”会取回带有“Standarten
Fuhrer”或者“Standarten
Fuehrer”内容的文档(大写字母必须与此处列出的完全相同),或者关键词本身大小写随意的任何版本,例如“staNdarTenfUhreR”。
(然而“standarten fuhrer”不会匹配。这段文本无法与列出的任何一个例外相匹配,因为大小写不同。因此被索引为两个分开的关键字)</p><p>映射源部分的空白符(white
space)不会被忽略,但空白符的数量无所谓。任何数量的空白符都匹配已索引的文档或者查询中的任意数量的空白符。例如映射源部分(“=>”左
端)的“AT€&€T”可以匹配“AT€€&€T”,不管被映射部分或已索引全文数据中实际有几个空格。根据上述例子中的第一条,上述文
本会作为“AT&T”关键字被索引。 对于使用Coreseek的中文用户,这个特性目前尚不被支持。Coreseek将在后续版本支持这个特性。</p><p>exceptions选项也允许特殊字符(这是通用charset_table选项规则的例外(exception),此选项因而得名)。假设您一般不想把“+”当作有效的字符,但仍想搜索一些例外情况,比如“C++”。上述例子正好可以做到这点,完全不管哪些字符在表中,哪些字符不在。</p><p>Exceptions选项被应用于原始输入文档和索引、搜索时的查询数据。因此要使文件的改动生效,需要重建索引并重启searchd。</p><h4>示例:</h4><pre>exceptions = <span><span>/usr/local</span></span><span><span>/sphinx/data</span></span><span><span>/exceptions.txt</span></span></pre><h3>11.2.14. min_word_len:最小索引词汇长度</h3><p>最小索引词长度。可选选项,默认为1(索引任何词)</p><p>只有长度不小于这个最小索引词长度的词会被索引。例如,如果min_word_len为4,那么“the”这个词不会被索引,但“they”会。</p><h4>示例:</h4><pre><span><span>min_word_len</span></span> = <span><span>4</span></span></pre><h3>11.2.15. charset_type:字符集编码</h3><p>字符集编码类型。可选选项,默认为“sbcs”。可用的值包括“sbcs”和“utf-8”。 对于使用Coreseek的中文用户,可选的值还可以有“zh_cn.utf-8 ”、“zh_cn.gbk”和“zh_cn.big5”(需要编译时提供iconv支持)。当设置charset_type值为上面的值时,系统默认您开启了中文分词特性。</p><p>不同的编码将它们的内部字符代码映射到特殊字节序列的方法不同。目前两个最常见的方法是单字节编码和UTF-8。它们对应的
charset_type值分别是“sbcs”(代表Single Byte Character
Set单字节字符集)和“utf-8”。选定的编码类型会在搜索被使用的任何情况下使用:索引数据时,对索引查询时,产生摘要时,等等。</p><p>注意,尽管“utf-8”暗示解码出来的值应按unicode码点数值对待,“sbcs”却对应一系列不同的编码,它们对不同字节值的处理不同,这要在charset_table设置中正确地反应出来。例如,同一个值244(十六进制0xE0)根据使用的是koi-8r还是windows-1251编码而映射到不同的俄语字符。</p><h4>示例:</h4><pre><span><span>charset_type</span></span> = utf-<span><span>8</span></span></pre><h3>11.2.16. charset_table:字符表和大小写转换规则</h3><p>接受的字符表和大小写转换规则。可选选项,默认值与charset_type 选项的值有关。 对于使用Coreseek的中文用户,Coreseek 提供的MMseg分词法内置了可接受的字符表,并且用户不可修改。当启用分词功能时,自动开启。</p><p>charset_table频繁应用于Sphinx的分词过程,即从文档文本或查询文本中抽取关键字的过程。它控制哪些字符被当作有效字符接受,哪些相反,还有接受了的字符如何转换(例如大小写信息保留还是去除)。</p><p>可以把charset_table想成一个对超过100K个Unicode字符中每一个的映射关系的大表(或者一个256个字符的小表,如果你使用

SBCS)。默认每个字符都对应0,这表示它不在关键字中出现,应被视为分隔符。一旦在此表中被提及,字符就映射到另一个字符(通常是它自身或者自身的小
写版本),同时被当作一个可以出现在关键字中的有效字符。</p><p>值的格式是逗号分隔的映射列表。两种最简单的映射分别是声明一个字符为有效和将一个简单字符映射为另一个字符。但用这种格式指定整个表会导致其体积臃肿、无法管理。因此提供了一些语法上的快捷方式,用它们可以一次指定一定范围的字符。详细的列表如下:</p><dl><dt>

        A-&gt;a 
      </dt><dd>
        单个字符映射,声明源字符“A”为允许出现在关键字中的字符,并将之映射到目的字符“a”(这并 
       <em>没有</em>声明“a”是允许的)。 
      </dd><dt>
        A..Z-&gt;a..z 
      </dt><dd>
        范围映射,声明源范围中的全部字符允许出现在关键字中,并将它们映射到目的范围。 
       <em>并不</em>声明目的范围是允许的。此外会检查 (长度必须相等) 
      </dd><dt>
        a 
      </dt><dd>
        单一字符映射,声明一个允许的字符,将它映射到它自身。相当于单个字符映射 a-&gt;a 。 
      </dd><dt>
        a..z 
      </dt><dd>
        杂散范围映射,声明范围中的全部字符为允许,将它们映射到自身。相当于范围映射 a..z-&gt;a..z 。 
      </dd><dt>
        A..Z/2 
      </dt><dd>
        

棋盘范围映射。映射每相邻两个字符到其中的第二个。形式化地说,声明范围中的奇数字符为允许,将它们映射到偶数字符上。同时允许偶数字符并映射到
其自身。例如, A..Z/2 相当于 A->B, B->B, C->D, D->D, …, Y->Z,
Z->Z。这个映射接将捷径方便声明大小写字符交替而非大小写字符分别连续的Unicode块。

      </dd></dl><p>&nbsp;</p><p>编码为0到31之间的控制字符总是被视作分隔符。编码32到127的字符即7位ASCII字符可以原样使用在映射中。为避免配置文件的编码问题,8

位ASCII字符和Unicode字符必须以U+xxx形式指定,“xxx”是码点对应的十六进制数。也可以用这个形式编码7位ASCII编码中的特殊字
符,例如用U+20来编码空格符,U+2E来编码句点,U+2C来编码逗号。</p><h4>示例:</h4><pre># <span><span>'sbcs</span></span>' defaults <span><span>for</span></span> English and Russian
charset_table = <span><span>0</span></span>..<span><span>9</span></span>, A..Z->a..z, _, a..z, \
U+A8->U+B8, U+B8, U+C0..U+DF->U+E0..U+FF, U+E0..U+FF

<span><span>'utf</span></span>-<span><span>8</span></span>' defaults <span><span>for</span></span> English and Russian

charset_table = <span><span>0</span></span>..<span><span>9</span></span>, A..Z->a..z, _, a..z, \
U+<span><span>410</span></span>..U+<span><span>42</span></span>F->U+<span><span>430</span></span>..U+<span><span>44</span></span>F, U+<span><span>430</span></span>..U+<span><span>44</span></span>F
</pre><h3>11.2.17. ignore_chars:忽略字符表</h3><p>忽略字符表。 可选选项,默认为空。</p><p>有些字符,如软断字符(U+00AD),不是仅仅要当作分隔符,而且应该被完全忽略。例如,如果“-”只是不在charset_table里,那么

“abc-def”会被当作两个关键字“abc”和“def”来索引。相反,如果将“-”加到ignore_char列表中,那么相同的文本会被当作一个
单独的关键字“abcdef”索引。</p><p>此选项的语法与 charset_table相同,但只允许声明字符,不允许映射它们。另外,忽略的字符不能出现在charset_table里。</p><h4>示例:</h4><pre><span><span>ignore_chars</span></span> = U+AD</pre><h3>11.2.18. min_prefix_len:最小索引前缀长度</h3><p>索引的最小前缀长度。可选选项,默认为0(不索引前缀)。</p><p>前缀索引使实现“wordstart*”形式的通配符成为可能(通配符语法的细节请参考 enable_star 选项)。当最小前缀长度被设置为正值,indexer除了关键字本身还会索引所有可能的前缀(即词的开头部分)。太短的前缀(小于允许的最小值)不会被索引。</p><p>例如,在min_prefix_len=3设置下索引关键字“example”会导致产生5个索引项“exa”, “exam”,
“examp”,
“exampl”和该词本身。对这个索引搜索“exam”会得到包含“example”的文档,即使该文档中没有“exam”自身。然而,前缀索引会使索
引体积急剧增大(因为待索引关键字增多了很多),而且索引和搜索的时间皆会恶化。</p><p>在前缀索引中没有自动的办法可以提高精确匹配(整个词完全匹配)的评分,但有一些技巧可以实现这个功能。首先,可以建立两个索引,一个带有前缀索引,另一个没有,同时在这两个索引中搜索,然后用 SetIndexWeights() 来设置二者的权重。其次,可以启用星号语法并重写扩展模式的查询:</p><pre><span><span># in sphinx.conf</span></span>
<span><span>enable</span></span>_star = 1

// <span><span>in</span></span> query
<span><span>$cl</span></span>->Query ( <span><span>"( keyword | keyword ) other keywords"</span></span> );
</pre><p> </p><h4>示例:</h4><pre><span><span>min_prefix_len</span></span> = <span><span>3</span></span></pre><h3>11.2.19. min_infix_len:最小索引中缀长度</h3><p>索引的最小中缀长度。可选选项,默认为0(不索引中缀)。</p><p>中缀索引是实现“start”, “end”, and “middle*”等形式的通配符成为可能(通配符语法的细节请参考 enable_star 选

项)。当最小中缀长度设置为正值,indexer除了对关键字本身还会对所有可能的中缀(即子字符串)做索引。太短的中缀(短于允许的最小长度)不会被索
引。例如,在min_infix_len=2设置下索引关键字“test”会导致产生6个索引项 “te”, “es”, “st”, “tes”,
“est”等中缀和词本身。对此索引搜索“es”会得到包含“test”的文档,即使它并不包含“es”本身。然而,中缀索引会使索引体积急剧增大(因为
待索引关键字增多了很多),而且索引和搜索的时间皆会恶化。</p><p>在中缀索引中没有自动的办法可以提高精确匹配(整个词完全匹配)的评分,但可以使用与 prefix indexes 选项中相同的技巧。</p><h4>示例:</h4><pre><span><span>min_infix_len</span></span> = <span><span>3</span></span></pre><h3>11.2.20. prefix_fields:前缀索引字段列表</h3><p>做前缀索引的字段列表。可选选项,默认为空(所有字段均为前缀索引模式)。</p><p>因为前缀索引对索引和搜索性能均有影响,可能需要将它限制在某些特定的全文数据字段:例如,对URL提供前缀索引,但对页面内容不提供。prefix_fields指定哪些字段要提供前缀索引,其他字段均会使用普通模式。值的格式是逗号分隔的字段名字列表。</p><h4>示例:</h4><pre><span><span>prefix_fields</span></span> = url, domain</pre><h3>11.2.21. infix_fields:中缀索引字段列表</h3><p>做中缀索引的字段列表。可选选项,默认为空(所有字段均为中缀索引模式)。</p><p>与 prefix_fields选项类似,但限制的是哪些字段做中缀索引。</p><h4>示例:</h4><pre><span><span>infix_fields</span></span> = url, domain</pre><h3>11.2.22. enable_star:星号语法</h3><p>允许前缀/中缀索引上的星号语法(或称通配符)。可选选项,默认为0(不使用通配符),这是为了与0.9.7版本的兼容性。可用的值为0和1。</p><p>此特性启用搜索前缀或中缀索引时的“星号语法”,或者说通配符语法。仅影响搜索,因此要使改变生效只须重启 searchd,而不需要重新索引。</p><p>默认值为0,意思是禁止星号语法,所有关键字都根据索引时的 min_prefix_len 和 min_infix_len settings设置被视为前缀或者中缀。取值1的意思是星号(“”)可以用在关键字的前面或后面。星号与零个或多个字符匹配。</p><p>例如,假设某索引启用了中缀索引,且enable_star值为1。搜索过程按如下工作:</p><ol><li>查询 “abcdef” 仅匹配确切含有“abcdef”这个词的文档;</li><li>查询 “abc” 可匹配含有以“abc”开头的词的文档(包括精确匹配词“abc”的文档);</li><li>查询 “cde” 匹配在任何地方含有“cde”的词的文档(包括精确匹配词“cde”的文档);</li><li>查询 “*def” 匹配含有以“def”结束的词的文档(包括精确匹配词“def”的文档)</li></ol><p> </p><h4>示例:</h4><pre><span><span>enable_star</span></span> = <span><span>1</span></span></pre><h3>11.2.23. ngram_len:N-gram长度</h3><p>N-gram索引的N-gram长度。可选选项,默认为0(禁用n-gram索引)可用的值是0和1(其他长度尚未实现) 对于使用Coreseek的中文用户,在启用了中文分词的情况下,本节内容可忽略。</p><p>N-gram提供对未分词CJK(Chinese, Japanse,
Koreasn中日韩)文本的基本支持。CJK搜索的问题在于词与词之前没有清晰的界限。理想中,文本可以通过一个称作分词程序(segmenter)的
特殊程序的过滤,之后分隔符即被加入到适当位置。然而分词过程缓慢而易错,因此通常会转而索引连续的一组N个字符,或称N-gram。</p><p>启用此特性,CJK字符流会被当作n-gram索引。例如,如果输入文本为“ABCDEF”(A到F均代表CJK字符)
,而此选项设置的长度为1,那它们会被当作“A B C D E F”而索引。(如果此选项设置的长度是2,那会产生“AB BC CD DE
EF”,但目前仅支持1)。只有那些在 ngram_chars 选项表中列出的字符会这样分割,其他不受影响。</p><p>注意,如果搜索查询是已分词的,即单独的词之间有分隔符分隔,那么在扩展模式中将这些词放入引号中搜索会得到正确的匹配结果,即使文档没有分词。例如,假设原查询为“BC DEF”,在应用程序端用引号将索引包起来,看起来是“BC” “DEF”(包括引号),这个查询被传给Sphinx并在其内部分割成1-gram,查询变成“B C” “D E F”,仍然包括作为词组查询操作符的引号。该查询会匹配正确的文本,即使文本中没有相应的分隔符。</p><p>即使搜索查询没有分词,Sphinx也可以返回较好的结果,这要感谢基于词组的相关度计算:它会使相近的词组匹配(在n-gram中CJK词相当于多个字符的词匹配)排在前面。</p><h4>示例:</h4><pre><span><span>ngram_len</span></span> = <span><span>1</span></span></pre><h3>11.2.24. ngram_chars:N-gram字符列表</h3><p>N-gram字符列表。 可选选项,默认为空。 对于使用Coreseek的中文用户,在启用了中文分词的情况下,本节内容可忽略。</p><p>与 ngram_len选项联用,此列表定义了从中抽取n-gram的字符序列。其他字符组成的词不受n-gram索引特性的影响。值的格式与charset_table相同。</p><h4>示例:</h4><pre><span><span>ngram_chars</span></span> = U+<span><span>3000</span></span>..U+<span><span>2</span></span>FA1F</pre><h3>11.2.25. phrase_boundary:词组边界符列表</h3><p>词组边界符列表。 可选选项,默认为空。</p><p>此列表控制哪些字符被视作分隔不同词组的边界,每到一个这样的边界,其后面的词的“位置”值都会被加入一个额外的增量,可以借此用近似搜索符来模拟词组搜索。语法与 charset_table选项相似,但没有字符之间的映射关系,而且这些词组边界符不能重复出现在其他任何设置选项中。</p><p>自每个词组边界起,后面的词的“位置”都会被加入一个额外的增量(由 phrase_boundary_step
义)。这使通过近似搜索符实现词组搜索成为可能:不同词组中的词之间的距离肯定大于phrase_boundary_step,因此相似距离小于
phrase_boundary_step的近似搜索其实是在搜索在一个词组范围内出现了全部给定查询词的情况,相当于词组搜索。</p><p>只有词组边界符后面紧跟着一个分隔符时,词组边界才被激活,这是为了避免S.T.A.L.K.E.R 或 URLs 等缩写被错当成若干个连续的词组(因为“.”属于词组边界符)。</p><h4>示例:</h4><pre><span><span>phrase_boundary</span></span> = ., ?, !, U+<span><span>2026</span></span> <span><span># horizontal ellipsis</span></span></pre><h3>11.2.26. phrase_boundary_step:词组边界位置增量</h3><p>词组边界上词位置的增量。可选选项,默认为0。</p><p>在词组边界上,当前词位置会加上此选项设置的额外增量。详细请参考 phrase_boundary 选项。</p><h4>示例:</h4><pre><span><span>phrase_boundary_step</span></span> = <span><span>100</span></span></pre><h3>11.2.27. html_strip:HTMl标记清理</h3><p>是否从输入全文数据中去除HTML标记。可选标记,默认为0。已知值包括0(禁用)和1(启用)。</p><p>HTML标签和实体都可以被标记并且得到处理。</p><p>HTML标签会被删除,但是其内容(即<P> 与
</P>之间的部分)默认情况下会保留。你可以选择标签中需要保留和索引的属性(例如A标签中的HREF属性,或者IMG标签中的ALT属
性)一些常见的内嵌标签会被完全清除,其他标签都被视为块级并被替换为空格。例如:’te<B>st</B>’文本将被单做一个

单一的关键字’test’被索引,但是,’te<P>st</P>’将被当做两个关键字’te’和’st’被索引。已知的内嵌标
签如下:A, B, I, S, U, BASEFONT, BIG, EM, FONT, IMG, LABEL, SMALL, SPAN,
STRIKE, STRONG, SUB, SUP, TT.</p><p>HTML实体会被解码并替换为对应的UTF-8字符。剥离器同时支持数字形式(例如&#239;)和文本形式(例如& oacute;或& nbsp;)。所有由HTML4标准规定的实体都支持。</p><p>此特性对 xmlpipe 数据源无效(建议升级到 xmlpipe2 )。这个去除HTML标记的模块应该很好地工作于正确格式化的HTML和XHTML,但就像大多数浏览器一样,对于格式错误的文本(例如带有无法配对的<和>的HTML)可能产生不希望的输出。</p><p>只有HTML标签和HTML注释会被删除。要同时删除标签的内容(例如要删除内嵌的脚本),请参考 html_remove_elements 选项。标签名没有限制,即任何看起来像有效的标签开头、结束或者注释的内容都会被删除。</p><h4>示例:</h4><pre><span><span>html_strip</span></span> = <span><span>1</span></span></pre><h3>11.2.28. html_index_attrs:HTML标签属性索引设置</h3><p>去除HTML标记但要索引的标记属性列表。可选选项,默认为空(不索引标记的属性)。</p><p>指定被保留并索引的HTML标记属性,而HTML标记本身会被被删除。格式是对每个标记列举可以索引的属性,请看下例:</p><h4>示例:</h4><pre><span><span>html_index_attrs</span></span> = img=alt,title; a=title;</pre><h3>11.2.29. html_remove_elements:HTML元素清理</h3><p>完全清空HTML标签列表,不仅这些标签本身会被删除,标签本身包含的内容也会被删除。可选选项,默认为空(不删除任何标签的内容)。</p><p>此特性允许删除标签包含的内容,即在开始标记和结束标记之间的所有东西。一般用于删除内嵌的脚本或CSS等。短的没有实际内容的标签(即<br />)也支持;类似不会这样的标签中的内容将被删除。</p><p>值为逗号分隔的标签名称列表。标签名大小写无关。</p><h4>示例:</h4><pre><span><span>html_remove_elements</span></span> = style, script</pre><h3>11.2.30. local:本地索引声明</h3><p>分布式索引 distributed index中的本地索引声明。可以出现多次, 可选选项,默认为空。</p><p>此设置用于声明分布式索引被搜索时要搜索的本地索引。全部本地索引会被依次搜索,仅使用1个CPU或核。要并行处理,可以配置searchd查询它自身(细节参考 第 11.2.31 节 “agent:远程索引声明” )。可以为每个分布式索引声明多个本地索引。每个本地索引可以在其他分布式索引中多次引用。</p><h4>示例:</h4><pre><span><span>local</span></span> = chunk1
<span><span>local</span></span> = chunk2
</pre><h3>11.2.31. agent:远程索引声明</h3><p>分布式索引(distributed index)中的远程代理和索引声明。可以出现多次,可选选项,默认为空。</p><p>此设置用来声明搜索分布式索引时要搜索的远程代理。代理可以看作网络指针,它指定了主机、端口和索引名。在最基本的情况下,代理可以与远程物理主机对应。更严格的来说,这不一定总是正确:可以将多个代理指向同一台远程主机,甚至指向同一个searchd实例(以便利用多个CPU或核)。</p><p>值的格式如下:</p><pre><span><span>agent</span></span> = specification:remote-indexes-list
<span><span>specification</span></span> = hostname <span><span>":"</span></span> port | path
</pre><p>“hostname”是远程主机名,“port”是远程TCP端口,”path”是Unix域套接字的路径, 而“remote-index-list”是一个逗号分隔的远程索引列表。</p><p>全部代理会被并行搜索。然而同一个代理的多个索引是依次搜索的。这使您可以根据硬件来优化配置。例如,如果两个远程索引存储在一个相同的硬盘上,最

好是配置一个带有多个按顺序搜索的索引,避免频繁的磁头寻址。如果这些索引存储在不同的硬盘上,那配置两个代理会更有利,因为这可以使工作完全并行。对于
CPU也是如此,虽然在两个进程间切换对性能的影响比较小而且常常被完全忽略。</p><p>在有多个CPU和硬盘的机器上,代理可以指向相同的机器以便并行地使用硬件,降低查询延迟。并不需要为此设置多个searchd实例,一个实例与自身通信是合法的。以下是一个示例设置,它是为一台有4个CPU的机器准备的,可以并行地使用4个CPU,各处理一个查询:</p><pre>index dist
{
type = distributed
local = chunk1
agent = localhost:9312:chunk2
agent = localhost:9312:chunk3
agent = localhost:9312:chunk4
}
</pre><p>注意其中一块是本地搜索的,而同一个searchd示例又向本身查询,以便并行地启动其他三个搜索。</p><h4>示例:</h4><pre><span><span>agent</span></span> = localhost:<span><span>9312</span></span>:chunk2 # contact itself
<span><span>agent</span></span> = /var/run/searchd.s:chunk2
<span><span>agent</span></span> = searchbox2:<span><span>9312</span></span>:chunk3,chunk4 # search remote indexes
</pre><h3>11.2.32. agent_blackhole:远程黑洞代理</h3><p>分布式索引( distributed index)中声明远程黑洞代理。多个值,可选选项,默认是空。于版本0.9.9-rc1引入。</p><p>agent_blackhole 选项使用户可以向远程代理发送“即发即忘”的查询(fire-and-forget queries)。这在调试(或者仅仅是测试)即将投入生产的集群的时候很有用:可以设置一个单独的调试/测试searchd实例,然后从实际生产中使用的主服务器(master,或称聚集者aggregator)实例向这个测试服务器转发查询请求,但不干扰生产系统的工作。主(master)searchd会以正常的方式尝试连接和查询黑洞代理,但是它既不会等待也不会处理黑洞代理的反馈。同时,发生在黑洞代理上的全部网络错误也都被忽略。值的格式与普通的 agent 完全相同。</p><h4>示例:</h4><pre><span><span>agent_blackhole</span></span> = testbox:<span><span>9312</span></span>:testindex1,testindex2</pre><h3>11.2.33. agent_connect_timeout:远程查询时间</h3><p>远程代理的连接超时时间,单位为毫秒。可选选项,默认为1000(即1秒)。</p><p>连接到远程代理时,searchd最多花这些时间等待connet()调用成功完成。如果达到了超时时间connect()仍没有完成,而 and retries 选项是启用的,那么将开始重试。</p><h4>示例:</h4><pre><span><span>agent_connect_timeout</span></span> = <span><span>300</span></span></pre><h3>11.2.34. agent_query_timeout:远程查询超时时间</h3><p>远程代理查询超时时间,以毫秒为单位。可选选项,默认为3000(即3秒)。</p><p>连接后,searchd最多花这这些时间等到远程查询完成。这个超时时间与连接超时时间是完全独立的。因此一个远程代理最多能造成的延迟为agent_connection_timeout与agent_query_timeout之和。如果超时时间已到,查询不会再重试,同时产生警告。</p><h4>示例:</h4><pre><span><span>agent_query_timeout</span></span> = <span><span>10000</span></span> <span><span># our query can be long, allow up to 10 sec</span></span></pre><h3>11.2.35. preopen:索引文件预开启</h3><p>预先打开全部索引文件还是每次查询时再打开索引。可选选项,默认为0(不预先打开)。</p><p>此选项令searchd在启动时(或轮换索引时)预先开打全部索引文件并在运行过程中保持打开。目前,默认是不预先打开这些文件(此行为可能在未来改变)。预先打开的每个索引文件会占用若干(目前是两个)文件描述符。但每次查询可以节约两个open()调用而且不会受高负载情况下索引轮换过程中可能发生的微妙的竞争条件(race condition)的影响。另一方面,当提供很多索引服务(几百到几千)时,必须每次查询时打开索引文件以便节约文件描述符。</p><p>这个指令不影响indexer的任何行为,只对searchd有用。</p><h4>示例:</h4><pre><span><span>preopen</span></span> = <span><span>1</span></span></pre><h3>11.2.36. ondisk_dict:字典文件保持设置</h3><p>指定是将字典文件(.spi)保持在磁盘上还是将它预先缓冲在内存中。可选选项,默认值是0(预先缓冲在内存里)。于版本0.9.9-rc1引入。</p><p>字典文件(.spi)既可以驻留在内存中也可以保持在磁盘上。默认情况下是将整个字典缓冲在内存中。这样做提高性能,但可能带来过大的内存压力,尤其是使用了前缀或中缀的时候。启用ondisk_dict为每次查询的每个关键词带来一次磁盘I/O操作,但是会减少内存使用。</p><p>这个指令不影响indexer的任何行为,只对searchd有用。</p><h4>示例:</h4><pre><span><span>ondisk_dict</span></span> = <span><span>1</span></span></pre><h3>11.2.37. inplace_enable:原地索引倒转设置</h3><p>是否启用原地索引倒转(in-place index inversion)。可选选项,默认值是0(使用单独的临时文件)。于版本0.9.9-rc1引入。</p><p>inplace_enable 选项极大地减少了建立索引时的磁盘压力,代价是略慢的索引速度(少使用大约两倍的磁盘空间,速度方面能达到原有性能的90-95%)</p><p>建立索引的过程有两个主要的阶段。第一个阶段主要是收集、处理文档以及对文档根据关键词进行部分的排序,中间结果被写入到临时文件(.tmp*)

中。第二个阶段则对文档进行完全排序并创建总重的索引文件。因此,重建一个正在应用于生产的索引将导致一个三倍大的磁盘占用峰值:第一倍,中间结果临时文

件,第二,新建的副本,和第三,在一切发生时旧的索引仍然占用一份磁盘空间,以便继续服务。(中间结果的大小与最终索引的大小相当)。对于很大的数据集,
这将是一笔很大的磁盘开销,而inplace_enable 选项用于减少这个开销。一旦启用这个选项,临时文件将被重复利用,最终的数据写回到临时文件中,最后改个名字就可以作为最终结果使用了。然而,这可能导致更多的临时数据块重新分配,因此性能会有一点损失。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>inplace_enable</span></span> = <span><span>1</span></span></pre><h3>11.2.38. inplace_hit_gap:原地索引倒转匹配点空隙设置</h3><p>微调原地倒转(In-place inversion)行为的选项。控制预先分配的匹配点列表(hitlist)的空隙的大小。可选选项,默认是0。于版本0.9.9-rc1引入。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>inplace_hit_gap</span></span> = <span><span>1</span></span>M</pre><h3>11.2.39. inplace_docinfo_gap:原地索引倒转文档信息空隙设置</h3><p>微调原地倒转(In-place inversion)行为的选项。控制预先分配的文档信息(docinfo)的空隙的大小。可选选项,默认是0。于版本0.9.9-rc1引入。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>inplace_docinfo_gap</span></span> = <span><span>1</span></span>M</pre><h3>11.2.40. inplace_reloc_factor:原地索引倒转重定位内存设置</h3><p>微调原地倒转(In-place inversion )行为的选项。控制重定位缓冲区占用索引时的内存的比例。可选选项,默认是0.1。于版本0.9.9-rc1引入。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>inplace_reloc_factor</span></span> = <span><span>0.1</span></span></pre><h3>11.2.41. inplace_write_factor:原地索引倒转写缓冲内存设置</h3><p>微调原地倒转(In-place inversion )行为的选项。控制原地写缓冲占用索引时的内存的比例。可选选项,默认是0.1。于版本0.9.9-rc1引入。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>inplace_write_factor</span></span> = <span><span>0.1</span></span></pre><h3>11.2.42. index_exact_words:词干化后原词索引</h3><p>是否在词干化处理后还索引原词(是否在索引原关键词的词干化/重映射后的形式的同时也索引原词)。可选选项,默认值是0(不索引额外的形式)。于版本0.9.9-rc1引入。</p><p>一旦启用,index_exact_words强制indexer除了词干化的版本外,将原始的关键字也加入索引。这样做也使查询语言中的精确匹配搜索符可用。这个选项将对索引大小和索引时间带来延迟。然而搜索的性能不会被影响。</p><h4>示例:</h4><pre><span><span>index_exact_words</span></span> = <span><span>1</span></span></pre><h3>11.2.43. overshort_step:短词位置增量</h3><p>在经过过短的词(比 min_word_len短的词)处后增加位置值。 可选选项,允许的值是0或者1,默认是1。于版本0.9.9-rc1引入。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>overshort_step</span></span> = <span><span>1</span></span></pre><h3>11.2.44. stopword_step:通用词位置增量</h3><p>在经过 停用词 处后增加位置值可选选项,允许的值是0或者1,默认是1。于版本0.9.9-rc1引入。</p><p>这个指令不影响searchd的任何行为,只对indexer有用。</p><h4>示例:</h4><pre><span><span>stopword_step</span></span> = <span><span>1</span></span></pre><h3>11.2.45. hitless_words:位置忽略词汇列表</h3><p>位置忽略词汇列表。 可选项,可用值为all或者列表所在的文件名。 版本2.0.1-beta引入。</p><p>By default, Sphinx full-text index stores not only a list of
matching documents for every given keyword, but also a list of its
in-document positions (aka hitlist). Hitlists enables phrase, proximity,
strict order and other advanced types of searching, as well as phrase
proximity ranking. However, hitlists for specific frequent keywords
(that can not be stopped for some reason despite being frequent) can get
huge and thus slow to process while querying. Also, in some cases we
might only care about boolean keyword matching, and never need
position-based searching operators (such as phrase matching) nor phrase
ranking.</p><p>hitless_words lets you create indexes that either do not have positional information (hitlists) at all, or skip it for specific keywords.</p><p>Hitless index will generally use less space than the
respective regular index (about 1.5x can be expected). Both indexing and
searching should be faster, at a cost of missing positional query and
ranking support. When searching, positional queries (eg. phrase queries)
will be automatically converted to respective non-positional
(document-level) or combined queries. For instance, if keywords “hello”
and “world” are hitless, “hello world” phrase query will be converted to
(hello & world) bag-of-words query, matching all documents that
mention either of the keywords but not necessarily the exact phrase. And
if, in addition, keywords “simon” and “says” are not hitless, “simon
says hello world” will be converted to (“simon says” & hello &
world) query, matching all documents that contain “hello” and “world”
anywhere in the document, and also “simon says” as an exact phrase.</p><h4>示例:</h4><pre><span><span>hitless_words</span></span> = all</pre><h3>11.2.46. expand_keywords:词汇展开</h3><p>尽可能展开关键字的精确格式或者型号形式。 可选项,默认为0(不展开关键字)。 版本2.0.1-beta引入。</p><p>Queries against indexes with expand_keywords feature
enabled are internally expanded as follows. If the index was built with
prefix or infix indexing enabled, every keyword gets internally
replaced with a disjunction of keyword itself and a respective prefix or
infix (keyword with stars). If the index was built with both stemming
and index_exact_words enabled,
exact form is also added. Here’s an example that shows how internal
expansion works when all of the above (infixes, stemming, and exact
words) are combined:</p><pre>running -> ( <span><span>running</span></span> | running | =running )</pre><p> </p><p>Expanded queries take naturally longer to complete, but can
possibly improve the search quality, as the documents with exact form
matches should be ranked generally higher than documents with stemmed or
infix matches.</p><p>Note that the existing query syntax does not allowe to
emulate this kind of expansion, because internal expansion works on
keyword level and expands keywords within phrase or quorum operators too
(which is not possible through the query syntax).</p><p>This directive does not affect indexer in any way, it only affects searchd.</p><h4>示例:</h4><pre><span><span>expand_keywords</span></span> = <span><span>1</span></span></pre><h3>11.2.47. blend_chars:混合字符列表</h3><p>混合字符列表。 可选项,默认为空。 版本2.0.1-beta引入。</p><p>Blended characters are indexed both as separators and valid
characters. For instance, assume that & is configured as blended and
AT&T occurs in an indexed document. Three different keywords will
get indexed, namely “at&t”, treating blended characters as valid,
plus “at” and “t”, treating them as separators.</p><p>Positions for tokens obtained by replacing blended characters
with whitespace are assigned as usual, so regular keywords will be
indexed just as if there was no blend_chars specified at
all. An additional token that mixes blended and non-blended characters
will be put at the starting position. For instance, if the field
contents are “AT&T company” occurs in the very beginning of the text
field, “at” will be given position 1, “t” position 2, “company” positin
3, and “AT&T” will also be given position 1 (“blending” with the
opening regular keyword). Thus, querying for either AT&T or just AT
will match that document, and querying for “AT T” as a phrase also match
it. Last but not least, phrase query for “AT&T company” will alsomatch it, despite the position</p><p>Blended characters can overlap with special characters used
in query syntax (think of T-Mobile or @twitter). Where possible, query
parser will automatically handle blended character as blended. For
instance, “hello @twitter” within quotes (a phrase operator) would
handle @-sign as blended, because @-syntax for field operator is not
allowed within phrases. Otherwise, the character would be handled as an
operator. So you might want to escape the keywords.</p><p>Starting with version 2.0.1-beta, blended characters can be
remapped, so that multiple different blended characters could be
normalized into just one base form. This is useful when indexing
multiple alternative Unicode codepoints with equivalent glyphs.</p><h4>示例:</h4><pre><span><span>blend_chars</span></span> = +, &, U+<span><span>23</span></span>
<span><span>blend_chars</span></span> = +, &->+ # <span><span>2.0</span></span>.<span><span>1</span></span>-beta and above
</pre><h3>11.2.48. blend_mode:混合类型</h3><p>混合类型列表。可选项,默认为 trim_none。 版本2.0.1-beta引入。</p><p>By default, tokens that mix blended and non-blended
characters get indexed in there entirety. For instance, when both
at-sign and an exclamation are in blend_chars, “@dude!”
will get result in two tokens indexed: “@dude!” (with all the blended
characters) and “dude” (without any). Therefore “@dude” query will not match it.</p><p>blend_mode directive adds flexibility to this indexing behavior. It takes a comma-separated list of options.</p><pre><span><span>blend_mode</span></span> = option [, option [, ...]]
<span><span>option</span></span> = trim_none | trim_head | trim_tail | trim_both | skip_pure
</pre><p> </p><p>Options specify token indexing variants. If multiple options
are specified, multiple variants of the same token will be indexed.
Regular keywords (resulting from that token by replacing blended with
whitespace) are always be indexed.</p><dl><dt>

        trim_none 
      </dt><dd>
        Index the entire token. 
      </dd><dt>
        trim_head 
      </dt><dd>
        Trim heading blended characters, and index the resulting token. 
      </dd><dt>
        trim_tail 
      </dt><dd>
        Trim trailing blended characters, and index the resulting token. 
      </dd><dt>
        trim_both 
      </dt><dd>
        Trim both heading and trailing blended characters, and index the resulting token. 
      </dd><dt>
        skip_pure 
      </dt><dd>
        Do not index the token if it’s purely blended, that is, consists of blended characters only. 
      </dd></dl><p>Returning to the “@dude!” example above, setting&nbsp;blend_mode = trim_head, trim_tail&nbsp;will result in two tokens being indexed, “@dude” and “dude!”. In this particular example,&nbsp;trim_both&nbsp;would

have no effect, because trimming both blended characters results in
“dude” which is already indexed as a regular keyword. Indexing “@U.S.A.”
with trim_both (and assuming that dot is blended two) would result in “U.S.A” being indexed. Last but not least, skip_pure enables
you to fully ignore sequences of blended characters only. For example,
“one @@@ two” would be indexed exactly as “one two”, and match that as a
phrase. That is not the case by default because a fully blended token
gets indexed and offsets the second keyword position.</p><p>Default behavior is to index the entire token, equivalent to blend_mode = trim_none.</p><h4>示例:</h4><pre><span><span>blend_mode</span></span> = trim_tail, skip_pure</pre><h3>11.2.49. rt_mem_limit:RT索引内存限制</h3><p>内存区块限制大小。 可选项,默认为空。 版本2.0.1-beta引入。</p><p>RT index keeps some data in memory (so-called RAM chunk) and
also maintains a number of on-disk indexes (so-called disk chunks). This
directive lets you control the RAM chunk size. Once there’s too much
data to keep in RAM, RT index will flush it to disk, activate a newly
created disk chunk, and reset the RAM chunk.</p><p>The limit is pretty strict; RT index should never allocate
more memory than it’s limited to. The memory is not preallocated either,
hence, specifying 512 MB limit and only inserting 3 MB of data should
result in allocating 3 MB, not 512 MB.</p><p> </p><h4>示例:</h4><pre><span><span>rt_mem_limit</span></span> = <span><span>512</span></span>M</pre><h3>11.2.50. rt_field:字段设置</h3><p>全文字段定义。 多值选项,必须设置。 版本2.0.1-beta引入。</p><p>Full-text fields to be indexed are declared using rt_field directive.
The names must be unique. The order is preserved; and so field values
in INSERT statements without an explicit list of inserted columns will
have to be in the same order as configured.</p><p> </p><h4>示例:</h4><pre><span><span>rt_field</span></span> = author
<span><span>rt_field</span></span> = title
<span><span>rt_field</span></span> = content
</pre><h3>11.2.51. rt_attr_uint:整数属性</h3><p>无符号整数属性定义。 多值选项(允许设置任意个此属性),可选项。 声明一个32位的无符号数属性。 版本2.0.1-beta引入。</p><h4>示例:</h4><pre><span><span>rt_attr_uint</span></span> = gid</pre><h3>11.2.52. rt_attr_bigint:长整数属性</h3><p>BIGINT属性定义 多值选项(允许设置任意个此属性),可选项。 声明一个64位的有符号数属性。 版本2.0.1-beta引入。</p><h4>示例:</h4><pre><span><span>rt_attr_bigint</span></span> = guid</pre><h3>11.2.53. rt_attr_float:浮点数属性</h3><p>浮点数属性定义。 多值选项(允许设置任意个此属性),可选项。 声明一个单精度,32为的IEEE 754格式的浮点数属性 版本2.0.1-beta引入。</p><h4>示例:</h4><pre><span><span>rt_attr_float</span></span> = gpa</pre><h3>11.2.54. rt_attr_timestamp:UNIX时间戳属性</h3><p>时间戳属性定义。 多值选项(允许设置任意个此属性),可选项。 版本2.0.1-beta引入。</p><h4>示例:</h4><pre><span><span>rt_attr_timestamp</span></span> = date_added</pre><h3>11.2.55. rt_attr_string:字符串属性</h3><p>字符串属性定义。 多值选项(允许设置任意个此属性),可选项。 版本2.0.1-beta引入。</p><h4>示例:</h4><pre><span><span>rt_attr_string</span></span> = author</pre><h2>11.3. indexer 程序配置选项</h2><h3>11.3.1. mem_limit:索引内存限制</h3><p>索引过程中内存使用限制。可选选项,默认32M。</p><p>这是indexer不会超越的强制内存限制。可以以字节、千字节(以K为后缀)或兆字节(以M为后缀)为单位。参见示例。当过小的值导致I/O缓冲低于8KB时该限制会自动提高,此值的最低限度依赖于待索引数据的大小。如果缓冲低于256KB,会产生警告。</p><p>最大可能的限制是2047M。太低的值会影响索引速度,但256M到1024M对绝大多数数据集(如果不是全部)来说应该足够了。这个值设得太高可

能导致SQL服务器连接超时。在文档收集阶段,有时内存缓冲的一部分会被排序,而与数据库的通信会暂停,于是数据库服务器可能超时。这可以通过提高SQL
服务器端的超时时间或降低 mem_limit来解决。 在Coreseek的分发版本中,如果使用python数据源,则在Python部分的处理不会受mem_limit的限制。</p><h4>示例:</h4><pre><span><span>mem_limit</span></span> = <span><span>256</span></span>M
<span><span># mem_limit = 262144K # same, but in KB</span></span>
<span><span># mem_limit = 268435456 # same, but in bytes</span></span>
</pre><h3>11.3.2. max_iops:每秒IO操作限制</h3><p>每秒最大I/O操作次数,用于限制I/O操作。可选选项,默认为0(无限制)。</p><p>与I/O节流有关的选项。它限制了每秒钟最大的I/O操作(读或写)的次数。值0意思是不加限制。</p><p>indexer在索引时可能导致突发的密集磁盘I/O,因此需要限制它磁盘活动(给同一台机器上运行的其他程序留出一些资源,比如searchd)。 I/O节流就是用来实现上述功能的。它的工作原理是,在indexer的连续磁盘I/O操作之间强制增加一个保证的延迟。现代SATA硬盘每秒钟可以执行多达70-100以上次的I/O操作(主要受磁头寻道时间的限制)。将索引I/O限制为上述数值的几分之一可以减轻由索引带来的搜索性能下降。</p><h4>示例:</h4><pre><span><span>max_iops</span></span> = <span><span>40</span></span></pre><h3>11.3.3. max_iosize:最大IO操作限制</h3><p>最大允许的I/O操作大小,以字节为单位,用于I/O节流。可选选项,默认为0(不限制)。</p><p>与I/O节流有关的选项。它限制indexer文件I/O操作的单次最大大小。值0代表不加限制。超过限制的读写操作会被分成几个小的操作,并被max_iops 计为多次。在本文写作时,全部I/O操作都被限制在256KB以下(默认的内部缓冲大小),因此大于256KB的max_iosize值没有任何作用。</p><h4>示例:</h4><pre><span><span>max_iosize</span></span> = <span><span>1048576</span></span></pre><h3>11.3.4. max_xmlpipe2_field:最大字段大小</h3><p>对于XMLLpipe2数据源允许的最大的字段大小,以字节为单位。可选选项,默认值为2MB。</p><h4>示例:</h4><pre><span><span>max_xmlpipe2_field</span></span> = <span><span>8</span></span>M</pre><h3>11.3.5. write_buffer:写缓冲大小</h3><p>写缓冲区的大小,单位是字节。可选选项,默认值是1MB。</p><p>在建立索引过程中,写缓冲用于写入临时行而最终的索引文件。写缓冲区越大则所需的磁盘写入次数越少。缓冲区使用的内存不计入 mem_limit选项的值。注意对于不同的文件,会分配多个缓冲区(目前最多4个),这会引起内存占用增加。</p><h4>示例:</h4><pre><span><span>write_buffer</span></span> = <span><span>4</span></span>M</pre><h3>11.3.6. max_file_field_buffer:外部文件缓冲大小</h3><p>文件字段可用的最大缓冲区大小,字节为单位。 可选项,默认为8MB,最小值为1MB.</p><p>File field buffer is used to load files referred to from sql_file_field columns.
This buffer is adaptive, starting at 1 MB at first allocation, and
growing in 2x steps until either file contents can be loaded, or maximum
buffer size, specified by max_file_field_buffer directive, is reached.</p><p>Thus, if there are no file fields are specified, no buffer is
allocated at all. If all files loaded during indexing are under (for
example) 2 MB in size, but max_file_field_buffer value is 128 MB, peak buffer usage would still be only 2 MB. However, files over 128 MB would be entirely skipped.</p><h4>示例:</h4><pre><span><span>max_file_field_buffer</span></span> = <span><span>128</span></span>M</pre><h2>11.4. searchd 程序配置选项</h2><h3>11.4.1. listen:监听设置</h3><p>指定searchd监听的IP地址和端口,或UNIX域socket的路径。于版本0.9.9-rc1引入。</p><p>一个非正式的listen语法说明如下:</p><pre><span><span>listen</span></span> = ( address <span><span>":"</span></span> port | port | path ) [ <span><span>":"</span></span> protocol ]</pre><p>即,用户可以指定IP地址(或主机名)和端口号,或者仅仅是端口号,或者Unix socket的路径。如果仅指定了端口号而没有地址,那么searchd会在所有的网络接口上监听。Unix路径都带有一个前导的斜杠”/”。</p><p>从版本0.9.9-rc2开始,还可以指定一个协议处理器(protocl
handler),或者叫监听器(listener),应用于这个socket上的连接。支持的协议值包括‘sphinx’(Sphinx 0.9.x
API协议)和mysql41(版本4.1到至少5.1的MySQL使用的协议)。关于MySQL协议的更多细节可以参考 第 5.10 节 “MySQL 协议支持与 SphinxQL” 。</p><h4>示例:</h4><pre><span><span>listen</span></span> = localhost
<span><span>listen</span></span> = localhost:<span><span>5000</span></span>
<span><span>listen</span></span> = <span><span>192.168</span></span>.<span><span>0.1</span></span>:<span><span>5000</span></span>
<span><span>listen</span></span> = /var/run/sphinx.s
<span><span>listen</span></span> = <span><span>9312</span></span>
<span><span>listen</span></span> = localhost:<span><span>9306</span></span>:mysql41
</pre><p>可以有多个listen指令,searchd 会在所有这些指令纸浆的端口和socket上监听,以备用户连接。如果没有找到listen指令,服务器会在所有的网络接口上用默认端口(9312)监听。 从版本1.10-beta开始,也会自动监听默认的SphinxQL端口9306。这两个端口号是由IANA(查看http://www.iana.org/assignments/port-numbers了解详情)所分配的,因此可以正常使用。</p><p>在Windows上不支持Unix域套接字。</p><h3>11.4.2. address:监听地址</h3><p>要绑定的接口IP地址。可选项,默认为0.0.0.0(即在所有接口上监听)。 不推荐, 建议使用 listen 。</p><p>address 设置指定searchd在哪个接口上绑定、监听和接受输入的网络连接。默认值为0.0.0.0,意思是在所有接口上监听。目前不能指定多个接口。</p><h4>示例:</h4><pre><span><span>address</span></span> = <span><span>192.168.0.1</span></span></pre><h3>11.4.3. port:监听端口</h3><p>searchd 的TCP端口号。 不推荐, 建议使用 listen 。 必选项,默认为9312。</p><h4>示例:</h4><pre><span><span>port</span></span> = <span><span>9312</span></span></pre><h3>11.4.4. log:搜索系统日志</h3><p>日志文件名。可选项,默认为“searchd.log”。全部searchd运行时事件会被记录在这个日志文件中。</p><p>Also you can use the ‘syslog’ as the file name. In this case
the events will be sent to syslog daemon. To use the syslog option the
sphinx must be configured ‘–with-syslog’ on building.</p><h4>示例:</h4><pre><span><span>log</span></span> = /var/<span><span>log</span></span>/searchd.<span><span>log</span></span></pre><h3>11.4.5. query_log:搜索查询日志</h3><p>查询日志文件名。可选项,默认为空(不记录查询日志)。全部搜索查询会被记录在此文件中。其格式在第 5.9 节 “搜索服务(searchd) 查询日志格式”中描述。</p><p>In case of ‘plain’ format, you can use the ‘syslog’ as the
path to the log file. In this case all search queries will be sent to
syslog daemon with LOG_INFO priority, prefixed with ‘[query]‘ instead of
timestamp. To use the syslog option the sphinx must be configured
‘–with-syslog’ on building.</p><h4>示例:</h4><pre>query_<span><span>log</span></span> = /var/<span><span>log</span></span>/query.log</pre><h3>11.4.6. query_log_format:查询日志格式</h3><p>查询日志格式。 可选项,可用值为plain、sphinxql,默认为plain。 版本2.0.1-beta引入。</p><p>Starting with version 2.0.1-beta, two different log formats
are supported. The default one logs queries in a custom text format. The
new one logs valid SphinxQL statements. This directive allows to switch
between the two formats on search daemon startup. The log format can
also be altered on the fly, using SET GLOBAL query_log_format=sphinxql syntax. Refer to第 5.9 节 “搜索服务(searchd) 查询日志格式” for more discussion and format details.</p><h4>示例:</h4><pre><span><span>query_log_format</span></span> = sphinxql</pre><h3>11.4.7. read_timeout:远程读取超时时间</h3><p>网络客户端请求的读超时时间,单位是秒。可选项,默认是5秒。 searchd 强制关闭在此时间内未能成功发出查询的客户端连接。</p><h4>示例:</h4><pre><span><span>read_timeout</span></span> = <span><span>1</span></span></pre><h3>11.4.8. client_timeout:客户端超时时间</h3><p>在使用持久连接时,两次查询之间等待的最长时间(单位是秒)。可选选项,默认是5分钟。</p><h4>示例:</h4><pre><span><span>client_timeout</span></span> = <span><span>3600</span></span></pre><h3>11.4.9. max_children:子进程数目限制</h3><p>子进程的最大数量(或者说,并行执行的搜索的数目)。可选项,默认为0,不限制。</p><p>用来控制服务器负载。任何时候不可能有比此设置值更多的搜索同时运行。当达到限制时,新的输入客户端会被用临时失败(SEARCH_RETRY)状态码驳回,同时给出一个声明服务器已到最大连接限制的消息。</p><h4>示例:</h4><pre><span><span>max_children</span></span> = <span><span>10</span></span></pre><h3>11.4.10. pid_file:PID文件</h3><p>searchd PID文件名。必选项。 Mandatory.</p><p>PID文件会在启动时重建(并锁定)。主守护进程运行时它含有该进程的ID,而当守护进程退出时该文件会被删除。这个选项是必须的,因为Sphinx在内部使用它做如下事:检查是否已有一个searchd示例;停止searchd;通知searchd应该轮换索引了。也可以被各种不同的外部自动化脚本所利用。</p><h4>示例:</h4><pre><span><span>pid_file</span></span> = /var/run/searchd.pid</pre><h3>11.4.11. max_matches:最大返回匹配数</h3><p>守护进程在内存中为每个索引所保持并返回给客户端的匹配数目的最大值。可选选项,默认值为1000。</p><p>引入此选项是为了控制和限制内存使用,max_matches设置定义了搜索每个索引时有多少匹配项会保存在内存中。每个找到的匹配项都会被处理,但只有它们中最佳的N个会在内存中保持并最终返回给客户端。假设索引中包括2000000个当前查询的匹配项,你几乎总是不需要它们中的全部。

通常您需要扫描它们并根据某种条件(即按相关度排序、或者价格、或者其他什么)选出最好的那些,比如500个,并以在页面上显示20到100项。只跟踪最

好的500个匹配要比保持全部的2000000个匹配项大大地节约内存和CPU,之后可以对这些最佳匹配排序,然后丢弃除了要在页面上要显式的20项之外
的结果。max_matches控制“最佳N个匹配”中的N。</p><p>此参数明显影响每个查询消耗的内存和CPU。1000到10000的值通常就可以满足需求,但更高的值要小心使用。粗心地把max_matches增加到1000000意味着searchd被迫为每一个查询分配1M条匹配项的缓冲。这会明显增大查询的内存消耗,有时会明显影响性能。</p><p>特别注意!此限制还可在另一个地方指定。max_matches可以通过对应的API调用实时降低,该调用的默认值也是1000。因此要使应用程序获取超过1000个匹配结果,必须修改配置文件,重启searchd,再用SetLimits()调用设置合适的限制。还要注意,API调用设置的限制不能大于.conf文件中的设置,这是为了预防恶意的或错误的请求。</p><h4>示例:</h4><pre><span><span>max_matches</span></span> = <span><span>10000</span></span></pre><h3>11.4.12. seamless_rotate:无缝轮换</h3><p>防止 searchd 轮换在需要预取大量数据的索引时停止响应。可选选项,默认为1(启用无缝(seamless)轮换)。</p><p>索引可能包含某些需要预取到内存中的数据。目前.spa, .spi 和 .spm文件会被完全预取到内存中(它们分别包含属性数据,MVA数据和关键字索引)。若无无缝轮换,轮换索引时会尽量使用较小的内存,并如下工作:</p><ol><li>新的查询暂时被拒绝(用“retry”错误码);</li><li>searchd 等待目前正在运行的查询结束;</li><li>旧的索引被释放,文件被重命名;</li><li>新的索引文件被重命名,分配所需的内存;</li><li>新的索引属性和字典数据预调进内存;</li><li>searchd 恢复为新索引提供查询服务。</li></ol><p> </p><p>然而,如果有大量的属性或字典数据,那么预调数据的步骤可能消耗大量的时间——预调1.5GB的文件可能需要几分钟的时间。</p><p>当启用了无缝轮换,轮换按如下工作:</p><ol><li>为新索引分配内存;</li><li>新索引的属性和字典数据异步地预调进内存;</li><li>如果成功,旧的索引被释放,新旧索引文件被重命名;</li><li>如果失败,释放新索引;</li><li>在任意时刻,查询服务都正常运行——或者使用旧索引,或者使用新索引。</li></ol><p> </p><p>无缝轮换以轮换过程中更大的峰值内存消耗为代价(因为当预调新索引时.spa/.spi/.spm数据的新旧拷贝需要同时保持在内存中)。平均内存耗用不变。</p><h4>示例:</h4><pre><span><span>seamless_rotate</span></span> = <span><span>1</span></span></pre><h3>11.4.13. preopen_indexes:索引预开启</h3><p>是否在启动是强制重新打开所有索引文件。可选选项,默认为1(全部打开)。</p><p>Starting with 2.0.1-beta, the default value for this option
is now 1 (foribly preopen all indexes). In prior versions, it used to be
0 (use per-index settings).</p><p>设置为 1 时,该配置会覆盖并对所有提供服务的索引强制 打开 preopen 选项 They will be preopened, no matter what is the per-index preopen setting. When set to 0, per-index settings can take effect. (And they default to 0.)</p><p>Pre-opened indexes avoid races between search queries and rotations that can cause queries to fail occasionally. They also make searchd use more file handles. In most scenarios it’s therefore preferred and recommended to preopen indexes.</p><h4>示例:</h4><pre><span><span>preopen_indexes</span></span> = <span><span>1</span></span></pre><h3>11.4.14. unlink_old:旧索引清理</h3><p>索引轮换成功之后,是否删除以.old为扩展名的索引拷贝。可选选项,默认为1(删除这些索引拷贝)。</p><h4>示例:</h4><pre><span><span>unlink_old</span></span> = <span><span>0</span></span></pre><h3>11.4.15. attr_flush_period:属性刷新周期</h3><p>用UpdateAttributes()实时更新文档属性时,所产生的变化首先写入到这些属性在内存中的一份拷贝中(必须将docinfo设置成extern)。其后,一旦searchd正常关闭(通过发送SIGTERM信号),这些变化才写入磁盘。于版本0.9.9-rc1中引入。</p><p>从版本0.9.9-rc1开始,可以令searchd每隔一段时间就将变化写回磁盘,防止丢失这些变化。这个间隔时间通过attr_flush_period选项设置,单位是秒。</p><p>默认值是0,即关闭隔一段时间就将变化写回磁盘的特性,但是正常关闭时的写回不被关闭。</p><h4>示例:</h4><pre><span><span>attr_flush_period</span></span> = <span><span>900</span></span> <span><span># persist updates to disk every 15 minutes</span></span></pre><h3>11.4.16. ondisk_dict_default:索引字典存储方式</h3><p>对 ondisk_dict 指令的全局的默认值。 可选选项,默认值是0(将字典预先缓冲到内存)。于版本0.9.9-rc1中引入。</p><p>这个选项用于为当前使用的这份searchd正在提供服务的所有索引指定ondisk_dict选项的默认值。如果某个索引的这个选项做了显式设定,那么这个设定覆盖上述实例级的默认设置,这种机制提供了细粒度的控制。</p><h4>示例:</h4><pre><span><span>ondisk_dict_default</span></span> = <span><span>1</span></span> # keep all dictionaries <span><span>on</span></span> disk</pre><h3>11.4.17. max_packet_size:最大包大小</h3><p>网络通讯时允许的最大的包的大小。这个限制既对来自客户端的查询包有效,也对分布式环境下远程代理返回的响应包有效。只用于内部校验,不直接影响内存占用和性能。可选选项,默认值是8M。于版本0.9.9-rc1引入。</p><h4>示例:</h4><pre><span><span>max_packet_size</span></span> = <span><span>32</span></span>M</pre><h3>11.4.18. mva_updates_pool:MVA更新共享内存</h3><p>用于多值属性MVA更新的存储空间的内存共享池大小。可选选项,默认大小是1M。于版本0.9.9-rc1引入。</p><p>这个设置控制用于存储多值属性MVA更新后的值共享存储池的大小。如果指定大小为0则意味着完全禁用多值属性MVA的更新。一旦达到了这个内存池大

小的限制,尝试更新多值属性MVA将得到错误。但普通的(标量的)属性仍然可以更新。由于内部实现上的技术困难,一旦多值属性MVA有所更新,则索引上发
生的任何更新改变都不能在索引重建前被写入(store,flush)磁盘,尽管这可能在未来实现。同时,多值属性MVA是设计用来在索引重建前迅速反应数据库中的变化,而不是一种永久存储的机制。</p><h4>示例:</h4><pre><span><span>mva_updates_pool</span></span> = <span><span>16</span></span>M</pre><h3>11.4.19. crash_log_path:崩溃日志</h3><p>崩溃日志文件的路径(正式地说叫做前缀)。可选选项,默认值为空(不创建崩溃日志文件)。于版本0.9.9-rc1引入。
从版本2.0.1-beta开始不再推荐使用,崩溃调试信息将以文本格式会记录到searchd.log日志文件中,独立的二进制崩溃文件不再需要了。</p><h3>11.4.20. max_filters:最大过滤器数目</h3><p>每次查询允许设置的过滤器的最大个数。只用于内部检查,不直接影响内存使用或性能。可选选项,默认值是256。于版本0.9.9-rc1引入。</p><h4>示例:</h4><pre><span><span>max_filters</span></span> = <span><span>1024</span></span></pre><h3>11.4.21. max_filter_values:单个过滤器最大过滤值数目</h3><p>单个过滤器允许的值的最大个数。只用于内部检查,不直接影响内存使用或性能。可选选项,默认值是4096。于版本0.9.9-rc1引入。</p><h4>示例:</h4><pre><span><span>max_filter_values</span></span> = <span><span>16384</span></span></pre><h3>11.4.22. listen_backlog:带处理监听队列</h3><p>TCP监听待处理队列长度。可选选项,默认值是5。</p><p>在Windows系统上创建的Sphinx目前(版本0.9.9)只能一个接一个地处理请求。同时发生的请求会被操作系统级别的TCP协议栈装入到

一个队列中,无法如对的请求立即失败并收到“连接被拒”错误信息。listen_backlog选项控制这个连接队列的长度。非Windows平台上创建
的Sphinx使用默认值即可。</p><h4>示例:</h4><pre><span><span>listen_backlog</span></span> = <span><span>20</span></span></pre><h3>11.4.23. read_buffer:读缓冲区</h3><p>每个关键字的读缓冲区的大小。可选选项,默认值是256K。</p><p>对于每个搜索查询中的每个关键词,有两个相关的读缓冲区(一个针对文档列表,一个针对关键词出现位置列表)。本选项允许控制他们的大小,增加每次查询的内存占用,但可能会减少IO时间。</p><h4>示例:</h4><pre><span><span>read_buffer</span></span> = <span><span>1</span></span>M</pre><h3>11.4.24. read_unhinted:无匹配时读取大小</h3><p>无匹配时读操作的大小。可选选项,默认值是32K。</p><p>当系统处理查询时,对于一些读取操作,系统预先就知道要读取的数据的确切长度,但是有一些却相反。其中对常见的是已匹配位置列表(hitlist)

的长度目前是无法预先取得的。这个选项控制在这些情况下读取多少数据。它会影响IO时间,对于比本选项设置值大的列表,IO时间减少,而对于那些较小的列
表则是IO时间增加。内存占用不受影响,因为读缓冲区已经是分配好了的。也因此这个选项的设置值不能超过选项read_buffer的设置值。</p><h4>示例:</h4><pre><span><span>read_unhinted</span></span> = <span><span>32</span></span>K</pre><h3>11.4.25. max_batch_queries:最大批量查询</h3><p>每次批量查询的查询数限制。 可选项,默认为32个。</p><p>Makes searchd perform a sanity check of the amount of the queries submitted in a single batch when using multi-queries. Set it to 0 to skip the check.</p><h4>示例:</h4><pre><span><span>max_batch_queries</span></span> = <span><span>256</span></span></pre><h3>11.4.26. subtree_docs_cache:子树优化文档缓存</h3><p>每个查询的公共子树文档缓存大小。 可选值,默认为0(禁止)。</p><p>Limits RAM usage of a common subtree optimizer (参见 第 5.11 节 “批量查询”). At most this much RAM will be spent to cache document entries per each query. Setting the limit to 0 disables the optimizer.</p><h4>示例:</h4><pre><span><span>subtree_docs_cache</span></span> = <span><span>8</span></span>M</pre><h3>11.4.27. subtree_hits_cache:子树优化命中缓存</h3><p>每个查询的公共子树命中缓存大小。 可选值,默认为0(禁止)。</p><p>Limits RAM usage of a common subtree optimizer (参见 第 5.11 节 “批量查询”).
At most this much RAM will be spent to cache keyword occurrences (hits)
per each query. Setting the limit to 0 disables the optimizer.</p><h4>示例:</h4><pre><span><span>subtree_hits_cache</span></span> = <span><span>16</span></span>M</pre><h3>11.4.28. workers:MPM模式</h3><p>多处理模式(MPM)。 可选项;可用值为none、fork、prefork,以及threads。 默认在Unix类系统为form,Windows系统为threads。 版本2.0.1-beta引入。</p><p>Lets you choose how searchd processes multiple concurrent requests. The possible values are:</p><dl><dt>

        none 
      </dt><dd>
        All requests will be handled serially, one-by-one. Prior to 1.x, this was the only mode available on Windows. 
      </dd><dt>
        fork 
      </dt><dd>
        A new child process will be forked to handle every incoming request. Historically, this is the default mode. 
      </dd><dt>
        prefork 
      </dt><dd>
        On startup,&nbsp; 
       <code>searchd</code>&nbsp;will pre-fork a number of worker processes, and pass the incoming requests to one of those children. 
      </dd><dt>
        threads 
      </dt><dd>
        A new thread will be created to handle every incoming 

request. This is the only mode compatible with RT indexing backend.

      </dd></dl><p>&nbsp;</p><p>Historically,&nbsp;searchd&nbsp;used fork-based model, 

which generally performs OK but spends a noticeable amount of CPU in
fork() system call when there’s a high amount of (tiny) requests per
second. Prefork mode was implemented to alleviate that; with prefork,
worker processes are basically only created on startup and re-created on
index rotation, somewhat reducing fork() call pressure.</p><p>Threads mode was implemented along with RT backend and is
required to use RT indexes. (Regular disk-based indexes work in all the
available modes.)</p><h4>示例:</h4><pre><span><span>workers</span></span> = threads</pre><h3>11.4.29. dist_threads:并发查询线程数</h3><p>Max local worker threads to use for parallelizable requests
(searching a distributed index; building a batch of snippets). Optional,
default is 0, which means to disable in-request parallelism.
版本2.0.1-beta引入。</p><p>Distributed index can include several local indexes. dist_threads lets
you easily utilize multiple CPUs/cores for that (previously existing
alternative was to specify the indexes as remote agents, pointing
searchd to itself and paying some network overheads).</p><p>When set to a value N greater than 1, this directive will
create up to N threads for every query, and schedule the specific
searches within these threads. For example, if there are 7 local indexes
to search and dist_threads is set to 2, then 2 parallel threads would
be created: one that sequentially searches 4 indexes, and another one
that searches the other 3 indexes.</p><p>In case of CPU bound workload, setting dist_threads to
1x the number of cores is advised (creating more threads than cores
will not improve query time). In case of mixed CPU/disk bound workload
it might sometimes make sense to use more (so that all cores could be
utilizes even when there are threads that wait for I/O completion).</p><p>Note that dist_threads does not require threads MPM. You can perfectly use it with fork or prefork MPMs too.</p><p>Starting with version 2.0.1-beta, building a batch of snippets with load_files flag enabled can also be parallelized. Up to dist_threads threads
are be created to process those files. That speeds up snippet
extraction when the total amount of document data to process is
significant (hundreds of megabytes).</p><h4>示例:</h4><pre>index dist_<span><span>test</span></span>
{
<span><span>type</span></span> = distributed
<span><span>local</span></span> = chunk1
<span><span>local</span></span> = chunk2
<span><span>local</span></span> = chunk3
<span><span>local</span></span> = chunk4
}

<span><span># ...</span></span>

dist_threads = 4</pre><h3>11.4.30. binlog_path:二进制日志路径</h3><p>Binary log (aka transaction log) files path. Optional, default is build-time configured data directory. 版本2.0.1-beta引入。</p><p>Binary logs are used for crash recovery of RT index data that
would otherwise only be stored in RAM. When logging is enabled, every
transaction COMMIT-ted into RT index gets written into a log file. Logs
are then automatically replayed on startup after an unclean shutdown,
recovering the logged changes.</p><p>binlog_path directive specifies the binary log files location. It should contain just the path; searchd will create and unlink multiple binlog.* files in that path as necessary (binlog data, metadata, and lock files, etc).</p><p>Empty value disables binary logging. That improves performance, but puts RT index data at risk.</p><h4>示例:</h4><pre>binlog_path = <span><span># disable logging</span></span>
binlog_path = /<span><span>var</span></span>/data <span><span># /var/data/binlog.001 etc will be created</span></span>
</pre><h3>11.4.31. binlog_flush:二进制日志刷新</h3><p>Binary log transaction flush/sync mode. Optional, default is 2 (flush every transaction, sync every second). 版本2.0.1-beta引入。</p><p>This directive controls how frequently will binary log be flushed to OS and synced to disk. Three modes are supported:</p><ul><li>0, flush and sync every second. Best performance, but up
to 1 second worth of committed transactions can be lost both on daemon
crash, or OS/hardware crash.</li><li>1, flush and sync every transaction. Worst performance, but every committed transaction data is guaranteed to be saved.</li><li>2, flush every transaction, sync every second. Good
performance, and every committed transaction is guaranteed to be saved
in case of daemon crash. However, in case of OS/hardware crash up to 1
second worth of committed transactions can be lost.</li></ul><p> </p><p>For those familiar with MySQL and InnoDB, this directive is entirely similar to innodb_flush_log_at_trx_commit.
In most cases, the default hybrid mode 2 provides a nice balance of
speed and safety, with full RT index data protection against daemon
crashes, and some protection against hardware ones.</p><h4>示例:</h4><pre><span><span>binlog_flush</span></span> = <span><span>1</span></span> <span><span># ultimate safety, low speed</span></span></pre><h3>11.4.32. binlog_max_log_size:二进制日志大小限制</h3><p>Maximum binary log file size. Optional, default is 0 (do not reopen binlog file based on size). 版本2.0.1-beta引入。</p><p>A new binlog file will be forcibly opened once the current
binlog file reaches this limit. This achieves a finer granularity of
logs and can yield more efficient binlog disk usage under certain
borderline workloads.</p><h4>示例:</h4><pre><span><span>binlog_max_log_size</span></span> = <span><span>16</span></span>M</pre><h3>11.4.33. collation_server:服务端默认字符集</h3><p>Default server collation. Optional, default is libc_ci. 版本2.0.1-beta引入。</p><p>Specifies the default collation used for incoming requests. The collation can be overridden on a per-query basis. Refer to 第 5.12 节 “字符串排序规则” section for the list of available collations and other details.</p><h4>示例:</h4><pre><span><span>collation_server</span></span> = utf8_ci</pre><h3>11.4.34. collation_libc_locale:服务端libc字符集</h3><p>Server libc locale. Optional, default is C. 版本2.0.1-beta引入。</p><p>Specifies the libc locale, affecting the libc-based collations. Refer to 第 5.12 节 “字符串排序规则” section for the details.</p><h4>示例:</h4><pre><span><span>collation_libc_locale</span></span> = fr_FR</pre><h3>11.4.35. plugin_dir:插件目录</h3><p>Trusted location for the dynamic libraries (UDFs). Optional, default is empty (no location). 版本2.0.1-beta引入。</p><p>Specifies the trusted directory from which the UDF libraries can be loaded. Requires workers = thread to take effect.</p><h4>示例:</h4><pre><span><span>workers</span></span> = threads
<span><span>plugin_dir</span></span> = /usr/local/sphinx/lib
</pre><h3>11.4.36. mysql_version_string:MySQL版本设置</h3><p>A server version string to return via MySQL protocol. Optional, default is empty (return Sphinx version). 版本2.0.1-beta引入。</p><p>Several picky MySQL client libraries depend on a particular
version number format used by MySQL, and moreover, sometimes choose a
different execution path based on the reported version number (rather
than the indicated capabilities flags). For instance, Python MySQLdb
1.2.2 throws an exception when the version number is not in X.Y.ZZ
format; MySQL .NET connector 6.3.x fails internally on version numbers
1.x along with a certain combination of flags, etc. To workaround that,
you can use mysql_version_string directive and have searchd report a different version to clients connecting over MySQL protocol. (By default, it reports its own version.)</p><h4>示例:</h4><pre><span><span>mysql_version_string</span></span> = <span><span>5.0</span></span>.<span><span>37</span></span></pre><h3>11.4.37. rt_flush_period:RT索引刷新周期</h3><p>RT indexes RAM chunk flush check period, in seconds. Optional, default is 0 (do not flush). 版本2.0.1-beta引入。</p><p>Actively updated RT indexes that however fully fit in RAM
chunks can result in ever-growing binlogs, impacting disk use and crash
recovery time. With this directive the search daemon performs periodic
flush checks, and eligible RAM chunks can get saved, enabling
consequential binlog cleanup. 参见 第 4.4 节 “二进制日志” for more details.</p><h4>示例:</h4><pre><span><span>rt_flush_period</span></span> = <span><span>3600</span></span></pre><h3>11.4.38. thread_stack:线程堆栈</h3><p>Per-thread stack size. Optional, default is 64K. 版本2.0.1-beta引入。</p><p>In the workers = threads mode, every request is
processed with a separate thread that needs its own stack space. By
default, 64K per thread are allocated for stack. However, extremely
complex search requests might eventually exhaust the default stack and
require more. For instance, a query that matches a few thousand keywords
(either directly or through term expansion) can eventually run out of
stack. Previously, that resulted in crashes. Starting with 2.0.1-beta, searchd attempts
to estimate the expected stack use, and blocks the potentially
dangerous queries. To process such queries, you can either the thread
stack size by using the thread_stack directive (or switch to a different workers setting if that is possible).</p><p>A query with N levels of nesting is estimated to require
approximately 30+0.12*N KB of stack, meaning that the default 64K is
enough for queries with upto 300 levels, 150K for upto 1000 levels, etc.
If the stack size limit is not met, searchd fails the query and reports the required stack size in the error message.</p><h4>示例:</h4><pre><span><span>thread_stack</span></span> = <span><span>256</span></span>K</pre><h3>11.4.39. expansion_limit:关键字展开限制</h3><p>The maximum number of expanded keywords for a single wildcard. Optional, default is 0 (no limit). 版本2.0.1-beta引入。</p><p>When doing substring searches against indexes built with dict = keywords enabled,
a single wildcard may potentially result in thousands and even millions
of matched keywords (think of matching ‘a*’ against the entire Oxford
dictionary). This directive lets you limit the impact of such
expansions. Setting expansion_limit = N restricts expansions to no more than N of the most frequent matching keywords (per each wildcard in the query).</p><h4>示例:</h4><pre><span><span>expansion_limit</span></span> = <span><span>16</span></span></pre><h3>11.4.40. compat_sphinxql_magics</h3><p>Legacy SphinxQL quirks compatiblity mode. Optional, default is 1 (keep compatibility). Introduced in version 2.0.1-beta.</p><p>Starting with version 2.0.1-beta, we’re bringing SphinxQL in
closer compliance with standard SQL. However, existing applications must
not get broken, and compat_sphinxql_magics lets you upgrade safely. It defauls to 1, which enables the compatibility mode. However, SphinxQL compatibility mode is now deprecated and will be removed once
we complete bringing SphinxQL in line with standard SQL syntax. So it’s
advised to update the applications utilising SphinxQL and then switch
the daemon to the new, more SQL compliant mode by settingcompat_sphinxql_magics = 0. Please refer to 第 7.21 节 “SphinxQL 升级备注, version 2.0.1-beta” for the details and update instruction.</p><h4>Example:</h4><pre><span><span>compat_sphinxql_magics</span></span> = <span><span>0</span></span> <span><span># the future is now</span></span></pre><h3>11.4.41. watchdog</h3><p>Threaded server watchdog. Optional, default is 1 (watchdog enabled). Introduced in version 2.0.1-beta.</p><p>A crashed query in threads multi-processing mode (workers = threads) can take down the entire server. With watchdog feature enabled, searchd additionally
keeps a separate lightweight process that monitors the main server
process, and automatically restarts the latter in case of abnormal
termination. Watchdog is enabled by default.</p><h4>Example:</h4><pre><span><span>watchdog</span></span> = <span><span>0</span></span> <span><span># disable watchdog</span></span></pre><h2>第 12 章  Coreseek配置选项参考</h2><p>目录</p><dl><dt>

     <a href="#coreseek-confgroup-chinese">12.1. 中文分词核心配置</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#coreseek-conf-chinese-charset_dictpath">12.1.1. charset_dictpath</a> 
      </dt><dt> 
       <a href="#coreseek-conf-chinese-charset_type">12.1.2. charset_type</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#coreseek-confgroup-mmseg">12.2. MMSEG分词配置选项</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#coreseek-conf-mmseg-merge_number_and_ascii">12.2.1. merge_number_and_ascii</a> 
      </dt><dt> 
       <a href="#coreseek-conf-mmseg-number_and_ascii_joint">12.2.2. number_and_ascii_joint</a> 
      </dt><dt> 
       <a href="#coreseek-conf-mmseg-compress_space">12.2.3. compress_space</a> 
      </dt><dt> 
       <a href="#coreseek-conf-mmseg-seperate_number_ascii">12.2.4. seperate_number_ascii</a> 
      </dt></dl> 
    </dd><dt> 
     <a href="#coreseek-confgroup-pysource">12.3. Python数据源程序接口</a> 
    </dt><dd> 
     <dl><dt> 
       <a href="#coreseek-conf-pysource-GetScheme">12.3.1. GetScheme() (设置检索字段的属性)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-GetKillList">12.3.2. GetKillList() (设置不参与检索的文档编号)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-GetFieldOrder">12.3.3. GetFieldOrder() (设置字段的顺序)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-Connected">12.3.4. Connected() (获取数据前的连接处理)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-OnBeforeIndex">12.3.5. OnBeforeIndex() (数据获取前处理)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-NextDocument">12.3.6. NextDocument() (文档获取处理)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-OnAfterIndex">12.3.7. OnAfterIndex() (数据获取后处理)</a> 
      </dt><dt> 
       <a href="#coreseek-conf-pysource-OnIndexFinished">12.3.8. OnIndexFinished() (索引完成时处理)</a> 
      </dt></dl> 
    </dd></dl><h2>12.1.&nbsp;中文分词核心配置</h2><p>关于中文分词的详细配置实例和分词词典的自定义设置,可以访问<a href="http://www.coreseek.cn/products-install/coreseek_mmseg/" target="_top">Coreseek网站中文分词核心配置</a>查看。</p><pre>核心配置:<code>charset_dictpath</code>        = /usr/<span>local</span>/mmseg3/etc/<code>charset_<span><span>type</span></span></code>                 = zh_cn.utf-8

<span>#</span><span>charset_table</span><span> = .................... #需将原有的该配置注释掉</span><span>ngram_len</span><span> = 0</span></pre><p> </p><h3>12.1.1. charset_dictpath</h3><p>设置中文分词词典所在的目录;</p><h4>示例:</h4><pre><span><span>#Linux</span></span>
<span><span>charset_dictpath</span></span> = /usr/local/mmseg3/etc/
<span><span>#Windows</span></span>
<span><span>charset_dictpath</span></span> = C:\usr\local\coreseek\etc
</pre><h3>12.1.2. charset_type</h3><p>设置文档的字符集,可选的值为“zh_cn.utf-8”、“zh_cn.gbk”和“zh_cn.big5”。“zh_cn.gbk”和“zh_cn.big5”需要iconv支持。</p><h4>示例:</h4><pre><span><span>charset_type</span></span> = zh_cn.utf-<span><span>8</span></span></pre><h2>12.2. MMSEG分词配置选项</h2><p>mmseg分词相关的配置选项,需要保存到文件mmseg.ini,并将该配置文件放置到charset_dictpath所设置的目录中。</p><pre>基本配置:
[mmseg]merge_number_and_ascii=0; ;合并英文和数字 abc123/xnumber_and_ascii_joint=-; ;定义可以连接英文和数字的字符compress_space=1; ;暂不支持seperate_number_ascii=0; ;就是将字母和数字打散
其中,分号表示注释</pre><p> </p><h3>12.2.1. merge_number_and_ascii</h3><p>是否合并英文和数字,该选项设置是否将连接在一起的英文字母和数字作为一个整体看待</p><h4>例如:</h4><pre><span><span>merge_number_and_ascii</span></span>=<span><span>0</span></span>; ;abc123将被切分为abc、<span><span>123</span></span>
<span><span>merge_number_and_ascii</span></span>=<span><span>1</span></span>; ;abc123将不被切分
</pre><h3>12.2.2. number_and_ascii_joint</h3><p>定义可以连接英文和数字的字符</p><h4>例如:</h4><pre><span><span>number_and_ascii_joint</span></span>=-_; ;abc_123、abc-<span><span>123</span></span>都将作为整体</pre><h3>12.2.3. compress_space</h3><p>预设配置,暂不支持</p><h3>12.2.4. seperate_number_ascii</h3><p>是否将字母和数字打散</p><h4>例如:</h4><pre><span><span>seperate_number_ascii</span></span>=<span><span>0</span></span>; ;abc作为整体
<span><span>seperate_number_ascii</span></span>=<span><span>1</span></span>; ;abc被切分为a、b、c
</pre><h2>12.3. Python数据源程序接口</h2><p>Python数据源的各种实例程序,可以访问Coreseek网站Python数据源获取。该部分的相关文档,还在继续完善中。</p><pre><span><span>#Python数据源基本演示程序</span></span>
<span><span>#/usr/local/coreseek/etc/pysource/csft_demo/__init__.py</span></span>
<span><span># -- coding:utf-8 --</span></span>

<span><span><span><span>class</span></span></span><span> </span><span><span><span>MainSource</span></span></span><span><span><span>(object)</span></span></span><span>:</span></span>
<span><span><span><span>def</span></span></span><span> </span><span><span><span>init</span></span></span><span><span><span>(self, conf)</span></span></span><span>:</span></span>
self.conf = conf
self.data = [
{<span><span>'id'</span></span>:<span><span>1</span></span>, <span><span>'subject'</span></span>:<span><span>u"标题1"</span></span>, <span><span>'date'</span></span>:<span><span>1270131607</span></span>},
{<span><span>'id'</span></span>:<span><span>2</span></span>, <span><span>'subject'</span></span>:<span><span>u'标题2'</span></span>, <span><span>'date'</span></span>:<span><span>1270135548</span></span>},
]
self.idx = <span><span>0</span></span>

<span><span><span><span>def</span></span></span><span> </span><span><span><span>GetScheme</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>return</span></span> [
(<span><span>'id'</span></span> , {<span><span>'docid'</span></span>:<span><span>True</span></span>, } ),
(<span><span>'subject'</span></span>, { <span><span>'type'</span></span>:<span><span>'text'</span></span>} ),
(<span><span>'date'</span></span>, {<span><span>'type'</span></span>:<span><span>'integer'</span></span>} ),
]

<span><span><span><span>def</span></span></span><span> </span><span><span><span>GetKillList</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>return</span></span> [<span><span>3</span></span>,<span><span>1</span></span>]

<span><span><span><span>def</span></span></span><span> </span><span><span><span>GetFieldOrder</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>return</span></span> (<span><span>'subject'</span></span>)

<span><span><span><span>def</span></span></span><span> </span><span><span><span>Connected</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>pass</span></span>

<span><span><span><span>def</span></span></span><span> </span><span><span><span>OnBeforeIndex</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>print</span></span> <span><span>'before index called'</span></span>
<span><span>pass</span></span>

<span><span><span><span>def</span></span></span><span> </span><span><span><span>NextDocument</span></span></span><span><span><span>(self, err)</span></span></span><span>:</span></span>
<span><span>if</span></span> self.idx < len(self.data):
item = self.data[self.idx]
self.id = item[<span><span>'id'</span></span>]
self.subject = item[<span><span>'subject'</span></span>].encode(<span><span>'utf-8'</span></span>)
self.date = item[<span><span>'date'</span></span>]
self.idx += <span><span>1</span></span>
<span><span>return</span></span> <span><span>True</span></span>
<span><span>else</span></span>:
<span><span>return</span></span> <span><span>False</span></span>
<span><span>pass</span></span>

<span><span><span><span>def</span></span></span><span> </span><span><span><span>OnAfterIndex</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>print</span></span> <span><span>'after index called'</span></span>
<span><span>pass</span></span>

<span><span><span><span>def</span></span></span><span> </span><span><span><span>OnIndexFinished</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>print</span></span> <span><span>'after index finished'</span></span>
<span><span>pass</span></span>

<span><span>if</span></span> name == <span><span>"__main__"</span></span>:
source = MainSource()
source.Connected()

source.OnBeforeIndex()
<span><span>while</span></span> source.NextDocument():
<span><span>print</span></span> <span><span>"id=%d, title=%s"</span></span> % (source.docid, source.title)

source.OnAfterIndex()
source.OnIndexFinished()
<span><span>pass</span></span>
<span><span>#eof</span></span>
</pre><p> </p><h3>12.3.1. GetScheme() (设置检索字段的属性)</h3><p>返回所有需要被索引的字段的属性</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>GetScheme</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>return</span></span> [
(<span><span>'id'</span></span> , {<span><span>'docid'</span></span>:<span><span>True</span></span>, } ),
(<span><span>'subject'</span></span>, { <span><span>'type'</span></span>:<span><span>'text'</span></span>} ),
(<span><span>'date'</span></span>, {<span><span>'type'</span></span>:<span><span>'integer'</span></span>} ),
]
</pre><p>在检索字段设置中,必须且仅有一个字段需要设置为docid,对应于SQL数据源中的文档编号。其他字段的属性,可以为integer,对应于sql_attr_uint,或者text,对应于全文检索字段。目前支持的类型如下:</p><ul><li>docid:对应于SQL数据源中的文档编号id</li><li>integer:整数属性,参见sql_attr_uint</li><li>bool:布尔属性,参见sql_attr_bool</li><li>long:长整型属性,参见sql_attr_bigint</li><li>timestamp:UNIX时间戳(整数)属性,参见sql_attr_timestamp</li><li>str2ord:字符串序数排序属性,参见sql_attr_str2ordinal</li><li>float:浮点数属性,参见sql_attr_float</li><li>list:多值属性(MVA)属性,参见sql_attr_multi的field</li><li>list-query:多值属性(MVA)属性,参见sql_attr_multi的query</li><li>string:字符串属性(可返回原始文本信息),参见sql_attr_string</li><li>string_text:字符串字段(可全文搜索,可返回原始文本信息),参见sql_field_string</li><li>text:全文检索字段,参见全文检索字段</li></ul><p> </p><h3>12.3.2. GetKillList() (设置不参与检索的文档编号)</h3><p>处于该列表之中的文档,将不被检索,对应于SQL数据源的sql_query_killlist</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>GetKillList</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>return</span></span> [<span><span>3</span></span>,<span><span>1</span></span>]
</pre><h3>12.3.3. GetFieldOrder() (设置字段的顺序)</h3><p>全文字段被检索的顺序</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>GetFieldOrder</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>return</span></span> [(<span><span>'subject'</span></span>,<span><span>'content'</span></span>)]
</pre><h3>12.3.4. Connected() (获取数据前的连接处理)</h3><p>一般用于进行数据库的连接等预处理</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>Connected</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>#在此进行数据库连接和处理</span></span>
<span><span>pass</span></span>
</pre><h3>12.3.5. OnBeforeIndex() (数据获取前处理)</h3><p>类似sql_query_pre配置选项的作用</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>OnBeforeIndex</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>print</span></span> <span><span>'before index called'</span></span>
<span><span>pass</span></span>
</pre><h3>12.3.6. NextDocument() (文档获取处理)</h3><p>获取实际的需要参与检索的数据,按条获取,需要获取的字段,作为self自身的属性给出,相当于sql_query的作用,每次读取一条数据</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>NextDocument</span></span></span><span><span><span>(self, err)</span></span></span><span>:</span></span>
<span><span>if</span></span> self.idx < len(self.data):
item = self.data[self.idx]
self.id = item[<span><span>'id'</span></span>]
self.subject = item[<span><span>'subject'</span></span>].encode(<span><span>'utf-8'</span></span>)
self.date = item[<span><span>'date'</span></span>]
self.idx += <span><span>1</span></span>
<span><span>return</span></span> <span><span>True</span></span>
<span><span>else</span></span>:
<span><span>return</span></span> <span><span>False</span></span>
<span><span>pass</span></span>
</pre><h3>12.3.7. OnAfterIndex() (数据获取后处理)</h3><p>类似sql_query_post配置选项的作用</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>OnAfterIndex</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>print</span></span> <span><span>'after index called'</span></span>
<span><span>pass</span></span>
</pre><h3>12.3.8. OnIndexFinished() (索引完成时处理)</h3><p>类似sql_query_post_index配置选项的作用</p><h4>例如:</h4><pre><span><span><span><span>def</span></span></span><span> </span><span><span><span>OnIndexFinished</span></span></span><span><span><span>(self)</span></span></span><span>:</span></span>
<span><span>print</span></span> <span><span>'after index finished'</span></span>
<span><span>pass</span></span>
</pre><h2>附录 A. Sphinx revision history</h2><p>目录</p><dl><dt>

     <a href="#rel111">A.1. Version 2.0.1-beta, 22 apr 2011</a> 
    </dt><dt> 
     <a href="#rel110">A.2. Version 1.10-beta, 19 jul 2010</a> 
    </dt><dt> 
     <a href="#rel099">A.3. Version 0.9.9-release, 02 dec 2009</a> 
    </dt><dt> 
     <a href="#rel099rc2">A.4. Version 0.9.9-rc2, 08 apr 2009</a> 
    </dt><dt> 
     <a href="#rel099rc1">A.5. Version 0.9.9-rc1, 17 nov 2008</a> 
    </dt><dt> 
     <a href="#rel0981">A.6. Version 0.9.8.1, 30 oct 2008</a> 
    </dt><dt> 
     <a href="#rel098">A.7. Version 0.9.8, 14 jul 2008</a> 
    </dt><dt> 
     <a href="#rel097">A.8. Version 0.9.7, 02 apr 2007</a> 
    </dt><dt> 
     <a href="#rel097rc2">A.9. Version 0.9.7-rc2, 15 dec 2006</a> 
    </dt><dt> 
     <a href="#rel097rc">A.10. Version 0.9.7-rc1, 26 oct 2006</a> 
    </dt><dt> 
     <a href="#rel096">A.11. Version 0.9.6, 24 jul 2006</a> 
    </dt><dt> 
     <a href="#rel096rc1">A.12. Version 0.9.6-rc1, 26 jun 2006</a> 
    </dt></dl><h2>A.1.&nbsp;Version 2.0.1-beta, 22 apr 2011</h2><h3>New general features</h3><ul><li>added remapping support to&nbsp;<a href="#conf-blend-chars">blend_chars</a>&nbsp;directive</li><li>added multi-threaded snippet batches support (requires a batch sent via API,&nbsp;<a href="#conf-dist-threads">dist_threads</a>, and&nbsp;load_files)</li><li>added collations (<a href="#conf-collation-server">collation_server</a>,&nbsp;<a href="#conf-collation-libc-locale">collation_libc_locale directives</a>)</li><li>added support for sorting and grouping on string attributes (ORDER BY,&nbsp;GROUP BY,&nbsp;WITHING GROUP ORDER BY)</li><li>added UDF support (<a href="#conf-plugin-dir">plugin_dir</a>&nbsp;directive;&nbsp;<a href="#sphinxql-create-function">CREATE FUNCTION</a>,&nbsp;<a href="#sphinxql-drop-function">DROP FUNCTION</a>&nbsp;statements)</li><li>added&nbsp;<a href="#conf-query-log-format">query_log_format</a>&nbsp;directive,&nbsp;<a href="#sphinxql-set">SET GLOBAL query_log_format | log_level = …</a>&nbsp;statements; and connection id tracking</li><li>added&nbsp;<a href="#conf-sql-column-buffers">sql_column_buffers</a>&nbsp;directive, fixed out-of-buffer column handling in ODBC/MS SQL sources</li><li>added&nbsp;<a href="#conf-blend-mode">blend_mode</a>&nbsp;directive that enables indexing multiple variants of a blended sequence</li><li>added UNIX socket support to C, Ruby APIs</li><li>added ranged query support to&nbsp;<a href="#conf-sql-joined-field">sql_joined_field</a></li><li>added&nbsp;<a href="#conf-rt-flush-period">rt_flush_period</a>&nbsp;directive</li><li>added&nbsp;<a href="#conf-thread-stack">thread_stack</a>&nbsp;directive</li><li>added SENTENCE, PARAGRAPH, ZONE operators (and&nbsp;<a href="#conf-index-sp">index_sp</a>,&nbsp;<a href="#conf-index-zones">index_zones</a>&nbsp;directives)</li><li>added keywords dictionary support (and&nbsp;<a href="#conf-dict">dict</a>,&nbsp;<a href="#conf-expansion-limit">expansion_limit</a>&nbsp;directives)</li><li>added&nbsp;passage_boundary,&nbsp;emit_zones&nbsp;options to snippets</li><li>added&nbsp;<a href="#conf-watchdog">a watchdog process</a>&nbsp;in threaded mode</li><li>added persistent MVA updates</li><li>added crash dumps to&nbsp;searchd.log, deprecated&nbsp;crash_log_path&nbsp;directive</li><li>added id32 index support in id64 binaries (EXPERIMENTAL)</li><li>added SphinxSE support for DELETE and REPLACE on SphinxQL tables</li></ul><h3>New SphinxQL features</h3><ul><li>added new, more SQL compliant SphinxQL syntax; and a&nbsp;<a href="#conf-compat-sphinxql-magics">compat_sphinxql_magics</a>&nbsp;directive</li><li>added&nbsp;<a href="#expr-func-crc32">CRC32()</a>,&nbsp;<a href="#expr-func-day">DAY()</a>,&nbsp;<a href="#expr-func-month">MONTH()</a>,&nbsp;<a href="#expr-func-year">YEAR()</a>,&nbsp;<a href="#expr-func-yearmonth">YEARMONTH()</a>,&nbsp;<a href="#expr-func-yearmonthday">YEARMONTHDAY()</a>&nbsp;functions</li><li>added&nbsp;<a href="#expr-ari-ops">DIV, MOD, and % operators</a></li><li>added&nbsp;<a href="#sphinxql-select">reverse_scan=(0|1)</a>&nbsp;option to SELECT</li><li>added support for MySQL packets over 16M</li><li>added dummy SHOW VARIABLES, SHOW COLLATION, and SET 

character_set_results support (to support handshake with certain client
libraries and frameworks)</li><li>added mysql_version_string directive (to workaround picky MySQL client libraries)</li><li>added support for global filter variables, SET GLOBAL @uservar=(int_list)</li><li>added DELETE … IN (id_list) syntax support</li><li>added C-style comments syntax (for example, SELECT /!40000 some comment/ id FROM test)</li><li>added UPDATE … WHERE id=X syntax support</li><li>added SphinxQL multi-query support</li><li>added DESCRIBESHOW TABLES statements</li></ul><h3>New command-line switches</h3><ul><li>added --print-queries switch to indexer that dumps SQL queries it runs</li><li>added --sighup-each switch to indexer that rotates indexes one by one</li><li>added --strip-path switch to searchd that skips file paths embedded in the index(-es)</li><li>added --dumpconfig switch to indextool that dumps an index header in sphinx.conf format</li></ul><h3>Major changes and optimizations</h3><ul><li>changed default preopen_indexes value to 1</li><li>optimized English stemmer (results in 1.3x faster snippets and indexing with morphology=stem_en)</li><li>optimized snippets, 1.6x general speedup</li><li>optimized const-list parsing in SphinxQL</li><li>optimized full-document highlighting CPU/RAM use</li><li>optimized binlog replay (improved performance on K-list update)</li></ul><h3>Bug fixes</h3><ul><li>fixed #767, joined fields vs ODBC sources</li><li>fixed #757, wordforms shared by indexes with different settings</li><li>fixed #733, loading of indexes in formats prior to v.14</li><li>fixed #763, occasional snippets failures</li><li>fixed #648, occasionally missed rotations on multiple SIGHUPs</li><li>fixed #750, an RT segment merge leading to false positives and/or crashes in some cases</li><li>fixed #755, zones in snippets output</li><li>fixed #754, stopwords counting at snippet passage generation</li><li>fixed #723, fork/prefork index rotation in children processes</li><li>fixed #696, freeze on zero threshold in quorum operator</li><li>fixed #732, query escaping in SphinxSE</li><li>fixed #739, occasional crashes in MT mode on result set send</li><li>fixed #746, crash with a named list in SphinxQL option</li><li>fixed #674, AVG vs group order</li><li>fixed #734, occasional crashes attempting to report NULL errors</li><li>fixed #829, tail hits within field position modifier</li><li>fixed #712, missing query_mode, force_all_words snippet option defaults in Java API</li><li>fixed #721, added dupe removal on RT batch INSERT/REPLACE</li><li>fixed #720, potential extraneous highlighting after a blended keyword</li><li>fixed #702, exceptions vs star search</li><li>fixed #666, ext2 query grouping vs exceptions</li><li>fixed #688, WITHIN GROUP ORDER BY related crash</li><li>fixed #660, multi-queue batches vs dist_threads</li><li>fixed #678, crash on dict=keywords vs xmlpipe vs min_prefix_len</li><li>fixed #596, ECHILD vs scripted configs</li><li>fixed #653, dependency in expression, sorting, grouping</li><li>fixed #661, concurrent distributed searches vs workers=threads</li><li>fixed #646, crash on status query via UNIX socket</li><li>fixed #589, libexpat.dll missing from some Win32 build types</li><li>fixed #574, quorum match order</li><li>fixed multiple documentation issues (#372, #483, #495, #601, #623, #632, #654)</li><li>fixed that ondisk_dict did not affect RT indexes</li><li>fixed that string attributes check in indextool –check was erroneously sensitive to string data order</li><li>fixed a rare crash when using BEFORE operator</li><li>fixed an issue with multiforms vs BuildKeywords()</li><li>fixed an edge case in OR operator (emitted wrong hits order sometimes)</li><li>fixed aliasing in docinfo accessors that lead to very rare crashes and/or missing results</li><li>fixed a syntax error on a short token at the end of a query</li><li>fixed id64 filtering and performance degradation with range filters</li><li>fixed missing rankers in libsphinxclient</li><li>fixed missing SPH04 ranker in SphinxSE</li><li>fixed column names in sql_attr_multi sample (works with example.sql now)</li><li>fixed an issue with distributed local+remote setup vs aggregate functions</li><li>fixed case sensitive columns names in RT indexes</li><li>fixed a crash vs strings from multiple indexes in result set</li><li>fixed blended keywords vs snippets</li><li>fixed secure_connection vs MySQL protocol vs MySQL.NET connector</li><li>fixed that Python API did not works with Python 2.3</li><li>fixed overshort_step vs snippets</li><li>fixed keyword staistics vs dist_threads searching</li><li>fixed multiforms vs query parsing (vs quorum)</li><li>fixed missed quorum words vs RT segments</li><li>fixed blended keywords occasionally skipping extra character when querying (eg “abc[]“)</li><li>fixed Python API to handle int32 values</li><li>fixed prefix and infix indexing of joined fields</li><li>fixed MVA ranged query</li><li>fixed missing blended state reset on document boundary</li><li>fixed a crash on missing index while replaying binlog</li><li>fixed an error message on filter values overrun</li><li>fixed passage duplication in snippets in weight_order mode</li><li>fixed select clauses over 1K vs remote agents</li><li>fixed overshort accounting vs soft-whitespace tokens</li><li>fixed rotation vs workers=threads</li><li>fixed schema issues vs distributed indexes</li><li>fixed blended-escaped sequence parsing issue</li><li>fixed MySQL IN clause (values order etc)</li><li>fixed that post_index did not execute when 0 documents were succesfully indexed</li><li>fixed field position limit vs many hits</li><li>fixed that joined fields missed an end marker at field end</li><li>fixed that xxx_step settings were missing from .sph index header</li><li>fixed libsphinxclient missing request cleanup in sphinx_query() (eg after network errors)</li><li>fixed that index_weights were ignored when grouping</li><li>fixed multi wordforms vs blend_chars</li><li>fixed broken MVA output in SphinxQL</li><li>fixed a few RT leaks</li><li>fixed an issue with RT string storage going missing</li><li>fixed an issue with repeated queries vs dist_threads</li><li>fixed an issue with string attributes vs buffer overrun in SphinxQL</li><li>fixed unexpected character data warnings within ignored xmlpipe tags</li><li>fixed a crash in snippets with NEAR syntax query</li><li>fixed passage duplication in snippets</li><li>fixed libsphinxclient SIGPIPE handling</li><li>fixed libsphinxclient vs VS2003 compiler bug</li></ul><h2>A.2. Version 1.10-beta, 19 jul 2010</h2><ul><li>added RT indexes support (第 4 章 RT实时索引)</li><li>added prefork and threads support (workers directives)</li><li>added multi-threaded local searches in distributed indexes (dist_threads directive)</li><li>added common subquery cache (subtree_docs_cachesubtree_hits_cache directives)</li><li>added string attributes support (sql_attr_stringsql_field_stringxml_attr_stringxml_field_string directives)</li><li>added indexing-time word counter (sql_attr_str2wordcountsql_field_str2wordcount directives)</li><li>added CALL SNIPPETS()CALL KEYWORDS() SphinxQL statements</li><li>added field_weights, index_weights options to SphinxQL SELECT statement</li><li>added insert-only SphinxQL-talking tables to SphinxSE (connection=’sphinxql://host[:port]/index’)</li><li>added select option to SphinxSE queries</li><li>added backtrace on crash to searchd</li><li>added SQL+FS indexing, aka loading files by names fetched from SQL (sql_file_field directive)</li><li>added a watchdog in threads mode to searchd</li><li>added automatic row phantoms elimination to index merge</li><li>added hitless indexing support (hitless_words directive)</li><li>added –check, –strip-path, –htmlstrip, –dumphitlist … –wordid switches to indextool</li><li>added –stopwait, –logdebug switches to searchd</li><li>added –dump-rows, –verbose switches to indexer</li><li>added “blended” characters indexing support (blend_chars directive)</li><li>added joined/payload field indexing (sql_joined_field directive)</li><li>added FlushAttributes() API call</li><li>added query_mode, force_all_words, limit_passages,
limit_words, start_passage_id, load_files, html_strip_mode, allow_empty
options, and %PASSAGE_ID% macro in before_match, after_match options to BuildExcerpts() API call</li><li>added @groupby/@count/@distinct columns support to SELECT (but not to expressions)</li><li>added query-time keyword expansion support (expand_keywords directive, SPH_RANK_SPH04 ranker)</li><li>added query batch size limit option (max_batch_queries directive; was hardcoded)</li><li>added SINT() function to expressions</li><li>improved SphinxQL syntax error reporting</li><li>improved expression optimizer (better constant handling)</li><li>improved dash handling within keywords (no longer treated as an operator)</li><li>improved snippets (better passage selection/trimming, around option now a hard limit)</li><li>optimized index format that yields ~20-30% smaller indexes</li><li>optimized sorting code (indexing time 1-5% faster on average; 100x faster in worst case)</li><li>optimized searchd startup time (moved .spa preindexing to indexer), added a progress bar</li><li>optimized queries against indexes with many attributes (eliminated redundant copying)</li><li>optimized 1-keyword queries (performace regression introduced in 0.9.9)</li><li>optimized SphinxQL protocol overheads, and performance on bigger result sets</li><li>optimized unbuffered attributes writes on index merge</li><li>changed attribute handling, duplicate names are strictly forbidden now</li><li>fixed that SphinxQL sessions could stall shutdown</li><li>fixed consts with leading minus in SphinxQL</li><li>fixed AND/OR precedence in expressions</li><li>fixed #334, AVG() on integers was not computed in floats</li><li>fixed #371, attribute flush vs 2+ GB files</li><li>fixed #373, segfault on distributed queries vs certain libc versions</li><li>fixed #398, stopwords not stopped in prefix/infix indexes</li><li>fixed #404, erroneous MVA failures in indextool –check</li><li>fixed #408, segfault on certain query batches (regular scan, plus a scan with MVA groupby)</li><li>fixed #431, occasional shutdown hangs in preforked workers</li><li>fixed #436, trunk checkout builds vs Solaris sh</li><li>fixed #440, escaping vs parentheses declared as valid in charset_table</li><li>fixed #442, occasional non-aligned free in MVA indexing</li><li>fixed #447, occasional crashes in MVA indexing</li><li>fixed #449, pconn busyloop on aborted clients on certain arches</li><li>fixed #465, build issue on Alpha</li><li>fixed #468, build issue in libsphinxclient</li><li>fixed #472, multiple stopword files failing to load</li><li>fixed #489, buffer overflow in query logging</li><li>fixed #493, Python API assertion after error returned from Query()</li><li>fixed #500, malformed MySQL packet when sending MVAs</li><li>fixed #504, SIGPIPE in libsphinxclient</li><li>fixed #506, better MySQL protocol commands support in SphinxQL (PING etc)</li><li>fixed #509, indexing ranged results from stored procedures</li></ul><h2>A.3. Version 0.9.9-release, 02 dec 2009</h2><ul><li>added Open, Close, Status calls to libsphinxclient (C API)</li><li>added automatic persistent connection reopening to PHP, Python APIs</li><li>added 64-bit value/range filters, fullscan mode support to SphinxSE</li><li>MAJOR CHANGE, our IANA assigned ports are 9312 and 9306 respectively (goodbye, trusty 3312)</li><li>MAJOR CHANGE, erroneous filters now fail with an error (were silently ignored before)</li><li>optimized unbuffered .spa writes on merge</li><li>optimized 1-keyword queries ranking in extended2 mode</li><li>fixed #441 (IO race in case of highly conccurent load on a preopened)</li><li>fixed #434 (distrubuted indexes were not searchable via MySQL protocol)</li><li>fixed #317 (indexer MVA progress counter)</li><li>fixed #398 (stopwords not removed from search query)</li><li>fixed #328 (broken cutoff)</li><li>fixed #250 (now quoting paths w/spaces when installing Windows service)</li><li>fixed #348 (K-list was not updated on merge)</li><li>fixed #357 (destination index were not K-list-filtered on merge)</li><li>fixed #369 (precaching .spi files over 2 GBs)</li><li>fixed #438 (missing boundary proximity matches)</li><li>fixed #371 (.spa flush in case of files over 2 GBs)</li><li>fixed #373 (crashes on distributed queries via mysql proto)</li><li>fixed critical bugs in hit merging code</li><li>fixed #424 (ordinals could be misplaced during indexing in case of bitfields etc)</li><li>fixed #426 (failing SE build on Solaris; thanks to Ben Beecher)</li><li>fixed #423 (typo in SE caused crash on SHOW STATUS)</li><li>fixed #363 (handling of read_timeout over 2147 seconds)</li><li>fixed #376 (minor error message mismatch)</li><li>fixed #413 (minus in SphinxQL)</li><li>fixed #417 (floats w/o leading digit in SphinxQL)</li><li>fixed #403 (typo in SetFieldWeights name in Java API)</li><li>fixed index rotation vs persistent connections</li><li>fixed backslash handling in SphinxQL parser</li><li>fixed uint unpacking vs. PHP 5.2.9 (possibly other versions)</li><li>fixed #325 (filter settings send from SphinxSE)</li><li>fixed #352 (removed mysql wrapper around close() in SphinxSE)</li><li>fixed #389 (display error messages through SphinxSE status variable)</li><li>fixed linking with port-installed iconv on OS X</li><li>fixed negative 64-bit unpacking in PHP API</li><li>fixed #349 (escaping backslash in query emulation mode)</li><li>fixed #320 (disabled multi-query route when select items differ)</li><li>fixed #353 (better quorum counts check)</li><li>fixed #341 (merging of trailing hits; maybe other ranking issues too)</li><li>fixed #368 (partially; @field “” caused crashes; now resets field limit)</li><li>fixed #365 (field mask was leaking on field-limited terms)</li><li>fixed #339 (updated debug query dumper)</li><li>fixed #361 (added SetConnectTimeout() to Java API)</li><li>fixed #338 (added missing fullscan to mode check in Java API)</li><li>fixed #323 (added floats support to SphinxQL)</li><li>fixed #340 (support listen=port:proto syntax too)</li><li>fixed #332 (\r is legal SphinxQL space now)</li><li>fixed xmlpipe2 K-lists</li><li>fixed #322 (safety gaps in mysql protocol row buffer)</li><li>fixed #313 (return keyword stats for empty indexes too)</li><li>fixed #344 (invalid checkpoints after merge)</li><li>fixed #326 (missing CLOCK_xxx on FreeBSD)</li></ul><h2>A.4. Version 0.9.9-rc2, 08 apr 2009</h2><ul><li>added IsConnectError(), Open(), Close() calls to Java API (bug #240)</li><li>added read_bufferread_unhinted directives</li><li>added checks for build options returned by mysql_config (builds on Solaris now)</li><li>added fixed-RAM index merge (bug #169)</li><li>added logging chained queries count in case of (optimized) multi-queries</li><li>added GEODIST() function</li><li>added –status switch to searchd</li><li>added MySpell (OpenOffice) affix file support (bug #281)</li><li>added ODBC support (both Windows and UnixODBC)</li><li>added support for @id in IN() (bug #292)</li><li>added support for aggregate functions in GROUP BY (namely AVG, MAX, MIN, SUM)</li><li>added MySQL UDF that builds snippets using searchd</li><li>added write_buffer directive (defaults to 1M)</li><li>added xmlpipe_fixup_utf8 directive</li><li>added suggestions sample</li><li>added microsecond precision int64 timer (bug #282)</li><li>added listen_backlog directive</li><li>added max_xmlpipe2_field directive</li><li>added initial SphinxQL support to mysql41 handler, SELECT …/SHOW WARNINGS/STATUS/META are handled</li><li>added support for different network protocols, and mysql41 protocol</li><li>added fieldmask ranker, updated SphinxSE list of rankers</li><li>added mysql_ssl_xxx directives</li><li>added –cpustats (requires clock_gettime()) and –status switches to searchd</li><li>added performance counters, Status() API call</li><li>added overshort_step and stopword_step directives</li><li>added strict order operator (aka operator before, eg. “one << two << three”)</li><li>added indextool utility, moved –dumpheader there, added –debugdocids, –dumphitlist options</li><li>added own RNG, reseeded on @random sort query (bug #183)</li><li>added field-start and field-end modifiers support (syntax is “^hello world$”; field-end requires reindex)</li><li>added MVA attribute support to IN() function</li><li>added AND, OR, and NOT support to expressions</li><li>improved logging of (optimized) multi-queries (now logging chained query count)</li><li>improved handshake error handling, fixed protocol version byte order (omg)</li><li>updated SphinxSE to protocol 1.22</li><li>allowed phrase_boundary_step=-1 (trick to emulate keyword expansion)</li><li>removed SPH_MAX_QUERY_WORDS limit</li><li>fixed CLI search vs documents missing from DB (bug #257)</li><li>fixed libsphinxclient results leak on subsequent sphinx_run_queries call (bug #256)</li><li>fixed libsphinxclient handling of zero max_matches and cutoff (bug #208)</li><li>fixed Java API over-64K string reads (eg. big snippets) in Java API (bug #181)</li><li>fixed Java API 2nd Query() after network error in 1st Query() call (bug #308)</li><li>fixed typo-class bugs in SetFilterFloatRange (bug #259), SetSortMode (bug #248)</li><li>fixed missing @@relaxed support (bug #276), fixed missing error on @nosuchfield queries, documented @@relaxed</li><li>fixed UNIX socket permissions to 0777 (bug #288)</li><li>fixed xmlpipe2 crash on schemas with no fields, added better document structure checks</li><li>fixed (and optimized) expr parser vs IN() with huge (10K+) args count</li><li>fixed double EarlyCalc() in fullscan mode (minor performance impact)</li><li>fixed phrase boundary handling in some cases (on buffer end, on trailing whitespace)</li><li>fixes in snippets (aka excerpts) generation</li><li>fixed inline attrs vs id64 index corruption</li><li>fixed head searchd crash on config re-parse failure</li><li>fixed handling of numeric keywords with leading zeroes such as “007″ (bug #251)</li><li>fixed junk in SphinxSE status variables (bug #304)</li><li>fixed wordlist checkpoints serialization (bug #236)</li><li>fixed unaligned docinfo id access (bug #230)</li><li>fixed GetRawBytes() vs oversized blocks (headers with over 32K charset_table should now work, bug #300)</li><li>fixed buffer overflow caused by too long dest wordform, updated tests</li><li>fixed IF() return type (was always int, is deduced now)</li><li>fixed legacy queries vs. special chars vs. multiple indexes</li><li>fixed write-write-read socket access pattern vs Nagle vs delays vs FreeBSD (oh wow)</li><li>fixed exceptions vs query-parser issue</li><li>fixed late calc vs @weight in expressions (bug #285)</li><li>fixed early lookup/calc vs filters (bug #284)</li><li>fixed emulated MATCH_ANY queries (empty proximity and phrase queries are allowed now)</li><li>fixed MATCH_ANY ranker vs fields with no matches</li><li>fixed index file size vs inplace_enable (bug #245)</li><li>fixed that old logs were not closed on USR1 (bug #221)</li><li>fixed handling of ‘!’ alias to NOT operator (bug #237)</li><li>fixed error handling vs query steps (step failure was not reported)</li><li>fixed querying vs inline attributes</li><li>fixed stupid bug in escaping code, fixed EscapeString() and made it static</li><li>fixed parser vs @field -keyword, foo|@field bar, “” queries (bug #310)</li></ul><h2>A.5. Version 0.9.9-rc1, 17 nov 2008</h2><ul><li>added min_stemming_len directive</li><li>added IsConnectError() API call (helps distingusih API vs remote errors)</li><li>added duplicate log messages filter to searchd</li><li>added –nodetach debugging switch to searchd</li><li>added blackhole agents support for debugging/testing (agent_blackhole directive)</li><li>added max_filtersmax_filter_values directives (were hardcoded before)</li><li>added int64 expression evaluation path, automatic inference, and BIGINT() enforcer function</li><li>added crash handler for debugging (crash_log_path directive)</li><li>added MS SQL (aka SQL Server) source support (Windows only, mssql_winauth and mssql_unicode directives)</li><li>added indexer-side column unpacking feature (unpack_zlibunpack_mysqlcompress directives)</li><li>added nested brackers and NOTs support to query language, rewritten query parser</li><li>added persistent connections support (Open() and Close() API calls)</li><li>added index_exact_words feature, and exact form operator to query language (“hello =world”)</li><li>added status variables support to SphinxSE (SHOW STATUS LIKE ‘sphinx_%’)</li><li>added max_packet_size directive (was hardcoded at 8M before)</li><li>added UNIX socket support, and multi-interface support (listen directive)</li><li>added star-syntax support to BuildExcerpts() API call</li><li>added inplace inversion of .spa and .spp (inplace_enable directive, 1.5-2x less disk space for indexing)</li><li>added builtin Czech stemmer (morphology=stem_cz)</li><li>added IDIV(), NOW(), INTERVAL(), IN() functions to expressions</li><li>added index-level early-reject based on filters</li><li>added MVA updates feature (mva_updates_pool directive)</li><li>added select-list feature with computed expressions support (see SetSelect() API call, test.php –select switch), protocol 1.22</li><li>added integer expressions support (2x faster than float)</li><li>added multiforms support (multiple source words in wordforms file)</li><li>added legacy rankers (MATCH_ALL/MATCH_ANY/etc), removed legacy matching code (everything runs on V2 engine now)</li><li>added field position limit modifier to field operator (syntax: @title[50] hello world)</li><li>added killlist support (sql_query_killlist directive, –merge-killlists switch)</li><li>added on-disk SPI support (ondisk_dict directive)</li><li>added indexer IO stats</li><li>added periodic .spa flush (attr_flush_period directive)</li><li>added config reload on SIGHUP</li><li>added per-query attribute overrides feature (see SetOverride() API call); protocol 1.21</li><li>added signed 64bit attrs support (sql_attr_bigint directive)</li><li>improved HTML stripper to also skip PIs (<? … ?>, such as <?php … ?>)</li><li>improved excerpts speed (upto 50x faster on big documents)</li><li>fixed a short window of searchd inaccessibility on startup (started listen()ing too early before)</li><li>fixed .spa loading on systems where read() is 2GB capped</li><li>fixed infixes vs morphology issues</li><li>fixed backslash escaping, added backslash to EscapeString()</li><li>fixed handling of over-2GB dictionary files (.spi)</li></ul><h2>A.6. Version 0.9.8.1, 30 oct 2008</h2><ul><li>added configure script to libsphinxclient</li><li>changed proximity/quorum operator syntax to require whitespace after length</li><li>fixed potential head process crash on SIGPIPE during “maxed out” message</li><li>fixed handling of incomplete remote replies (caused over-degraded distributed results, in rare cases)</li><li>fixed sending of big remote requests (caused distributed requests to fail, in rare cases)</li><li>fixed FD_SET() overflow (caused searchd to crash on startup, in rare cases)</li><li>fixed MVA vs distributed indexes (caused loss of 1st MVA value in result set)</li><li>fixed tokenizing of exceptions terminated by specials (eg. “GPS AT&T” in extended mode)</li><li>fixed buffer overrun in stemmer on overlong tokens
occasionally emitted by proximity/quorum operator parser (caused crashes
on certain proximity/quorum queries)</li><li>fixed wordcount ranker (could be dropping hits)</li><li>fixed –merge feature (numerous different fixes, caused broken indexes)</li><li>fixed –merge-dst-range performance</li><li>fixed prefix/infix generation for stopwords</li><li>fixed ignore_chars vs specials</li><li>fixed misplaced F_SETLKW check (caused certain build types, eg. RPM build on FC8, to fail)</li><li>fixed dictionary-defined charsets support in spelldump, added \x-style wordchars support</li><li>fixed Java API to properly send long strings (over 64K; eg. long document bodies for excerpts)</li><li>fixed Python API to accept offset/limit of ‘long’ type</li><li>fixed default ID range (that filtered out all 64-bit values) in Java and Python APIs</li></ul><h2>A.7. Version 0.9.8, 14 jul 2008</h2><h3>Indexing</h3><ul><li>added support for 64-bit document and keyword IDs, –enable-id64 switch to configure</li><li>added support for floating point attributes</li><li>added support for bitfields in attributes, sql_attr_bool directive and bit-widths part in sql_attr_uint directive</li><li>added support for multi-valued attributes (MVA)</li><li>added metaphone preprocessor</li><li>added libstemmer library support, provides stemmers for a number of additional languages</li><li>added xmlpipe2 source type, that supports arbitrary fields and attributes</li><li>added word form dictionaries, wordforms directive (and spelldump utility)</li><li>added tokenizing exceptions, exceptions directive</li><li>added an option to fully remove element contents to HTML stripper, html_remove_elements directive</li><li>added HTML entities decoder (with full XHTML1 set support) to HTML stripper</li><li>added per-index HTML stripping settings, html_striphtml_index_attrs, and html_remove_elements directives</li><li>added IO load throttling, max_iops and max_iosize directives</li><li>added SQL load throttling, sql_ranged_throttle directive</li><li>added an option to index prefixes/infixes for given fields only, prefix_fields and infix_fields directives</li><li>added an option to ignore certain characters (instead of just treating them as whitespace), ignore_chars directive</li><li>added an option to increment word position on phrase boundary characters, phrase_boundary and phrase_boundary_step directives</li><li>added –merge-dst-range switch (and filters) to index merging feature (–merge switch)</li><li>added mysql_connect_flags directive (eg. to reduce indexing time MySQL network traffic and/or time)</li><li>improved ordinals sorting; now runs in fixed RAM</li><li>improved handling of documents with zero/NULL ids, now skipping them instead of aborting</li></ul><h3>Search daemon</h3><ul><li>added an option to unlink old index on succesful rotation, unlink_old directive</li><li>added an option to keep index files open at all times (fixes subtle races on rotation), preopen and preopen_indexes directives</li><li>added an option to profile searchd disk I/O, –iostats command-line option</li><li>added an option to rotate index seamlessly (fully avoids query stalls), seamless_rotate directive</li><li>added HTML stripping support to excerpts (uses per-index settings)</li><li>added ‘exact_phrase’, ‘single_passage’, ‘use_boundaries’, ‘weight_order ‘options to BuildExcerpts() API call</li><li>added distributed attribute updates propagation</li><li>added distributed retries on master node side</li><li>added log reopen on SIGUSR1</li><li>added –stop switch (sends SIGTERM to running instance)</li><li>added Windows service mode, and –servicename switch</li><li>added Windows –rotate support</li><li>improved log timestamping, now with millisecond precision</li></ul><h3>Querying</h3><ul><li>added extended engine V2 (faster, cleaner, better; SPH_MATCH_EXTENDED2 mode)</li><li>added ranking modes support (V2 engine only; SetRankingMode() API call)</li><li>added quorum searching support to query language (V2 engine only; example: “any three of all these words”/3)</li><li>added query escaping support to query language, and EscapeString() API call</li><li>added multi-field syntax support to query language (example: “@(field1,field2) something”), and @@relaxed field checks option</li><li>added optional star-syntax (‘word’) support in keywords, enable_star directive (for prefix/infix indexes only)</li><li>added full-scan support (query must be fully empty; can perform block-reject optimization)</li><li>added COUNT(DISTINCT(attr)) calculation support, SetGroupDistinct() API call</li><li>added group-by on MVA support, SetArrayResult() PHP API call</li><li>added per-index weights feature, SetIndexWeights() API call</li><li>added geodistance support, SetGeoAnchor() API call</li><li>added result set sorting by arbitrary expressions in run time (eg. “@weight+log(price)2.5″), SPH_SORT_EXPR mode</li><li>added result set sorting by @custom compile-time sorting function (see src/sphinxcustomsort.inl)</li><li>added result set sorting by @random value</li><li>added result set merging for indexes with different schemas</li><li>added query comments support (3rd arg to Query()/AddQuery() API calls, copied verbatim to query log)</li><li>added keyword extraction support, BuildKeywords() API call</li><li>added binding field weights by name, SetFieldWeights() API call</li><li>added optional limit on query time, SetMaxQueryTime() API call</li><li>added optional limit on found matches count (4rd arg to SetLimits() API call, so-called ‘cutoff’)</li></ul><h3>APIs and SphinxSE</h3><ul><li>added pure C API (libsphinxclient)</li><li>added Ruby API (thanks to Dmytro Shteflyuk)</li><li>added Java API</li><li>added SphinxSE support for MVAs (use varchar), floats (use float), 64bit docids (use bigint)</li><li>added SphinxSE options “floatrange”, “geoanchor”,
“fieldweights”, “indexweights”, “maxquerytime”, “comment”, “host” and
“port”; and support for “expr:CLAUSE”</li><li>improved SphinxSE max query size (using MySQL condition pushdown), upto 256K now</li></ul><h3>General</h3><ul><li>added scripting (shebang syntax) support to config files (example: #!/usr/bin/php in the first line)</li><li>added unified config handling and validation to all programs</li><li>added unified documentation</li><li>added .spec file for RPM builds</li><li>added automated testing suite</li><li>improved index locking, now fcntl()-based instead of buggy file-existence-based</li><li>fixed unaligned RAM accesses, now works on SPARC and ARM</li></ul><h3>Changes and fixes since 0.9.8-rc2</h3><ul><li>added pure C API (libsphinxclient)</li><li>added Ruby API</li><li>added SetConnectTimeout() PHP API call</li><li>added allowed type check to UpdateAttributes() handler (bug #174)</li><li>added defensive MVA checks on index preload (protection against broken indexes, bug #168)</li><li>added sphinx-min.conf sample file</li><li>added –without-iconv switch to configure</li><li>removed redundant -lz dependency in searchd</li><li>removed erroneous “xmlpipe2 deprecated” warning</li><li>fixed EINTR handling in piped read (bug #166)</li><li>fixup query time before logging and sending to client (bug #153)</li><li>fixed attribute updates vs full-scan early-reject index (bug #149)</li><li>fixed gcc warnings (bug #160)</li><li>fixed mysql connection attempt vs pgsql source type (bug #165)</li><li>fixed 32-bit wraparound when preloading over 2 GB files</li><li>fixed “out of memory” message vs over 2 GB allocs (bug #116)</li><li>fixed unaligned RAM access detection on ARM (where unaligned reads do not crash but produce wrong results)</li><li>fixed missing full scan results in some cases</li><li>fixed several bugs in –merge, –merge-dst-range</li><li>fixed @geodist vs MultiQuery and filters, @expr vs MultiQuery</li><li>fixed GetTokenEnd() vs 1-grams (was causing crash in excerpts)</li><li>fixed sql_query_range to handle empty strings in addition to NULL strings (Postgres specific)</li><li>fixed morphology=none vs infixes</li><li>fixed case sensitive attributes names in UpdateAttributes()</li><li>fixed ext2 ranking vs. stopwords (now using atompos from query parser)</li><li>fixed EscapeString() call</li><li>fixed escaped specials (now handled as whitespace if not in charset)</li><li>fixed schema minimizer (now handles type/size mismatches)</li><li>fixed word stats in extended2; stemmed form is now returned</li><li>fixed spelldump case folding vs dictionary-defined character sets</li><li>fixed Postgres BOOLEAN handling</li><li>fixed enforced “inline” docinfo on empty indexes (normally ok, but index merge was really confused)</li><li>fixed rare count(distinct) out-of-bounds issue (it occasionaly caused too high @distinct values)</li><li>fixed hangups on documents with id=DOCID_MAX in some cases</li><li>fixed rare crash in tokenizer (prefixed synonym vs. input stream eof)</li><li>fixed query parser vs “aaa (bbb ccc)|ddd” queries</li><li>fixed BuildExcerpts() request in Java API</li><li>fixed Postgres specific memory leak</li><li>fixed handling of overshort keywords (less than min_word_len)</li><li>fixed HTML stripper (now emits space after indexed attributes)</li><li>fixed 32-field case in query parser</li><li>fixed rare count(distinct) vs. querying multiple local indexes vs. reusable sorter issue</li><li>fixed sorting of negative floats in SPH_SORT_EXTENDED mode</li></ul><h2>A.8. Version 0.9.7, 02 apr 2007</h2><ul><li>added support for sql_str2ordinal_column</li><li>added support for upto 5 sort-by attrs (in extended sorting mode)</li><li>added support for separate groups sorting clause (in group-by mode)</li><li>added support for on-the-fly attribute updates (PRE-ALPHA; will change heavily; use for preliminary testing ONLY)</li><li>added support for zero/NULL attributes</li><li>added support for 0.9.7 features to SphinxSE</li><li>added support for n-grams (alpha, 1-grams only for now)</li><li>added support for warnings reported to client</li><li>added support for exclude-filters</li><li>added support for prefix and infix indexing (see max_prefix_len, max_infix_len)</li><li>added @*  syntax to reset current field to query language</li><li>added removal of duplicate entries in query index order</li><li>added PHP API workarounds for PHP signed/unsigned braindamage</li><li>added locks to avoid two concurrent indexers working on same index</li><li>added check for existing attributes vs. docinfo=none case</li><li>improved groupby code a lot (better precision, and upto 25x times faster in extreme cases)</li><li>improved error handling and reporting</li><li>improved handling of broken indexes (reports error instead of hanging/crashing)</li><li>improved mmap() limits for attributes and wordlists (now able to map over 4 GB on x64 and over 2 GB on x32 where possible)</li><li>improved malloc() pressure in head daemon (search time should not degrade with time any more)</li><li>improved test.php command line options</li><li>improved error reporting (distributed query, broken index etc issues now reported to client)</li><li>changed default network packet size to be 8M, added extra checks</li><li>fixed division by zero in BM25 on 1-document collections (in extended matching mode)</li><li>fixed .spl files getting unlinked</li><li>fixed crash in schema compatibility test</li><li>fixed UTF-8 Russian stemmer</li><li>fixed requested matches count when querying distributed agents</li><li>fixed signed vs. unsigned issues everywhere (ranged queries, CLI search output, and obtaining docid)</li><li>fixed potential crashes vs. negative query offsets</li><li>fixed 0-match docs vs. extended mode vs. stats</li><li>fixed group/timestamp filters being ignored if querying from older clients</li><li>fixed docs to mention pgsql source type</li><li>fixed issues with explicit ‘&’ in extended matching mode</li><li>fixed wrong assertion in SBCS encoder</li><li>fixed crashes with no-attribute indexes after rotate</li></ul><h2>A.9. Version 0.9.7-rc2, 15 dec 2006</h2><ul><li>added support for extended matching mode (query language)</li><li>added support for extended sorting mode (sorting clauses)</li><li>added support for SBCS excerpts</li><li>added mmap()ing for attributes and wordlist (improves search time, speeds up fork() greatly)</li><li>fixed attribute name handling to be case insensitive</li><li>fixed default compiler options to simplify post-mortem debugging (added -g, removed -fomit-frame-pointer)</li><li>fixed rare memory leak</li><li>fixed “hello hello” queries in “match phrase” mode</li><li>fixed issue with excerpts, texts and overlong queries</li><li>fixed logging multiple index name (no longer tokenized)</li><li>fixed trailing stopword not flushed from tokenizer</li><li>fixed boolean evaluation</li><li>fixed pidfile being wrongly unlink()ed on bind() failure</li><li>fixed --with-mysql-includes/libs (they conflicted with well-known paths)</li><li>fixes for 64-bit platforms</li></ul><h2>A.10. Version 0.9.7-rc1, 26 oct 2006</h2><ul><li>added alpha index merging code</li><li>added an option to decrease max_matches per-query</li><li>added an option to specify IP address for searchd to listen on</li><li>added support for unlimited amount of configured sources and indexes</li><li>added support for group-by queries</li><li>added support for /2 range modifier in charset_table</li><li>added support for arbitrary amount of document attributes</li><li>added logging filter count and index name</li><li>added --with-debug option to configure to compile in debug mode</li><li>added -DNDEBUG when compiling in default mode</li><li>improved search time (added doclist size hints, in-memory wordlist cache, and used VLB coding everywhere)</li><li>improved (refactored) SQL driver code (adding new drivers should be very easy now)</li><li>improved exceprts generation</li><li>fixed issue with empty sources and ranged queries</li><li>fixed querying purely remote distributed indexes</li><li>fixed suffix length check in English stemmer in some cases</li><li>fixed UTF-8 decoder for codes over U+20000 (for CJK)</li><li>fixed UTF-8 encoder for 3-byte sequences (for CJK)</li><li>fixed overshort (less than min_word_len) words prepended to next field</li><li>fixed source connection order (indexer does not connect to all sources at once now)</li><li>fixed line numbering in config parser</li><li>fixed some issues with index rotation</li></ul><h2>A.11. Version 0.9.6, 24 jul 2006</h2><ul><li>added support for empty indexes</li><li>added support for multiple sql_query_pre/post/post_index</li><li>fixed timestamp ranges filter in “match any” mode</li><li>fixed configure issues with –without-mysql and –with-pgsql options</li><li>fixed building on Solaris 9</li></ul><h2>A.12. Version 0.9.6-rc1, 26 jun 2006</h2><ul><li>added boolean queries support (experimental, beta version)</li><li>added simple file-based query cache (experimental, beta version)</li><li>added storage engine for MySQL 5.0 and 5.1 (experimental, beta version)</li><li>added GNU style configure script</li><li>added new searchd protocol (all binary, and should be backwards compatible)</li><li>added distributed searching support to searchd</li><li>added PostgreSQL driver</li><li>added excerpts generation</li><li>added min_word_len option to index</li><li>added max_matches option to searchd, removed hardcoded MAX_MATCHES limit</li><li>added initial documentation, and a working example.sql</li><li>added support for multiple sources per index</li><li>added soundex support</li><li>added group ID ranges support</li><li>added --stdin command-line option to search utility</li><li>added --noprogress option to indexer</li><li>added --index option to search</li><li>fixed UTF-8 decoder (3-byte codepoints did not work)</li><li>fixed PHP API to handle big result sets faster</li><li>fixed config parser to handle empty values properly</li><li>fixed redundant time(NULL) calls in time-segments mode</li></ul><p>
</p>

Xunsearch 安装使用

<p>官网网址<span style="">:http://www.xunsearch.com</span></p><pre style="max-width:100%;overflow-x:auto;">官方安装手册地址:http://www.xunsearch.com/doc/php/guide/start.installation
wget http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2
tar -xjf xunsearch-full-latest.tar.bz2
cd xunsearch-full-1.4.11/
sh setup.sh##根据提示安装

以下为安装成功界面

+=================================================+
| Installation completed successfully, Thanks you |

安装成功,感谢选择和使用 xunsearch
说明和注意事项:
1. 开启/重新开启 xunsearch 服务程序,命令如下:
/usr/local/xunsearch/bin/xs-ctl.sh restart
强烈建议将此命令写入服务器开机脚本中
2. 所有的索引数据将被保存在下面这个目录中:
/usr/local/xunsearch/data
如需要转移到其它目录,请使用软链接。
3. 您现在就可以在我们提供的开发包(SDK)基础上
开发您自己的搜索了。
目前只支持 PHP 语言,参见下面文档:
/usr/local/xunsearch/sdk/php/README

+=================================================+

</pre><h3>启动
</h3><pre style="max-width:100%;overflow-x:auto;"><span class="hljs-comment">##启动</span>
/usr/<span class="hljs-built_in">local</span>/xunsearch/bin/xs-ctl.sh start
INFO: starting server[xs-indexd] ... (BIND:127.0.0.1:8383)
INFO: starting server[xs-searchd] ... (BIND:127.0.0.1:8384)
</pre><h3>运行条件
</h3><pre style="max-width:100%;overflow-x:auto;"><span class="hljs-comment">##检测 PHP-SDK 的运行条件</span>
/usr/<span class="hljs-built_in">local</span>/xunsearch/sdk/php/util/RequiredCheck.php

Xunsearch PHP-SDK 运行需求检查

检查内容

本程序用于确认您的服务器配置是否能满足运行 Xunsearch PHP-SDK 的要求。
它将检查服务器所运行的 PHP 版本,查看是否安装了合适的PHP扩展模块,以及
确认 php.ini 文件是否正确设置。

项目结果用于备注
PHP 版本7.0.6XS(core)PHP 5.2.0 或更高版本是必须的。
SPL 扩展OKXS(core)SPL 扩展用于自动加载和对象戏法
PCRE 扩展OKXSDocument, XSSearch用于字符串切割、判断
编码转换mbstringXSDocument, XSSearch用于支持非 UTF-8 字符集
缓存模块WARNINGXS用于缓存项目配置文件的解析结果
JSON 扩展OKutil.Quest, util.Indexer用于读取或输出 JSON 格式的数据
XML 扩展OKutil.Indexer用于读取导入 XML 格式的数据
MySQL 扩展mysqliutil.Indexer用于读取导入 MySQL 的数据库
SQLite 扩sqlite3util.Indexer用于读取导入 SQLite 的数据库

检查结果

共计 8 项通过,1 项警告,0 项错误。

您的服务器配置符合 Xunsearch/PHP-SDK 的最低要求。
如果您需要使用特定的功能,请关注上述的 WARNING 项。
</pre><h3>配置
</h3><pre style="max-width:100%;overflow-x:auto;">##配置 以BLOG为例
cd /usr/local/xunsearch/sdk/php/app
cp demo.ini blog.ini

配置文件生成工具http://www.xunsearch.com/tools/iniconfig

vim blog.ini

project.name = blog
project.default_charset = utf-8
server.index = 8383
server.search = 8384

[id]
type = id

[subject]

type = title

[message]
type = body

[chrono]

type = numeric

[title]
type = title
[c_id]
type=numeric
[is_top]
type=numeric
[password]
type=string
~

</pre><pre style="max-width:100%;overflow-x:auto;">##导入数据源
/usr/local/xunsearch/sdk/php/util/Indexer.php --rebuild --source=mysql://用户:密码@localhost/库名 --sql="SELECT id,title,c_id,message FROM thinkask_blog where status=1" --project=blog
</pre><pre style="max-width:100%;overflow-x:auto;">##xunSearch 有接口导入,具体查看文档http://www.xunsearch.com/doc/php/guide/index.add

定时导入

crontab -e  
0 3 * * *    /usr/local/shell/xunSearch.sh  
crontab -l  


#xunSearch.sh:
#!/bin/bash  
/usr/local/xunsearch/sdk/php/util/Indexer.php --rebuild --source=mysql://用户:密码@localhost/库名 --sql="SELECT id,title,c_id,message FROM thinkask_blog where status=1" --project=blog &gt; /dev/null 2&gt;&amp;1  </code></pre><h3>PHP封装使用</h3><pre style="max-width:100%;overflow-x:auto;"><code class="javascript hljs" codemark="1">##PHP封装使用

/**

  • [xunSearch xunSearch处理]
  • @Author Jerry
  • @DateTime 2018-05-30T11:34:04+0800
  • @Example eg:
  • @return [type] [description]
    */

function xunSearch($keyword,$index='blog'){

if(!$keyword) return;
require_once '/usr/local/xunsearch/sdk/php/lib/XS.php';
$xs = new \XS($index);    // demo  为项目名称,配置文件是:$sdk/app/demo.in i
// $index = $xs-&gt;index;   //  获取索引对象
$search = $xs-&gt;search;   //  获取搜索对象
$search-&gt;setLimit(20); 
$docs = $search-&gt;setQuery()-&gt;search($keyword);
$info = [];
foreach ($docs as  $doc) {
        $info[$doc-&gt;id]['title'] = $search-&gt;highlight($doc-&gt;title);//高亮处理标题 
        $info[$doc-&gt;id]['href'] = '/b_d@'.encode($doc-&gt;c_id).'@'.encode($doc-&gt;id).'.html';//高亮处理标题 
        $info[$doc-&gt;id]['message'] = $search-&gt;highlight(strip_tags(htmlspecialchars_decode($doc-&gt;message)));//高亮处理标题 
   }

return $info;
}
</pre><p>
</p>

php+中文分词scws+sphinx+mysql全文搜索

<h3>sphinx 安装</h3><p>请参照<a href="https://jerryblog.cn/b_d@MNjmMY6f918e5@NNzmkY6f918e5.html" target="_blank" style="background-color: rgb(255, 255, 255);">https://jerryblog.cn/b_d@MNjmMY6f918e5@NNzmkY6f918e5.html</a><br></p><p>安装libsphinxclient</p><pre><code class="hljs bash" codemark="1"><span class="hljs-built_in">cd</span> coreseek-4.1-beta/csft-4.1/api/libsphinxclient
sh buildconf.sh
./configure --prefix=/usr/<span class="hljs-built_in">local</span>/sphinxclient
make && make install</code></pre><h3>安装php拓展</h3><pre><code class="hljs ruby" codemark="1"><span class="hljs-comment">##我WGET好像有问题,我是用WINDOW下载了,传到服务器的。</span>
<span class="hljs-comment">##此扩展是PHP7的包,其它包请百度查找</span>
wget <span class="hljs-symbol">http:</span>/<span class="hljs-regexp">/git.php.net/</span><span class="hljs-string">?p</span>=pecl/search_engine/sphinx.git;a=snapshot;h=<span class="hljs-number">9</span>a3d08c67af0cad216aa0d38d39be71362667738;sf=tgz
<span class="hljs-comment"># tar zxvf sphinx-9a3d08c.tar.gz</span>
<span class="hljs-comment"># cd cd sphinx-9a3d08c</span>
<span class="hljs-comment">#(此处为当前使用的PHP目录)</span>
/www/wdlinux/apache_php/bin/phpize
./configure --with-php-config=<span class="hljs-regexp">/www/wdlinux</span><span class="hljs-regexp">/apache_php/bin</span><span class="hljs-regexp">/php-config --with-sphinx=/usr</span><span class="hljs-regexp">/local/sphinxclient</span>
make && make install
安装后,在/www/wdlinux/apache_php-<span class="hljs-number">7.0</span>.<span class="hljs-number">6</span>/lib/php/extensions/no-debug-non-zts-<span class="hljs-number">20151012</span>/目录下生成sphinx.so扩展 PHP目录不一样,生成文件目录也不一样。</code></pre><h3>在php.ini中加入</h3><pre><code class="hljs ini" codemark="1"><span class="hljs-section">[sphinx]</span>
<span class="hljs-attr">extension_dir</span>=/www/wdlinux/apache_php-<span class="hljs-number">7.0</span>.<span class="hljs-number">6</span>/lib/php/extensions/<span class="hljs-literal">no</span>-debug-non-zts-<span class="hljs-number">20151012</span>/
<span class="hljs-attr">extension</span>=sphinx.so
<span class="hljs-comment">##需要重启WEB服务</span></code></pre><p>查看phpinfo();</p><p><img src="https://imgs.jerryblog.cn/2018051815266367056257.png" alt="QQ截图20180518174401"></p><p>到此完成安装</p><p>以下采用"Main + Delta" ("主索引"+"增量索引")的索引策略,使用Sphinx自带的一元分词。</p><p>##测试数据</p><h3>我们先要明白几个概念:</h3><ul><li>source:数据源,数据是从什么地方来的。<br></li><li>index:索引,当有数据源之后,从数据源处构建索引。索引实际上就是相当于一个字典检索。有了整本字典内容以后,才会有字典检索。<br></li><li>searchd:提供搜索查询服务。它一般是以deamon的形式运行在后台的。<br></li><li>indexer:构建索引的服务。当要重新构建索引的时候,就是调用indexer这个命令。<br></li><li>attr:属性,属性是存在索引中的,它不进行全文索引,但是可以用于过滤和排序。</li></ul><div><br></div><p>配置文件可以查看:<a href="https://jerryblog.cn/b_d@MNjmMY6f918e5@ONDmcY6f918e5.html" target="_blank" style="">https://jerryblog.cn/b_d@MNjmMY6f918e5@ONDmcY6f918e5.html</a></p><p><br></p><pre style="max-width: 100%;"><code class="bash hljs" codemark="1">#<span style="font-size: inherit;">#重建索引:&nbsp;&nbsp;</span></code><code class="bash hljs" codemark="1">/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf --all

报错

FATAL: out of memory (unable to allocate 235667448 bytes)
该提示表示当前环境下,可以使用的内存不足够;可能是因为其他程序占用内存较多导致可用内存太少;也有可能是因为配置中mem_limit设置太大。
最快的解决方法
修改sphinx.conf 文件,将mem_limit值改小,

启动sphinx

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

查看进程

ps -ef |grep searchd

root 18294 1 0 15:16 ? 00:00:00 /usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/sphinx.conf
root 18295 18294 0 15:16 ? 00:00:00 /usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/sphinx.conf
root 18304 17955 0 15:17 pts/0 00:00:00 grep searchd

停止Searchd:

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

查看Searchd状态:

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

</code><br></pre><h3>索引更新及使用说明</h3><p>"增量索引"每N分钟更新一次.通常在每天晚上低负载的时进行一次索引合并,同时重新建立"增量索引"。当然"主索引"数据不多的话,也可以直接重新建立"主索引"。<br>API搜索的时,同时使用"主索引"和"增量索引",这样可以获得准实时的搜索数据.本文的Sphinx配置将"主索引"和"增量索引"放到分布式索引master中,因此只需查询分布式索引"master"即可获得全部匹配数据(包括最新数据)。<br>索引的更新与合并的操作可以放到cron job完成:</p><p><br></p><pre style="max-width: 100%;"><code class="bash hljs" codemark="1">crontab <span class="hljs-_">-e</span>
/1 * /usr/<span class="hljs-built_in">local</span>/sphinx/shell/delta_index_update.sh
0 3 * /usr/<span class="hljs-built_in">local</span>/sphinx/shell/merge_daily_index.sh
crontab <span class="hljs-_">-l</span> </code></pre><pre style="max-width: 100%;"><code class="bash hljs" codemark="1"><span class="hljs-comment">#delta_index_update.sh:</span>
<span class="hljs-meta">#!/bin/bash </span>
/usr/<span class="hljs-built_in">local</span>/sphinx/bin/indexer -c /usr/<span class="hljs-built_in">local</span>/sphinx/etc/sphinx.conf --rotate items_delta > /dev/null 2>&1 </code></pre><pre style="max-width: 100%;"><code class="bash hljs" codemark="1"><span class="hljs-comment">#merge_daily_index.sh:</span>
<span class="hljs-meta">#!/bin/bash </span>
indexer=&lt;span class=&quot;hljs-built_in&quot;&gt;which&lt;/span&gt; indexer
mysql=&lt;span class=&quot;hljs-built_in&quot;&gt;which&lt;/span&gt; mysql

QUERY=<span class="hljs-string">"use sphinx_items;select max_doc_id from sph_counter where counter_id = 2 limit 1;"</span>
index_counter=$(&lt;span class=&quot;hljs-variable&quot;&gt;$mysql</span> -h192.168.1.198 -uroot -p123456 <span class="hljs-_">-s</span>N <span class="hljs-_">-e</span> <span class="hljs-string">"<span class="hljs-variable">$QUERY</span>"</span>)

<span class="hljs-comment">#merge "main + delta" indexes </span>
<span class="hljs-variable">$indexer</span> -c /usr/<span class="hljs-built_in">local</span>/sphinx/etc/sphinx.conf --rotate --merge items items_delta --merge-dst-range deleted 0 0 >> /usr/<span class="hljs-built_in">local</span>/sphinx/var/index_merge.log 2>&1

<span class="hljs-keyword">if</span> [ <span class="hljs-string">"$?"</span> <span class="hljs-_">-eq</span> 0 ]; <span class="hljs-keyword">then</span>

&lt;span class=&quot;hljs-comment&quot;&gt;##update sphinx counter  &lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; [ ! -z &lt;span class=&quot;hljs-variable&quot;&gt;$index_counter&lt;/span&gt; ]; &lt;span class=&quot;hljs-keyword&quot;&gt;then&lt;/span&gt;  
    &lt;span class=&quot;hljs-variable&quot;&gt;$mysql&lt;/span&gt; -h192.168.1.198 -uroot -p123456 -Dsphinx_items &lt;span class=&quot;hljs-_&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;REPLACE INTO sph_counter VALUES (1, '&lt;span class=&quot;hljs-variable&quot;&gt;$index_counter&lt;/span&gt;')&quot;&lt;/span&gt;  
&lt;span class=&quot;hljs-keyword&quot;&gt;fi&lt;/span&gt;  
&lt;span class=&quot;hljs-comment&quot;&gt;##rebuild delta index to avoid confusion with main index  &lt;/span&gt;
&lt;span class=&quot;hljs-variable&quot;&gt;$indexer&lt;/span&gt; -c /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/sphinx/etc/sphinx.conf --rotate items_delta &gt;&gt; /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/sphinx/var/rebuild_deltaindex.log 2&gt;&amp;1  

<span class="hljs-keyword">fi</span> </code></pre><h3><strong>php中文分词scws安装:注意扩展的版本和php的版本</strong></h3><pre style="max-width: 100%;"><code class="bash hljs" codemark="1">wget -c http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2
tar jxvf scws-1.2.3.tar.bz2
<span class="hljs-built_in">cd</span> scws-1.2.3
./configure --prefix=/usr/<span class="hljs-built_in">local</span>/scws
make && make install </code></pre><pre style="max-width: 100%;"><code class="javascript hljs" codemark="1">##php.ini最后加入 ,记得重启WEB服务
[scws]
extension_dir=<span class="hljs-regexp">/www/</span>wdlinux/apache_php<span class="hljs-number">-7.0</span><span class="hljs-number">.6</span>/lib/php/extensions/no-debug-non-zts<span class="hljs-number">-20151012</span>/
extension = scws.so
scws.default.charset = utf8
scws.default.fpath = <span class="hljs-regexp">/usr/</span>local/scws/etc

    &lt;/code&gt;&lt;/pre&gt;&lt;pre style=&quot;max-width: 100%;&quot;&gt;&lt;code class=&quot;php hljs&quot; codemark=&quot;1&quot;&gt;##关于sphinx其它API方法可以访问http://www.php.net/manual/zh/book.sphinx.php

php分词方法

/**

  • [scwsWord scws分词方法 ]
  • @Author Jerry
  • @DateTime 2018-05-22T17:19:57+0800
  • @Example eg:
  • @param [type] $word [ string 字符关键字]
  • @return [type] [description]
    */

function scwsWord($word,$detail=false){

 //实例化分词插件核心类
 $so = scws_new();
 //设置分词时所用编码
 $so-&gt;set_charset('utf-8');
 //设置分词所用词典(此处使用utf8的词典)
 $so-&gt;set_dict('/usr/local/scws/etc/dict.utf8.xdb');
 //设置分词所用规则
 $so-&gt;set_rule('/usr/local/scws/etc/rules.utf8.ini ');
 //分词前去掉标点符号
 $so-&gt;set_ignore(true);
 //是否复式分割,如“中国人”返回“中国+人+中国人”三个词。
 $so-&gt;set_multi(true);
 //设定将文字自动以二字分词法聚合
 $so-&gt;set_duality(true);
 //要进行分词的语句
 $so-&gt;send_text($word);
 //获取分词结果,如果提取高频词用get_tops方法
 $wordArr = [];
 $word = [];
 while ($tmp = $so-&gt;get_result())
 {
     $wordArr[] = $tmp;
     foreach ($tmp as  $v) {
        $word[] = $v['word'];
     }
 }
 $so-&gt;close();
 $words = $detail?$wordArr:$word;
 return $words;

}

/**

  • [sphinx 分词方法]
  • @Author Jerry
  • @DateTime 2018-05-24T11:53:53+0800
  • @Example eg:
  • @param [type] $word [搜索的词]
  • @param [type] $index [SPHINX索引名]
  • @param string $ip [服务的IP]
  • @param integer $port [服务的端口]
  • @return [type] [description]
    */

function sphinx($word,$index='index_blog',$ip='127.0.0.1',$port=9312,$detail=false){
$sc = new \SphinxClient();
$sc->SetServer('127.0.0.1',9312);
//SPH_MATCH_ALL, 匹配所有查询词(默认模式); SPH_MATCH_ANY, 匹配查询词中的任意一个; SPH_MATCH_EXTENDED2, 支持特殊运算符查询
// $sc->SetMatchMode(SPH_MATCH_ALL);
$sc->SetMatchMode(SPH_MATCH_EXTENDED);
$sc->SetArrayResult(TRUE);
$re = $sc->Query($word,$index);
if($detail) return $re;
$ids = [0];##防止SQL IN方法的报错
if(count($re['matches'])>1){

foreach ($re['matches'] as $key =&gt; $v) {
    $ids[] = $v['id'];
}

}
return implode(",", $ids);
}
/**

  • [sphinxScwsWord 组合使用]
  • @Author Jerry
  • @DateTime 2018-05-28T16:08:33+0800
  • @Example eg:
  • @return [type] [description]
    */

function sphinxScwsWord($keyword,$sort='@id desc',$searchFromField='@title',$field='c_id,id,title',$index='*',$ip='127.0.0.1',$MatchMode = SPH_MATCH_FULLSCAN,$port=9312){

 //设定搜索词  
 $words_array =  scwsWord($keyword);  
 $words = &quot;&quot;;  
 foreach($words_array as $v)  
 {  
 $words = $words.'|('.$v.')';  
 }  
 $words = trim($words,'|');  
 $sc = new \SphinxClient();  
 $sc-&gt;SetServer($ip,$port);   
    // SPH_MATCH_ALL匹配所有查询词(默认模式)
    // SPH_MATCH_ANY匹配查询词中的任意一个
    // SPH_MATCH_PHRASE将整个查询看作一个词组,要求按顺序完整匹配
    // SPH_MATCH_BOOLEAN将查询看作一个布尔表达式
    // SPH_MATCH_EXTENDED将查询看作一个Sphinx内部查询语言的表达式
    // SPH_MATCH_FULLSCAN使用完全扫描,忽略查询词汇
    // SPH_MATCH_EXTENDED2类似 SPH_MATCH_EXTENDED ,并支持评分和权重.
 $sc-&gt;SetMatchMode(SPH_MATCH_ANY);  //SPH_MATCH_EXTENDED
 $sc-&gt;SetArrayResult(TRUE);  
 $sc-&gt;SetSortMode(SPH_SORT_EXTENDED, $sort);##排序
 $sc-&gt;SetSelect ( $field); ##搜索的字段 
 $res = $sc-&gt;Query($searchFromField?$searchFromField:''.$words,$index);  
show($res);
show($words);
show($searchFromField);
show($words_array);
if(count($res['matches'])&gt;1){
    $data = [];
    foreach ($res['matches'] as $k =&gt; $v) {
        ##组合数据
        $data[$k]['href'] = '/b_d@'.encode($v['attrs']['c_id']).'@'.$v['id'].'.html';
        $data[$k]['title'] = $v['attrs']['title'];
        ##分词色
        foreach ($words_array as $v) {
          $data[$k]['title'] = str_replace($v, &quot;&lt;span style=&quot;color:red&quot;&gt;{$v}&lt;/span&gt;&quot;, $data[$k]['title']); 
        } 
        
    }
    return $data;
}else{
    return [];
}

 

}</code></pre><p><br></p>

nohup和&后台运行

<pre style="max-width:100%;overflow-x:auto;"><span class="hljs-comment"> 留做备用,有时候忘记用法

nohup ./BookStack >>/dev/null 2>&1 &</span>

[1] 2405
</pre><p>
</p>

gcc 4.4.7 升级到 4.8.2

<div><font color="#ff0000">注意,GCC升级前,请先备份重要数据,先备份,先备份,先备份,  GCC 编译时间较长,请耐心等待</font>
</div><pre style="max-width:100%;overflow-x:auto;">下载GCC文件
wget http://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
tar -jxvf gcc-4.8.2.tar.bz2

下载供编译需求的依赖项

这个脚本文件会帮我们下载、配置、安装依赖库,可以节约我们大量的时间和精力

./contrib/download_prerequisites
mkdir gcc-build-4.8.2
cd gcc-build-4.8.2
../configure -enable-checking=release -enable-languages=c,c++ -disable-multilib
yum groupinstall "Development Tools"
make && make intsall

reboot//请先重启,切记!

gcc -v
gcc version 4.8.2 (GCC)

g++ -v
gcc version 4.8.2 (GCC)
[库升级]
先检查库文件
strings /usr/lib64/libstdc++.so.6 | grep GLIBC
以为gcc升级成功了,就可以直接编程c++11的程序了。还需要进行库升级。源码编译升级安装了gcc后,编译程序或运行其它程序时,有时会出现类似:
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
的问题。这是因为升级gcc时,生成的动态库没有替换老版本gcc的动态库导致的,将gcc最新版本的动态库替换系统中老版本的动态库即可解决。
复制库文件到指定目录,并修改软连接
cp /www/gcc-4.8.2/gcc-build-4.8.2/stage1-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.18 /usr/lib64/
cd /usr/lib64/
rm libstdc++.so.6
ln -s libstdc++.so.6.0.18 libstdc++.so.6

再次检查库文件

strings /usr/lib64/libstdc++.so.6 | grep GLIBC</pre><p>
</p>

Sphinx(斯芬克司) 安装

<p>Sphinx是由俄罗斯人Andrew Aksyonoff开发的一个全文检索引擎。意图为其他应用提供高速、低空间占用、高结果
相关度的全文搜索功能。</p><p>Sphinx可以非常容易的与SQL数据库和脚本语言集成。当前系统内置MySQL和PostgreSQL
数据库数据源的支持,也支持从标准输入读取特定格式 的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS
的原生支持)</p><h3>Sphinx的特性</h3><ul><li>高速的建立索引(在当代CPU上,峰值性能可达到10 MB/秒);</li><li>高性能的搜索(在2 – 4GB 的文本数据上,平均每次检索响应时间小于0.1秒);</li><li>可处理海量数据(目前已知可以处理超过100 GB的文本数据, 在单一CPU的系统上可 处理100 M 文档);</li><li>提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;</li><li>支持分布式搜索;</li><li>支持短语搜索</li><li>提供文档摘要生成</li><li>可作为MySQL的存储引擎提供搜索服务;</li><li>支持布尔、短语、词语相似度等多种检索模式;</li><li>文档支持多个全文检索字段(最大不超过32个);</li><li>文档支持多个额外的属性信息(例如:分组信息,时间戳等);</li><li>支持断词;</li></ul><h3>安装
</h3><p>Sphinx在mysql上的应用有两种方式:</p><p>
①、采用API调用,如使用PHP、java等的API函数或方法查询。优点是可不必对mysql重新编译,服务端进程“低耦合”,且程序可灵活、方便的调用;</p><p>
缺点是如已有搜索程序的条件下,需修改部分程序。推荐程序员使用<font color="#ff0000">(下面安装是这种)</font>。</p><p>
②、使用插件方式(sphinxSE)把sphinx编译成一个mysql插件并使用特定的sql语句进行检索。其特点是,在sql端方便组合,且能直接返回数据给客户端</p><p>
不必二次查询(注),在程序上仅需要修改对应的sql,但这对使用框架开发的程序很不方便,比如使用了ORM。另外还需要对mysql进行重新编译,且需要mysql-5.1以上版本</p><p>
支持插件存储。系统管理员可使用这种方式</p><p>
</p><pre style="max-width:100%;overflow-x:auto;">#手册网址http://sphinxsearch.com/docs/current.html#compiling-source-linux

如果要使用sphinxSE插件存储请使用mysql-5.1以上版本

mysql -V

我的SQL版本

mysql Ver 14.14 Distrib 5.6.30, for Linux (x86_64) using EditLine wrapper

编译软件:gcc gcc-c++ autoconf automake

Sphinx :Sphinx 2.3.2 </pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">#下载 Sphinx 包

wget http://sphinxsearch.com/files/sphinx-2.3.2-beta.tar.gz

解压包

tar zvxf sphinx-2.3.2-beta.tar.gz

cd sphinx-2.3.2-beta
./configure --prefix=/usr/local/sphinx --with-mysql
You can now run 'make install' to build and install Sphinx binaries.
On a multi-core machine, try 'make -j4 install' to speed up the build.
Updates, articles, help forum, and commercial support, consulting, training,
and development services are available at http://sphinxsearch.com/
Thank you for choosing Sphinx!

make && make install

报错

cc1plus: error: unrecognized command line option "-std=c++11"
make[2]: * [sphinx.o] Error 1
make[2]: Leaving directory `/www/sphinx-2.3.2-beta/src'
make[1]: * [all] Error 2
make[1]: Leaving directory `/www/sphinx-2.3.2-beta/src'
make: * [all-recursive] Error 1

"-std=c++11"出现这个编译错误的原因在g++ gcc 版本不够高

gcc -v
gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)

</pre><h3>#升级GCC
</h3><p>查看  www.jerryblog.cn/b_d@MNwm6f918eY6f918e5@ONDmAY6f918e5.html</p><p>
</p><pre style="max-width:100%;overflow-x:auto;">#继续安装Sphinx
make &&make install
安装完成后,在 /usr/local/sphinx目录下会有4个目录
ls /usr/local/sphinx/
bin etc share var
配置sphinx的配置文件
</pre>
<p>
</p>

svn

Linux使用svn时报错Can't convert string from的解决方法

<pre class="brush:cpp;toolbar:false">在linux中,svn co 、 svn up或者svnc cleanup时,如果有中文文件名的文件报下面的错:
  svn: Can’t convert string from ‘UTF-8’ to native encoding:
  svn: src/main/webapp/resources/js/My97DatePicker/?229?188?128?229?143?145?229?140?133
  第一行的大致意思是:不能将字符串从UTF-8编码转换到本地,主要是因为SVN客户端需要utf8来支持中文。
  第二行报销的文件路径,查看其路径下的文件,肯定是有中文命名的文件。因此需要查看下系统编码文件:
.UTF-8
  LC_CTYPE=“C”
  LC_NUMERIC=“C”
  LC_TIME=“C”
  LC_COLLATE=“C”
  LC_MONETARY=“C”
  LC_MESSAGES=“C”
  LC_PAPER=“C”
  LC_NAME=“C”
  LC_ADDRESS=“C”
  LC_TELEPHONE=“C”
  LC_MEASUREMENT=“C”
  LC_IDENTIFICATION=“C”
  LC_ALL=C
  只需要修改bash_profile ~/.bashrc文件就可以,添加下面几行:
  export LC_ALL=en_US.UTF-8
  export.UTF-8
  export LANGUAGE=en_US.UTF-8
  然后source一下:
  ~/.bashrc

  这时候,再重新进行SVN操作就不会再报svn: Can‘t convert string from ’UTF-8‘ to native encoding:的错误了。
  另一种解决办法
  解决办法很简单,正确设置当前系统的 locale:
  export LC_CTYPE=“zh_CN.UTF-8″
  然后重新 checkout 即可。
  注意,根据你的系统字符集设置变量,如果 zh_CN.UTF-8 不行,有可能要改成 GB2312:
  export LC_CTYPE=”zh_CN.GB2312″
  另外,有的变量名不同,用的是:
  export LANG=“zh_CN.UTF-8″
  上面就是Linux svn报错can‘t convert string from的解决方法介绍了,有两种方法可以解决,第二种方法相对简单但不一定能够解决svn报错问题。</pre><p><br/></p>

svn :svn: Commit failed (details follow):

今天在家里面提交SVN代码时遇到SVN报错,记录下

svn: Commit failed (details follow):
svn: E155010: Commit failed (details follow):
file is scheduled for addition, but is missing

> 产生问题的原因是有一个文件已经加入到版本库中,但是后来在文件系统中又移除了这个文件,所以不能够提交。
后面网上找了个解决办法

svn revert  /文件路径

> 但又有个新总是,那就是移除的是一个文件夹。。里面有很多文件。。。。。

#抛出错
svn Can't revert without reverting children 

##使用
svn rm --keep-local /文件路径  
再执行
svn commit -m '';

Linux中svn提交文件后自动同步更新到网站目录

<p>情景:在测试环境下,开发部提出希望提交到SVN的代码能自动同步到WEB站点目录下,解决每次都要传双份这一问题,尤其是频繁更新后的繁琐,浪费了大量时间。</p><p>思路:通过搜索,查到svn的hooks目录的触发功能,该目录下有许多模板,其中一个是post-commit.tmpl,意为“提交后执行”,通过这个功能我们可以将提交代码后要做的事写到里面来执行。</p><p>步骤:</p><p>1. 首先导出一份svn的文件到网站目录</p><p># svn co file:///data/svn/php/ /data/wwwroot/</p><p>2. 修改“提交后执行文件”post-commit.tmpl</p><p># cd /data/svn/php/hooks</p><p># mv post-commit.tmpl  post-commit</p><p># chmod +x post-commit</p><p># cat post-commit</p><pre style="max-width: 100%;"><span class="hljs-meta">#!/bin/sh
SVN=/usr/bin/svn
WEB=/网站目录 LOG_PATH=/日志目录
echo "------------Start Commit -----------" >> $LOG_PATH
echo "Time:"date '+%Y-%m-%d %T'>>$LOG_PATH export LANG='zh_CN.UTF-8' #防止乱码
for DIR in svnlook dirs-changed /data/svn/php/SVN项目目录
do $SVN update $WEB/$DIR done

</span></pre><p>
</p><p>
</p>

svn 常用命令


svn add 命令 递归目录下所有文件
svn add . --no-ignore --force




清除当前目录下所有.svn目录
find . -type d -name ".svn"|xargs rm -rf</code></pre><p><br></p>


 

SVN 安装,配置,关闭

<p>如何新加一个仓库</p><p>===================================</p>
<p>1,先把之前的SVN关闭  ps -ew |grep svn 查出PID</p><p>2,killall svnserve</p><p>mkdir newpro</p><p>svnadmin create newpro</p><p>其它配置,参照下面的配置</p><font color="#ff0000"><span>结束所有的svn服务killall svnserve</span><span>
开启SVN svnserve -d -r /项目目录</span></font><p>====================================</p>



<pre style="max-width:100%;overflow-x:auto;">yum install subversion #安装SVN服务
rpm -ql subversion#查看安装位置
mkdir -p /var/svn/pro#创建svn版本库目录
svnadmin create /var/svn/pro#创建版本库

创建完成后会出现以下文件

conf db format hooks locks README.txt
</pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">进入conf目录(该svn版本库配置文件)
authz文件是权限控制文件
passwd是帐号密码文件

svnserve.conf SVN服务配置文件

设置帐号密码
vi passwd

在[users]块中添加用户和密码,格式:帐号=密码,如dan=dan

设置权限
vi authz
在末尾添加如下代码:
[/]
dan=rw
w=r

意思是版本库的根目录dan对其有读写权限,w只有读权限

修改svnserve.conf文件
vi svnserve.conf
打开下面的几个注释:
anon-access = read #匿名用户可读 应改为none 不然无法显示日志
auth-access = write #授权用户可写
password-db = passwd #使用哪个文件作为账号文件
authz-db = authz #使用哪个文件作为权限文件
realm = /var/svn/svnrepos # 认证空间名,版本库所在目录
</pre><p>
</p><pre style="max-width:100%;overflow-x:auto;">
svnserve <span class="hljs-_">-d</span> -r /var/svn/pro<span class="hljs-comment">#启动svn版本库</span>
</pre><p>
</p>


<p>在WINDOWS中导出项目</p><p>新建一个测试文件夹,在该文件夹下右键选择 SVN checkout如下图(要事先安装TortoiseSVN)</p><p>svn地址格式如下:  svn://ip/pro</p><p>
</p>

linux 清除 .svn文件

<p>find . -type d -name ".svn"|xargs rm -rf<br/></p>

git

gitlab项目自动同步到github或者码云gitee

  • gitlab创建代码仓库
  • 打开gitlab项目,在左侧菜单栏选择Settings->Repository
  • 选择Push to a remote repository,打开之后可以看到相关的配置信息。
  • 勾选Remote mirror repository
  • 填写Git repository URL:这个URL地址就是你在码云或者github上面创建的项目的ssh地址,不过需要在地址里加上你的码云或者github的账号密码。

    比如: 我在码云的账号:userName 
    密码:password 
    项目地址:https://gitee.com/FutaoSmile/SpringCloud-ServiceRegisterCenter.git
    那么这个地址应该相应的改成这样: 
    https://userName:password@gitee.com/FutaoSmile/SpringCloud-ServiceRegisterCenter.git 
    密码和地址之间有一个@符号。
    
  • 测试:提交一次push到gitlab之后,gitlab会帮我们自动push代码到我们所配置的远程仓库。

git同时提交gitee和github

  • 在GITHUB和GITEE创建仓库
  • 本地克隆仓库(两个随便一个都行)
  • 更改.git文件配置 (.git/config)
  • 以下以本人learn为例

##原配置文件
[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
[remote &quot;origin&quot;]
    url = https://github.com/Jerrybibo/learn.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch &quot;master&quot;]
    remote = origin
    merge = refs/heads/master
[gui]
    wmstate = normal
    geometry = 841x483+125+125 189 218

##更改后配置文件
[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
[remote &quot;origin&quot;]
    url = https://github.com/Jerrybibo/learn.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[remote &quot;origin&quot;]
    url = https://gitee.com/jerrycyl/learn.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch &quot;master&quot;]
    remote = origin
    merge = refs/heads/master
[gui]
    wmstate = normal
    geometry = 841x483+125+125 189 218

最后git push 查看两仓库

搭建Git服务器

GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。

搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。

假设你已经有sudo权限的用户账号,下面,正式开始安装。

第一步,安装git

$ sudo apt-get install git

第二步,创建一个git用户,用来运行git服务:

$ sudo adduser git

第三步,创建证书登录:

收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

第四步,初始化Git仓库:

先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:

$ sudo git init --bare sample.git

Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git

$ sudo chown -R git:git sample.git

第五步,禁用shell登录:

出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

git:x:1001:1001:,,,:/home/git:/bin/bash

改为:

git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell

这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

第六步,克隆远程仓库:

现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:

$ git clone git@server:/srv/sample.git
Cloning into 'sample'...
warning: You appear to have cloned an empty repository.

git常用命令


git强制覆盖本地命令(单条执行)
git fetch --all && git reset --hard origin/master && git pull
 
git branch 查看本地所有分支
git status 查看当前状态 
git commit 提交 
git branch -a 查看所有的分支
git branch -r 查看远程所有分支
git commit -am "init" 提交并且加注释 
git remote add origin git@192.168.1.119:ndshow
git push origin master 将文件给推到服务器上 
git remote show origin 显示远程库origin里的资源 
git push origin master:develop
git push origin master:hb-dev 将本地库与服务器上的库进行关联 
git checkout --track origin/dev 切换到远程dev分支
git branch -D master develop 删除本地库develop
git checkout -b dev 建立一个新的本地分支dev
git merge origin/dev 将分支dev与当前分支进行合并
git checkout dev 切换到本地dev分支
git remote show 查看远程库
git add .
git rm 文件名(包括路径) 从git中删除指定文件
git clone git://github.com/schacon/grit.git 从服务器上将代码给拉下来
git config --list 看所有用户
git ls-files 看已经被提交的
git rm [file name] 删除一个文件
git commit -a 提交当前repos的所有的改变
git add [file name] 添加一个文件到git index
git commit -v 当你用-v参数的时候可以看commit的差异
git commit -m "This is the message describing the commit" 添加commit信息
git commit -a -a是代表add,把所有的change加到git index里然后再commit
git commit -a -v 一般提交命令
git log 看你commit的日志
git diff 查看尚未暂存的更新
git rm a.a 移除文件(从暂存区和工作区中删除)
git rm --cached a.a 移除文件(只从暂存区中删除)
git commit -m "remove" 移除文件(从Git中删除)
git rm -f a.a 强行移除修改后文件(从暂存区和工作区中删除)
git diff --cached 或 $ git diff --staged 查看尚未提交的更新
git stash push 将文件给push到一个临时空间中
git stash pop 将文件从临时空间pop下来

vagrant

vagrant快速搭建LNMP环境

vagrant下载
可以到VirtualBox的官网进行下载:
https://www.virtualbox.org/wiki/Downloads
vagrant安装
下载vagrant下的centos7的box
贴一个别人上传好的云盘链接
https://pan.baidu.com/s/1kW18LBD
创建一个新的centos7的虚拟机
vagrant box add mycentos CentOS-7.1.1503-x86_64-netboot.box
看看vagrant列表里有没有
vagrant box list
vagrant init mycentos
配置一下Vagrantfile文件
加上下面两条,为了添加ssh验证
config.ssh.username = "vagrant"
config.ssh.password = "vagrant"
其他比如共享文件夹和端口转发视个人情况自己百度之
更新yum源
yum update
安装wget
yum install wget
改yum源,用163的
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget http://mirrors.163.com/.help/CentOS6-Base-163.repo
yum makecache
安装mysql
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
yum localinstall mysql-community-release-el7-5.noarch.rpm
yum repolist enabled | grep "mysql.-community."
yum install mysql-community-server
改密码
mysql -u root
use mysql
select user,password,host from user;
update user set password=PASSWORD('root') where user='root';
FLUSH PRIVILEGES;
安装nginx
安装一些支持库
一. gcc 安装
安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装:
yum install gcc-c++
二. PCRE pcre-devel 安装
PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令:
yum install -y pcre pcre-devel
三. zlib 安装
zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库。
yum install -y zlib zlib-devel
四. OpenSSL 安装
OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。
nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库。
yum install -y openssl openssl-devel
下载nginx
wget -c https://nginx.org/download/nginx-1.10.1.tar.gz
解压
tar -zxvf nginx-1.10.1.tar.gz cd nginx-1.10.1
配置
./configure
编译安装
make make install
安装php7.1
下载php7
wget -O php7.tar.gz http://cn2.php.net/get/php-7.1.1.tar.gz/from/this/mirror
解压
tar -xvf php7.tar.gz
cd php-7.0.4
安装依赖包
yum install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel libcurl libcurl-devel libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel gmp gmp-devel libmcrypt libmcrypt-devel readline readline-devel libxslt libxslt-devel
解决libmcrypt库没有的问题
yum install -y epel-release
yum install -y libmcrypt-devel
编译配置
./configure --prefix=/usr/local/php --with-curl --with-freetype-dir --with-gd --with-gettext --with-iconv-dir --with-kerberos --with-libdir=lib64 --with-libxml-dir --with-mysqli --with-openssl --with-pcre-regex --with-pdo-mysql --with-pdo-sqlite --with-pear --with-png-dir --with-jpeg-dir --with-xmlrpc --with-xsl --with-zlib --with-bz2 --with-mhash --enable-fpm --enable-bcmath --enable-libxml --enable-inline-optimization --enable-gd-native-ttf --enable-mbregex --enable-mbstring --enable-opcache --enable-pcntl --enable-shmop --enable-soap --enable-sockets --enable-sysvsem --enable-sysvshm --enable-xml --enable-zip

安装
make && make install
配置环境变量
vim /etc/profile
export PATH=$PATH:/usr/local/php/bin
source /etc/profile
置php-fpm
cp php.ini-production /etc/php.ini
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf
cp ./sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
chmod +x /etc/init.d/php-fpm
启动php-fpm
/etc/init.d/php-fpm start
打包vagrant
vagrant package --base mycentos_default_1515579423331_47721 --output centos7-lnmp.box

vagrant方式开发环境部署
  1. 下载地址
  2. 基本原理
  3. 安装文档
  4. 注意事项
  5. vagrant 操作命令
  6. vagrant box相关参数

1.1. 下载地址

VirtualBox <https://www.virtualbox.org/wiki/Downloads>

Vagrant <https://www.vagrantup.com/downloads.html>

BOX包(适用于php5.4版本的bbc) <http://122.144.135.218/commerce_b2b2c-lnmp-with-prism-0.0.2.box> BOX包(适用于php5.6版本的bbc) <http://122.144.135.218/shopex-bbc-lnmp-php56-with-redis-v0.3.box>

1.2. 原理

VirtualBox 是一款开源虚拟机软件。

Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境。它使用Oracle的开源VirtualBox虚拟化系统,使用Chef创建自动化虚拟环境。

BBC Vagrant 是基于VirtualBox创建的虚拟机,并通过Vagrant进行打包而得到的VM环境。在虚拟机中部署好开发环境并建立虚拟机和实体机的文件共享,在开发时,可以通过实体机进行文件修改,并经过虚拟机中的环境执行,从而实现不同操作系统的工作环境的轻松部署。

1.3. 安装文档

1.4. 注意事项

  • 所有操作需要在workspace目录下执行
  • 浏览页面是127.0.0.1:8000。对应workspace/ecstore/
  • mysql网页配置端口是3306,如果需要从母机连接,需要访问33060端口。
  • 如果需要连接ssh,为:vagrant ssh 即可。
  • windows下,因为virtualbox本身一个bug,所以不能使用4.3.18版本,4.3.12版本可以用。
  • win8可能需要改bios(开启intel的虚拟技术intel Virtualization Technology)
  • box中的系统是64位的,建议在64位操作系统中使用

1.5. Vagrant 操作命令

  • 导入box

    vagrant box add [BOX NAME] [BOX URL]

  • 显示box列表

    vagrant box list

  • 移除box列表

    vagrant box remove [BOX NAME]

  • 初始化Vagrant(给当前目录创建vagrant环境)

    vagrant init [BOX NAME]

  • 启动Vagrant

    vagrant up

  • 关闭Vagrant

    vagrant halt

  • 暂停Vagrant

    vagrant suspend

  • 删除当前目录的Vagrant环境

    vagrant destroy

  • 实际环境中如果需要进行其它操作,可以使用-h参数来获取帮助例如:

    vagrant -h

1.6. BOX相关参数

  • ecstore-lnmp-0.0.2.box 应用参数

    项目

内容 centos 6.5 libmcrypt 2.5.7 libxml 2.9.0 freetype 62.3.5 gd 2.0.35 mysql 5.6.16 nginx 1.5.10 php 5.3.28 zend guard loader php-5.3-linux-glibc23-x86_64 mysql用户名密码 用户名:root,密码无 linux用户名密码 root用户和vagrant用户,密码均为vagrant 安装目录 /usr/local/webserver(php/mysql/nginx/freetype/gd) 启动脚本 /etc/init.d/(php-fpm|nginx|mysql) php配置文件 /usr/local/webserver/php/php.ini php-fpm配置文件 /usr/local/webserver/php/etc/php-fpm.conf nginx配置文件 /usr/local/webserver/nginx/conf/nginx.conf mysql配置文件 /etc/my.cnf 共享目录 /vagrant/ www目录 /vagrant/ecstore/ - ecstore-lnmp-0.0.2.box 端口映射

</tr>

</tr> </tbody></table>

  • shopex-bbc-lnmp-php56-with-redis-v0.1.box 应用参数
应用端口号映射端口号
ssh222222
nginx808000
prism80808001
mongodb27017-
rabbitmq-server(web)(预占用)156728002
mysql330633060
php-fpm9000-
项目内容
virtualBox版本5.0.20
vagrant1.8.40
CentOSCentOS 6.6 minimal
MySQL5.6.22-log MySQL Community Server (GPL)
nginxopenresty/1.9.7.4
Redisv=3.2.0 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=e1c0dcc4eb7d7755
ZendGuardLoaderZend Guard Loader v3.3, Copyright (c) 1998-2014, by Zend Technologies
OPcacheZend OPcache v7.0.4-dev, Copyright (c) 1999-2015, by Zend Technologies
mysql用户名密码用户名:root 密码:空
linux用户名密码root用户和vagrant用户,密码均为vagrant
安装目录/usr/local/{nginx,mysql,redis,php56}
启动脚本/etc/init.d/{nginx,mysql,redis,php56}
php配置文件/usr/local/php56/etc/php.ini
php-fpm配置文件/usr/local/php56/etc/php-fpm.conf
nginx配置文件/usr/local/nginx/conf/nginx.conf
共享目录/vagrant/
www目录/vagrant/
  • shopex-bbc-lnmp-php56-with-redis-v0.1.box 端口映射关系
应用虚拟机端口号宿主机端口
ssh222222
nginx808000
mysql330633060
php-fpm9000-
redis637916379
mac vagrant 配置

vagrant Vagrantfile 几个配置点
box设置

config.vm.box = &quot;CentOs7&quot;

该名称是再使用 vagrant init 中后面跟的名字。

hostname设置

config.vm.hostname = &quot;for_work&quot;

虚拟机网络设置

config.vm.network &quot;private_network&quot;, ip: &quot;192.168.33.10&quot;
#config.vm.network &quot;public_network&quot;

同步目录设置

config.vm.synced_folder  &quot;/Users/helei/www&quot;, &quot;/vagrant&quot;

端口转发设置

config.vm.network :forwarded_port, guest: 80, host: 80

mac demo 配置

# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "centos"
config.vm.synced_folder "/Users/chenyingliang/web/www", "/wwws",owner: "www", group: "www"

  config.vm.network :forwarded_port, guest: 80, host: 80
  config.vm.network :forwarded_port, guest: 8080, host: 8080
  config.vm.network :forwarded_port, guest: 8888, host: 8888
  config.vm.network :forwarded_port, guest: 3303, host: 3303
  config.vm.network :forwarded_port, guest: 888, host: 888
  config.vm.network :forwarded_port, guest: 86, host: 86
  config.vm.network :forwarded_port, guest: 5700, host: 5700
  config.vm.network :forwarded_port, guest: 5200, host: 5200
  config.vm.network "private_network", ip: "192.168.33.88"
config.ssh.username = 'root'
config.ssh.password = 'vagrant'
config.ssh.insert_key = false

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
   #  vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
    vb.memory = "4048"
  vb.cpus = 4
  end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

vagrant 使用 root用户
  1. 进入虚拟机,修改/etc/ssh/sshd_config配置文件
sudo vi /etc/ssh/sshd_config

## 把下面两项目的#号删掉
PermitRootLogin yes             # 允许 root 身份登录
PasswordAuthentication yes      # 可以使用密码登录

sudo systemctl restart sshd ## 重起sshd

exit(); 退出虚拟机

  1. 修改 Vagrantfile,增加下在的配置
config.ssh.username = 'root'
config.ssh.password = 'vagrant'
config.ssh.insert_key = false
  1. 重新加载Vagrantfile配置
vagrant reload
  1. 现次进入虚拟机就是ROOT用户了
sudo vagrant ssh 
vagrant环境中symfony程序速度慢解决方案

Mac本身自带的php没有memcached扩展,所以就把这个程序放到vagrant中,然而发现访问的速度非常慢,一个极其简单的页面也需要消耗10秒左右,于是搜索了一下,发现之前有人遇到相同的 问题。
vagrant环境中symfony程序速度慢解决方案

  • 使用vagrant1.2版本(目测不合适,现在都已经1.7+了)
  • 使用NFS方式挂载目录
  • vagrant虚拟机中的Vbox Guest Additions版本与virtual box版本一致(我当前的环境就是一致的)
  • 使用opcache扩展(我当前的环境已经安装了apc)
  • 关闭xdebug和xphrof扩展(我当前环境已经关闭)
    看这情况,只能尝试一下NFS方式了,根据vagrant的 文档配置,还好OS X自带了nfsd,省去了安装的麻烦,只需要修改vagrantfile即可。
config.vm.network :private_network, type::dhcpconfig.vm.synced_folder ".", "/vagrant", type: "nfs"
然后重启vagrant虚拟机vagrant reload
Vagrantfile- mac 已生效
# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://vagrantcloud.com/search.
  config.vm.box = "centos"
  config.vm.network :forwarded_port, guest: 80, host: 80
  config.vm.network :forwarded_port, guest: 8080, host: 8080
  config.vm.network :forwarded_port, guest: 8888, host: 8888
  config.vm.network :forwarded_port, guest: 3303, host: 3303
  config.vm.network :forwarded_port, guest: 888, host: 888
  config.vm.network :forwarded_port, guest: 86, host: 86
  config.vm.network :forwarded_port, guest: 5700, host: 5700
  config.vm.network :forwarded_port, guest: 5200, host: 5200
  config.vm.network "private_network", ip: "192.168.33.88"
  config.ssh.username = 'root'
  config.ssh.password = 'vagrant'
  config.ssh.insert_key = false

  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network "private_network", ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
   config.nfs.map_uid = Process.uid
  config.nfs.map_gid = Process.gid
  config.vm.synced_folder "/Users/jerry/www/web", "/vagrant",id: "vagrant-root", :nfs => true

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  # config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
  #   vb.memory = "1024"
  # end
  #
  # View the documentation for the provider you are using for more
  # information on available options.

  # Enable provisioning with a shell script. Additional provisioners such as
  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end
`

docker
daemon 配置

{
  "debug": true,
  "experimental": false,
"registry-mirrors": ["http://hub-mirror.c.163.com", "https://registry.docker-cn.com"]
}
安装宝塔

拉取CENTOS


docker pull centos:7

创建一个CentOS容器并映射8888端口,复制返回的容器ID

docker run -i -t -d --name baota -p 20:20 -p 21:21 -p 80:80 -p 443:443 -p 888:888 -p 8888:8888 -p 3306:3306 -p 3303:3303 --privileged=true -v /Users/chenyingliang/web:/wwws centos
上面命令的意思是创建一个docker容器命名为baota(名称大家自定义)让他后台运行,然后将宿主机的20,21,80,443,888,8888这五个端口映射到docker容器中去。
并且将宿主机的/Users/chenyingliang/web文件夹映射到docker容器的/www上去(注意:文件目录如果不存在。宿主机和容器会自己创建,无需手动创建)。privileged表示在运行容器的时候,给容器加特权,设置容器有写文件的权限。

进入容器终端

docker exec -it [容器ID] bash

chenyingliang@chenyingliangdeMacBook-Air ~ % docker exec -it 33702c063e2c9c36e17ba8ef1c7477302a76900ef32bfecc2d33e5bee2830640 bash 
[root@33702c063e2c /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

安装宝塔

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh
命令
  • 列出所有容器信息 docker ps
  • 停止所有容器 docker stop $(docker ps -a -q)
  • 使用以下命令来查看是否已安装了 centos docker images

Docker 命令大全
容器生命周期管理
run
start/stop/restart
kill
rm
pause/unpause
create
exec
容器操作
ps
inspect
top
attach
events
logs
wait
export
port
容器rootfs命令
commit
cp
diff
镜像仓库
login
pull
push
search
本地镜像管理
images
rmi
tag
build
history
save
load
import
info|version
info
version

nginx

nginx 是一个高性能的HTTP和反向代理的web 服务器,同时也提供 IMAP/POP3/SMTP服务 。

正向代理

请求会经过代理服务器,然后请求到目标服务器,获得得内容后,最后响应给客户端!

反向代理

反向代理是作用在服务器端的,是一个虚拟ip。对于用户的一个请求,会转发到多个后端处理器中的一台来处理该具体请求。

反向代理是代理服务器的一种。服务器根据客户端的请求,从其关联的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器簇的存在

集群和负载均衡

静态资源虚拟化

nginx 进程模型

nginx 默认 一个主进程(master process),一个工作进程(worker process) ,工作进程可以通过更改配置文件nginx.conf增加;

nginx.conf
##Nginx worker进程运行的用户及用户组 
user  www www;
##Nginx worker进程个数:其数量直接影响性能。
worker_processes  2;
## 日志地址
error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
pid        logs/nginx.pid;

events {
    use epoll;
     #注意:在使用debug_connection前,需确保在执行configure时已经加入了--with-debug参数,否则不会生效
    worker_connections  2048;
}
http {
##嵌入其他配置文件 语法:include /path/file
#参数既可以是绝对路径也可以是相对路径(相对于Nginx的配置目录,即nginx.conf所在的目录)
    include       mime.types;
    
    default_type  application/octet-stream;
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    #access_log  logs/access.log  main;
    sendfile        on;
    # tcp_nopush     on;
    keepalive_timeout  65;
  # gzip压缩功能设置
    gzip on;
    gzip_min_length 1k;
    gzip_buffers    4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 6;
    gzip_types text/html text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
    gzip_vary on;
  
  # http_proxy 设置
    client_max_body_size   10m;
    client_body_buffer_size   128k;
    proxy_connect_timeout   75;
    proxy_send_timeout   75;
    proxy_read_timeout   75;
    proxy_buffer_size   4k;
    proxy_buffers   4 32k;
    proxy_busy_buffers_size   64k;
    proxy_temp_file_write_size  64k;
    proxy_temp_path   /usr/local/nginx/proxy_temp 1 2;
  # 设定负载均衡后台服务器列表 
    upstream  backend  { 
              #ip_hash; 
              server   192.168.10.100:8080 max_fails=2 fail_timeout=30s ;  
              server   192.168.10.101:8080 max_fails=2 fail_timeout=30s ;  
    }
  # 很重要的虚拟主机配置
    server {
        listen       80;
        server_name  itoatest.example.com;
        root   /apps/oaapp;
        charset utf-8;
        access_log  logs/host.access.log  main;
        #对 / 所有做负载均衡+反向代理
        location / {
            root   /apps/oaapp;
            index  index.jsp index.html index.htm;
            proxy_pass        http://backend;  
            proxy_redirect off;
            # 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header  Host  $host;
            proxy_set_header  X-Real-IP  $remote_addr;  
            proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            
        }
        #静态文件,nginx自己处理,不去backend请求tomcat
        location  ~* /download/ {  
            root /apps/oa/fs;  
            
        }
        location ~ .*\.(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$   
        {   
            root /apps/oaapp;   
            expires      7d; 
        }
        location /nginx_status {
            stub_status on;
            access_log off;
            allow 192.168.10.0/24;
            deny all;
        }
        location ~ ^/(WEB-INF)/ {   
            deny all;   
        }
        #error_page  404              /404.html;
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
  ## 其它虚拟主机,server 指令开始
}
nginx 跨域解决
location / {  
    #允许跨域请求的域,*代表所有
    add_header 'Access-Control-Allow-Origin' *;
    #允许带上cookie请求 
    add_header 'Access-Control-Allow-Credentials' 'true';
    #允许请求的方法,比如 GET/POST/PUT/DELETE 
    add_header 'Access-Control-Allow-Methods' *; 
    #允许请求的
    header add_header 'Access-Control-Allow-Headers' *;
    
   #Access-Control-Allow-Methods 是为了防止出现Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.错误:
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

    if ($request_method = 'OPTIONS') {
        return 204;
    }
}
日志切割
## .日志切割(按天进行日志切割)
#!/bin/bash
year=`date +%Y`
month=`date +%m`
day=`date +%d`
logs_backup_path="/usr/local/nginx/logs_backup/$year$month"               #日志存储路径

logs_path="/usr/local/nginx/logs/"                                                             #要切割的日志路径
logs_access="access"                                                                            #要切割的日志
logs_error="error"
pid_path="/usr/local/nginx/logs/nginx.pid"                                                 #nginx的pid

[ -d $logs_backup_path ]||mkdir -p $logs_backup_path
rq=`date +%Y%m%d`
#mv ${logs_path}${logs_access}.log ${logs_backup_path}/${logs_access}_${rq}.log
mv ${logs_path}${logs_error}.log ${logs_backup_path}/${logs_error}_${rq}.log
kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)

3.做定时任务

crontab –e

59 23 * * * bash /usr/local/nginx/shell/cut_ngnix_log.sh   #每天23:59分开始执行;

Nginx 防盗链配置支持
#对源站点验证 
valid_referers *.imooc.com;
#非法引入会进入下方判断 
if ($invalid_referer) { 
    return 404; 
}
nginx 模块

event module 事件模块

phase handler

output filter

upstream 反向代理

load balancer 负载均衡

extend module

负载配置