网上有增量索引的资料,但不完善,很多都是转载来转载去的。

Sphinx做了索引之后,并不会自动去抓取mysql新增的内容。写个脚本定期重新索引是不可能的。Sphinx本身也有增量索引功能。说白了就是回MySQL里拿新增的内容,并合并到原有的索引中。

由此可见,Sphinx还是比较适合一些大数据、只增不改的数据库。

网上有增量教程,大概就是在MySQL里建立一个辅助表,在每次Sphinx过来抓的时候mark一下,然后下一次在这个点后继续抓。但是逻辑上有问题,看文章作者似乎发现了并修改了,但还是不完善。增量索引空sql_query_pre,则将一直沿用主索引建立时记录的maxid,每次增量索引都会抓到一些重复内容。

实际上如果仅用sql_query_pre,辅助表需要ID、This_time、Last_time 三个字段,因为sql_query_pre是在增量主sql前执行,如此一来,增量主语句获取的内容将为空。【即便是官方文档,也是使用sql_query_pre,这一点另我很好奇】,增加一个缓存上次maxid的last_time字段,这样就可以在每次sql_query_pre的时候查询最新的maxid,写入this_time,并把原来的this_time移动到last_time,sql_qurey执行的时候,使用last_time中记录的maxid来获取数据。

我没有尝试使用sql_query_post,但我觉得用他更合适。这样就可以只用两个字段了。

Mysql的辅助表

CREATE TABLE IF NOT EXISTS `sph_counter` (
  `key` int(11) NOT NULL,
  `last_time` int(11) NOT NULL,
  `this_time` int(11) NOT NULL,
  PRIMARY KEY (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

主索引

source main
{
        type                    = mysql
        sql_host                = localhost
        sql_user                = root
        sql_pass                = 
        sql_db                  = db
        sql_port                = 3306
        sql_query_pre           = SET NAMES utf8
        sql_query_pre           = SET SESSION query_cache_type=OFF
        sql_query_pre           = REPLACE INTO sph_counter SELECT 1,0, MAX(id) FROM hashs
        sql_query               = SELECT id,atime,title,size,hash,title as content FROM hashs WHERE id<=(SELECT this_time FROM sph_counter WHERE `key`=1)
        sql_attr_string         = content
        sql_attr_string         = size
        sql_attr_string         = hash
        sql_attr_timestamp	= atime
}

增量索引

source delta : main
{
        sql_ranged_throttle   = 1000
        sql_query_pre         = SET NAMES utf8
        sql_query_pre         = SET SESSION query_cache_type=OFF
        sql_query_pre         = update sph_counter set last_time = this_time , this_time = (select MAX(hashs.id) from hashs) where `key` = 1
        sql_query             = SELECT id,atime,title,size,hash,title as content FROM hashs WHERE id>(SELECT last_time FROM sph_counter WHERE `key`=1)
}

最后是定期更新增量的shell,实测这样写法不会遗漏数据,也不会额外读取。

/usr/bin/indexer --rotate btzz_inc && /usr/bin/indexer --merge btzz btzz_inc --rotate

不得不说Sphinx的确非常好用,即便不用分词器,就用原版的Sphinx+chartset_table,效果也会比自己做的搜索快且好的多的多。

有些网友说Sphinx只返回ID,数据还是需要去mysql拿,因此说Sphinx在数据不大的情况下可能会是累赘,看网上很多教程也是这样。

我是直接完全从Sphinx拿数据的方式,没有上千万的数据,不到一百,但觉得速度的确是有很大改善。

了解Sphinx仅第二天,可能有一些基础的东西没了解,欢迎拍砖。