tips:
Sphinx查询中Attribute(属性)的概念,而且Sphinx在启动Searchd的时候会将所有属性加载到内存中.所以如果数量巨大时可能会 FATAL: out of memory (unable to allocate 1494868092 bytes),此时应该分批创建索引再合并。
sphinx增量索引和主索引来实现索引的实时更新
项目中文章的信息内容因为持续有新增,而文章总量的基数又比较大,所以做搜索的时候,用了主索引+增量索引这种方式来实现索引的实时更新。
实现原理:
1. 新建一张表,记录一下上一次已经创建好索引的最后一条记录的ID
2. 当索引时,然后从数据库中取出所有ID大于上面那个sphinx中的那个ID的数据, 这些就是新的数据,然后创建一个小的索引文件
3. 把上边我们创建的增量索引文件合并到主索引文件上去
4. 把最后一条记录的ID更新到第一步创建的表中
值得注意的两点:
1)当合并索引的时候,只是把增量的索引合并进主索引中,增量索引本身并不会变化,也不会被删除;
2)当重建主索引的时候,增量索引就会被删除;
具体操作实现流程:
1. 新建一张表,用于存储已经建过索引的最大的doc_id
CREATE TABLE `sph_counter` (
`counter_id` int(11) NOT NULL COMMENT '标识不同的数据表',
`max_doc_id` int(11) NOT NULL COMMENT '每个索引表的最大ID,会实时更新',
PRIMARY KEY (`counter_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-----------------------------------------------
以ID作为增量和生成主索引的分割点的时候,如果使用索引合并来做的话,那么只能索引到新增的数据,而
更新的数据则无法被索引,所以做个记录更新时间的字段与ID做联合主键,以这个更新时间来做分割点
--------------------------------------------------------------------------------------
2. 配置索引文件
#主索引数据源定义
source article_main
{
type = mysql
sql_host =xxx.xxx.xxx.xx
sql_user =
sql_pass =
sql_db =
sql_port = 3306
sql_query_pre = SET NAMES utf8
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query_range =
sql_range_step = 10000
sql_query = \
SELECT *\
FROM documents WHERE id<=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1);
sql_attr_timestamp = pubtime #从SQL读取到的值必须为整数,作为时间属性
sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集
sql_query_info = SELECT * FROM documents WHERE id=$id #命令行查询时,从数据库读取原始数据信息
}
#增量数据源
29 source delta : src1
30
31 {
32
33 sql_query_pre = SET NAMES utf8
34
35 sql_query_pre = SET SESSION query_cache_type=OFF
36
37 sql_query = SELECT * FROM documents WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
#如果只做索引合并不做主索引的定时生成,那么这里必须还要再更新完增量索引后将sph_counter的max_doc_id 修改,不然每当再次生成增量索引时
sql_query_post = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents;
38
39 sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集
40
41 sql_query_info = SELECT * FROM documents WHERE id=$id
42
43 }
46 #定义索引
47 index test1
48 {
49 #索引数据源
50 source = src1
51 #数据地址
52 path = /usr/local/csft4/var/data/test1
53 docinfo = extern
54 charset_type = zh_cn.utf-8
55 #中文分词配置
56 #BSD、Linux环境下设置,/符号结尾
57 charset_dictpath = /usr/local/mmseg4/etc/
58 }
59
60
61 # 增量索引
62 index delta : test1
63 {
64 source = delta
65 path = /usr/local/csft4/var/data/delta
66 docinfo = extern
67 mlock = 0
68 morphology = none
69 min_word_len = 1
70 html_strip = 0
71
72 charset_dictpath = /usr/local/mmseg4/etc/ #BSD、Linux环境下设置,/符号结尾
73 charset_type = zh_cn.utf-8
74 }
indexer
77 {
78 mem_limit =64M
79 }
80
81
82 searchd
83 {
84 listen = 9312
85 listen = 9306:mysql41
86 log = /usr/local/csft4/logs/searchd.log
87 query_log = /usr/local/csft4/logs/query.log
88 read_timeout = 5
89 max_children = 30
90 pid_file = /usr/local/csft4/pids/searchd.pid
91 max_matches = 1000
92 seamless_rotate = 1
93 preopen_indexes = 1
94 unlink_old = 1
95 workers = threads # for RT to work
96 }
文件配置完毕后,重新启动searchd服务来加载新的配置文件:
./searchd -c /usr/local/csft4/etc/csft.conf --stop
注意csft.conf配置文件里面的注释只能使用#号,否则会报parse语法错误。
两外sql语句中where条件最好同主语句写在同一行。
关闭后再次打开searchd服务
/usr/local/csft4/bin/searchd -c /usr/local/csft4/etc/csft.conf
新建主索引 :
sudo /usr/local/csft4/bin/indexer -c /usr/local/csft4/etc/csft.conf test1 --rotate
插入一些数据后测试新建增量索引:
sudo /usr/local/csft4/bin/indexer -c /usr/local/csft4/etc/csft.conf delta --rotate
-rotate参数可以在不停searchd的情况下索引,不然的话会有类似如下的提示:
FATAL: failed to lock /usr/local/coreseek/var/data/hx_9enjoy_delta.spl: Resource temporarily unavailable, will not index. Try --rotate option.
ERROR: index 'delta' is already locked; lock: failed to lock /usr/local/coreseek/var/data/cncn_article_delta.spl: Resource temporarily unavailable
需要注意的是如果在searchd为开启状态下使用--rotate生成索引文件名则生成的文件会带有new这个字符串:
delta.new.spa delta.new.sph delta.new.spk delta.new.spp test1.new.spa test1.new.sph test1.new.spk test1.new.spp
delta.new.spd delta.new.spi delta.new.spm delta.new.sps test1.new.spd test1.new.spi test1.new.spm test1.new.sps
如果sphinx在运行中,要indexer时,需要加上--rotate参数,这样索引完就直接生效了。
原因是sphinx的searchd在启动时会创建一个 .spl 锁文件,并在关闭时会删除它。在indexer创建索引时如果发现有 .spl文件,则不会创建新索引,因为这时已经标志sphinx正在运行中,除非使用 –rotate。
rotate运行机制
->indexer完成索引
->发送SIGHUP 给searchd(同时在终端输出索引已经完成)
->searchd接到中断信号->等待所有子进程退出
->重命名 当前索引为旧索引为 .old
->重命名 .new 索引文件作为当前索引
->尝试加载当前索引文件->如果加载失败,searchd会把.old文件回滚为当前文件,并把刚建立的新索引重命名为 .new
->加载成的话:完成无缝切换
------------------------------------------
手动重启的两种办法:
1.
关闭searchd :killall -9 searchd
重启 searchd :searchd -c ../sphinx.conf
2.
关闭:searchd --stop
启动:searchd
经过实验发现,如果是生成增量索引,即使searchd在开启状态也能生成。
而在没有生成索引时开启searchd服务则会提示:
[root@localhost bin]# /usr/local/csft4/bin/searchd -c /usr/local/csft4/etc/csft.conf
Coreseek Fulltext 4.1 [ Sphinx 2.0.2-dev (r2922)]
Copyright (c) 2007-2011,
Beijing Choice Software Technologies Inc (http://www.coreseek.com)
using config file '/usr/local/csft4/etc/csft.conf'...
WARNING: compat_sphinxql_magics=1 is deprecated; please update your application and config
listening on all interfaces, port=9312
listening on all interfaces, port=9306
precaching index 'test1'
WARNING: index 'test1': preload: failed to open /usr/local/csft4/var/data/test1.sph: No such file or directory; NOT SERVING
precaching index 'delta'
WARNING: index 'delta': preload: failed to open /usr/local/csft4/var/data/delta.sph: No such file or directory; NOT SERVING
FATAL: no valid indexes to serve
Sphinx查询中Attribute(属性)的概念,而且Sphinx在启动Searchd的时候会将所有属性加载到内存中.所以如果数量巨大时可能会 FATAL: out of memory (unable to allocate 1494868092 bytes),此时应该分批创建索引再合并。
sphinx增量索引和主索引来实现索引的实时更新
项目中文章的信息内容因为持续有新增,而文章总量的基数又比较大,所以做搜索的时候,用了主索引+增量索引这种方式来实现索引的实时更新。
实现原理:
1. 新建一张表,记录一下上一次已经创建好索引的最后一条记录的ID
2. 当索引时,然后从数据库中取出所有ID大于上面那个sphinx中的那个ID的数据, 这些就是新的数据,然后创建一个小的索引文件
3. 把上边我们创建的增量索引文件合并到主索引文件上去
4. 把最后一条记录的ID更新到第一步创建的表中
值得注意的两点:
1)当合并索引的时候,只是把增量的索引合并进主索引中,增量索引本身并不会变化,也不会被删除;
2)当重建主索引的时候,增量索引就会被删除;
具体操作实现流程:
1. 新建一张表,用于存储已经建过索引的最大的doc_id
CREATE TABLE `sph_counter` (
`counter_id` int(11) NOT NULL COMMENT '标识不同的数据表',
`max_doc_id` int(11) NOT NULL COMMENT '每个索引表的最大ID,会实时更新',
PRIMARY KEY (`counter_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-----------------------------------------------
以ID作为增量和生成主索引的分割点的时候,如果使用索引合并来做的话,那么只能索引到新增的数据,而
更新的数据则无法被索引,所以做个记录更新时间的字段与ID做联合主键,以这个更新时间来做分割点
--------------------------------------------------------------------------------------
2. 配置索引文件
#主索引数据源定义
source article_main
{
type = mysql
sql_host =xxx.xxx.xxx.xx
sql_user =
sql_pass =
sql_db =
sql_port = 3306
sql_query_pre = SET NAMES utf8
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query_range =
sql_range_step = 10000
sql_query = \
SELECT *\
FROM documents WHERE id<=(SELECT max_doc_id FROM sph_counter WHERE counter_id=1);
sql_attr_timestamp = pubtime #从SQL读取到的值必须为整数,作为时间属性
sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集
sql_query_info = SELECT * FROM documents WHERE id=$id #命令行查询时,从数据库读取原始数据信息
}
#增量数据源
29 source delta : src1
30
31 {
32
33 sql_query_pre = SET NAMES utf8
34
35 sql_query_pre = SET SESSION query_cache_type=OFF
36
37 sql_query = SELECT * FROM documents WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
#如果只做索引合并不做主索引的定时生成,那么这里必须还要再更新完增量索引后将sph_counter的max_doc_id 修改,不然每当再次生成增量索引时
sql_query_post = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents;
38
39 sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集
40
41 sql_query_info = SELECT * FROM documents WHERE id=$id
42
43 }
46 #定义索引
47 index test1
48 {
49 #索引数据源
50 source = src1
51 #数据地址
52 path = /usr/local/csft4/var/data/test1
53 docinfo = extern
54 charset_type = zh_cn.utf-8
55 #中文分词配置
56 #BSD、Linux环境下设置,/符号结尾
57 charset_dictpath = /usr/local/mmseg4/etc/
58 }
59
60
61 # 增量索引
62 index delta : test1
63 {
64 source = delta
65 path = /usr/local/csft4/var/data/delta
66 docinfo = extern
67 mlock = 0
68 morphology = none
69 min_word_len = 1
70 html_strip = 0
71
72 charset_dictpath = /usr/local/mmseg4/etc/ #BSD、Linux环境下设置,/符号结尾
73 charset_type = zh_cn.utf-8
74 }
indexer
77 {
78 mem_limit =64M
79 }
80
81
82 searchd
83 {
84 listen = 9312
85 listen = 9306:mysql41
86 log = /usr/local/csft4/logs/searchd.log
87 query_log = /usr/local/csft4/logs/query.log
88 read_timeout = 5
89 max_children = 30
90 pid_file = /usr/local/csft4/pids/searchd.pid
91 max_matches = 1000
92 seamless_rotate = 1
93 preopen_indexes = 1
94 unlink_old = 1
95 workers = threads # for RT to work
96 }
文件配置完毕后,重新启动searchd服务来加载新的配置文件:
./searchd -c /usr/local/csft4/etc/csft.conf --stop
注意csft.conf配置文件里面的注释只能使用#号,否则会报parse语法错误。
两外sql语句中where条件最好同主语句写在同一行。
关闭后再次打开searchd服务
/usr/local/csft4/bin/searchd -c /usr/local/csft4/etc/csft.conf
新建主索引 :
sudo /usr/local/csft4/bin/indexer -c /usr/local/csft4/etc/csft.conf test1 --rotate
插入一些数据后测试新建增量索引:
sudo /usr/local/csft4/bin/indexer -c /usr/local/csft4/etc/csft.conf delta --rotate
-rotate参数可以在不停searchd的情况下索引,不然的话会有类似如下的提示:
FATAL: failed to lock /usr/local/coreseek/var/data/hx_9enjoy_delta.spl: Resource temporarily unavailable, will not index. Try --rotate option.
ERROR: index 'delta' is already locked; lock: failed to lock /usr/local/coreseek/var/data/cncn_article_delta.spl: Resource temporarily unavailable
需要注意的是如果在searchd为开启状态下使用--rotate生成索引文件名则生成的文件会带有new这个字符串:
delta.new.spa delta.new.sph delta.new.spk delta.new.spp test1.new.spa test1.new.sph test1.new.spk test1.new.spp
delta.new.spd delta.new.spi delta.new.spm delta.new.sps test1.new.spd test1.new.spi test1.new.spm test1.new.sps
如果sphinx在运行中,要indexer时,需要加上--rotate参数,这样索引完就直接生效了。
原因是sphinx的searchd在启动时会创建一个 .spl 锁文件,并在关闭时会删除它。在indexer创建索引时如果发现有 .spl文件,则不会创建新索引,因为这时已经标志sphinx正在运行中,除非使用 –rotate。
rotate运行机制
->indexer完成索引
->发送SIGHUP 给searchd(同时在终端输出索引已经完成)
->searchd接到中断信号->等待所有子进程退出
->重命名 当前索引为旧索引为 .old
->重命名 .new 索引文件作为当前索引
->尝试加载当前索引文件->如果加载失败,searchd会把.old文件回滚为当前文件,并把刚建立的新索引重命名为 .new
->加载成的话:完成无缝切换
------------------------------------------
手动重启的两种办法:
1.
关闭searchd :killall -9 searchd
重启 searchd :searchd -c ../sphinx.conf
2.
关闭:searchd --stop
启动:searchd
经过实验发现,如果是生成增量索引,即使searchd在开启状态也能生成。
而在没有生成索引时开启searchd服务则会提示:
[root@localhost bin]# /usr/local/csft4/bin/searchd -c /usr/local/csft4/etc/csft.conf
Coreseek Fulltext 4.1 [ Sphinx 2.0.2-dev (r2922)]
Copyright (c) 2007-2011,
Beijing Choice Software Technologies Inc (http://www.coreseek.com)
using config file '/usr/local/csft4/etc/csft.conf'...
WARNING: compat_sphinxql_magics=1 is deprecated; please update your application and config
listening on all interfaces, port=9312
listening on all interfaces, port=9306
precaching index 'test1'
WARNING: index 'test1': preload: failed to open /usr/local/csft4/var/data/test1.sph: No such file or directory; NOT SERVING
precaching index 'delta'
WARNING: index 'delta': preload: failed to open /usr/local/csft4/var/data/delta.sph: No such file or directory; NOT SERVING
FATAL: no valid indexes to serve
——————————————————————————————————————————————————————————————————
对索引的操作命令:
重建主索引和增量索引:
- /usr/local/coreseek/bin/indexer--config /usr/local/coreseek/etc/csft.conf -rotate index_main
- /usr/local/coreseek/bin/indexer--config /usr/local/coreseek/etc/csft.conf -rotate index_add
合并建主索引和增量索引:
- indexer --config /usr/local/coreseek/etc/csft.conf --merge index_main index_add --merge-dst-range deleted 0 0 -rotate
重建整个索引:
/usr/local/coreseek/bin/indexer --config /usr/local/coreseek/etc/csft.conf --all --rotate