一.sphinx增量索引的设置
数据库中的已有数据很大,又不断有新数据加入到数据库中,也希望能够检索到。全部重新建立索引很消耗资源,因为我们需要更新的数据相比较而言很少。例如。原来的数据有几百万条,而新增的只是几千条。这样就可以使用“主索引+增量索引”的模式来实现近乎实时更新的功能。
这个模式实现的基本原理是设置两个数据源和两个索引,为那些基本不更新的数据建立主索引,而对于那些新 增的数据建立增量索引。主索引的更新频率可以设置的长一些(例如设置在每天的午夜进行),而增量索引的更新频率,我们可以将时间设置的很短(几分钟左 右),这样在用户搜索的时候,我们可以同时查询这两个索引的数据。
使用“主索引+增量索引”方法有个简单的实现,在数据库中增加一个计数表,记录每次重新构建主索引时,被索引表的最后一个数据id,这样在增量索引时只需要索引这个id以后的数据即可,每次重新构建主索引时都更新这个表。
测试条件:以默认的sphinx.conf配置为例,数据库表的数据也以 example.sql为例。
1.先在mysql中插入一个计数表和两个索引表
2.修改sphinx.conf
source main_src{ type = mysql sql_host = localhost sql_user = yourusername sql_pass = yourpassword sql_db = test //你所用的数据库 sql_port = 3306 //所用端口,默认是3306
sql_query_pre = SET NAMES utf8
sql_query_pre = SET SESSION query_cache_type=OFF #下面的语句是更新sph_counter表中的 max_doc_id。
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title,\ content FROM documents \ WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) }
// 注意:delta_src 中的sql_query_pre的个数需和main_src 对应,否则可能搜索不出相应结果
source delta_src: main_src{ sql_ranged_throttle = 100 sql_query_pre = SET NAMES utf8 sql_query_pre = SET SESSION query_cache_type=OFF sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content FROM documents \ WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )}
index main //主索引{ source = main_src path = /path/to/main # example: /usr/local/sphinx/var/data/main ............. charset_type = utf-8 #这个是支持中文必须要设置的 chinese_dictionary =/usr/local/sphinx/etc/xdict #..........其它可以默认}
//delta可全部复制主索引,然后更改source 和path如下
index delta: main //增量索引{ source = delta_src path = /path/to/delta # example: /usr/local/sphinx/var/data/delta… }
其它的配置可都用默认的,如果你设置了分布式检索的索引,那么更改下对应的索引名称即可。
3.重新建立索引:
如果sphinx正在运行,那么首先停止运行,然后,根据sphinx.conf配置文件来建立所有索引,最后,启动服务
P.S /usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/sphinx.conf --all--rotate 这样就不需要停searchd,索引后也不再需要重启searchd了。
如果想测试增量索引是否成功,往数据库表中插入数据,查找是否能够检索到,这个时候检索应该为空,然后,单独重建 delta索引
/usr/local/sphinx/bin/indexer -c /usr/lcoal/sphinx/etc/sphinx.conf delta
查看是否将新的记录进行了索引。如果成功,此时,再用 /usr/local/sphing/bin/search 工具来检索,能够看到,在main索引中检索到的结果为0,而在delta中检索到结果。当然,前提条件是,检索的词,只在后来插入的数据中存在。
接下来的问题是如何让增量索引与主索引合并
4.索引合并
合并两个已有索引 有时比 重新索引所有数据有效,虽然,索引合并时,待合并的两个索引都会被读入内存一次,合并后的内容需写入磁盘一次,即,合并100GB和1GB的两个所以,将导致202GB的IO操作
命令原型: indexer --merge DSTINDEX SRCINDEX [--rotate] 将SRCINDEX合并到 DSTINDEX ,所以只有DSTINDEX会改变,如果两个索引都正在提供服务,那么 -- rotate 参数是必须的。例如:将delta合并到main中。
indexer --merge main delta
5.索引自动更新
需要使用到脚本。
建立两个脚本:build_main_index.sh 和 build_delta_index.sh.
build_main_index.sh:
#!/bin/sh
# 停止正在运行的searchd
/usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/mersphinx.conf --stop >> /usr/local/sphinx/var/log/sphinx/searchd.log
#建立主索引
/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/mersphinx.conf main >> /usr/local/sphinx/var/log/sphinx/mainindex.log
#启动searchd守护程序
/usr/local/sphinx/bin/searchd >> /usr/local/sphinx/var/log/sphinx/searchd.log
build_delta_index.sh
脚本写好后,需要编译 chmod +x filename 这样才能运行。即
chmod +x build_main_index.sh
chmod +x build_delta_index.sh
最后,我们需要脚本能够自动运行,以实现,delta索引每5分钟重新建立,和main索引只在午夜2:30时重新建立。
使用crontab 命令 这有俩个地方可作参考 crontab crontab文件
crontab -e 来编辑 crontab文件,如果之前没有使用,会是一个空的文件。写下下面两条语句
*/30 * * * * /bin/sh /usr/local/sphinx/etc/build_delta_index.sh > /dev/null 2>&1
30 2 * * * /bin/sh /usr/local/sphinx/etc/build_main_index.sh > /dev/null 2>&1
第一条是表示每30分钟运行 /usr/local/sphinx/etc/下的build_delta_index.sh 脚本,输出重定向。
第二条是表示 每天的 凌晨2:30分运行 /usr/local/sphinx/etc下的build_main_inde.sh 脚本,输出重定向。
关于前面的 5个值的设置,在上面的crontab文件中有详细的描述。关于重定向的解释,请看最上面的Crontab笔记 ,也有crontab的介绍。
保存好后:重新启动服务
过滤:
合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“
主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引
对应的数据)。因此indexer有这个选项。合并索引一般比重新索引快,但在大型索引上仍
然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写
入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还
是比重新索引少)
基本的命令语法如下:
indexer --merge DSTINDEX SRCINDEX[--rotate]
SRCINDEX的内容被合并到DSTINDEX中,因此只有DSTINDEX索引会被改变。若
DSTINDEX已经被searchd用于提供服务,则--rotate参数是必须的。最初设计的使用模式是,
将小量的更新从SRCINDEX合并到DSTINDEX中。因此,当属性被合并时,一旦出现了重
复的文档ID,SRCINDEX中的属性值更优先(会覆盖DSTINDEX中的值)。不过要注意,
“旧的”关键字并不会被自动删除。例如,在DSTINDEX中有一个叫做“old”的关键字与文
档123相关联,而在SRCINDEX中则有关键字“new”与同一个文档相关,那么在合并后用
这两个关键字都能找到文档123。您可以给出一个显式条件来将文档从DSTINDEX中移除,
以便应对这种情况,相关的开关是--merge-dst-range:
indexer --merge main delta--merge-dst-range deleted 00
这个开关允许您在合并过程中对目标索引实施过滤。过滤器可以有多个,只有满足全部过滤
条件的文档才会在最终合并后的索引中出现。在上述例子中,过滤器只允许“deleted”为0
的那些条件通过,而去除所有标记为已删除(“deleted”)的记录(可以通过调用
UpdateAttributes() 设置文档的属性)。
去旧(强行更新):
情景描述:假设有一旧关键字“去钓鱼”,与论坛贴子“周末的活动”相关联,用“去钓鱼”可以搜索到这篇帖子。之后楼主把贴子关键字部分改成了“去河边钓鱼”。如果用sphinx的indexer生成增量索引bbsattend,然后用indexer--merge bbs bbsattend--rotate合成到主索引bbs后。用“去河边钓鱼”搜不到结果,用“去钓鱼”可以搜到“去河边钓鱼”的结果。
解决办法:加--merge-killists option(选项)
indexer --merge bbs bbsattend--rotate --merge-killists