注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

php开发lamp

《西安--木木》-经历丰富了生活。 架构师QQ群: 246695517

 
 
 

日志

 
 

coreseek索引更新机制  

2013-06-09 16:42:05|  分类: sphinx |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

每隔一分钟更新增量索引,每天再重建一次索引。sph_counter 中存放区分主索引和增量索引的maxid。现在的方法,依旧是每分钟更新增量索引,但是重建索引改成合并,将增量索引合并到主索引中,并更改sph_counter中的maxid值,清空增量索引。搜索则都是同时从两个索引中搜索。

先是更新sph_counter的maxid值,这个时候还没有考虑到清空增量索引,所以合并索引这步暂时是没有问题的,而合并索引后,再更新增量索引,还会得到第一次建立索引后的所有增量,因为没有改变maxid,后来在coreseek.cn上看到有人提到sql_query_post_index,可以更新增量索引后改变maxid值,于是在增量index中加入了这个选项,= =开始是手工更新增量索引,合并到主索引,这两步一起做,没有问题,后来用crontab才发现,增量索引每更新一次,前面的记录都会丢失,因为这些记录还没有合并到主索引就被更新的增量索引覆盖了。这个方法行不通,后来问了神仙,= =,原来脚本也可以更改数据表中的值,请教了一下,此问题解决。说完另一个问题,一起贴最终的脚本内容。

合并索引后,清空增量索引,到底怎么个清空法是个问题,开始的想法是直接删除增量索引文件,删除后加--rotate,更新增量索引会出错,出错信息好像是没有增量索引的文件吧。后来听神仙说,要去掉--rotate,没有出错,可是后面的每分钟更新增量索引会有问题,看了一下索引文件,只要加了--rotate的,生成的增量索引文件是delta_new.,这样,虽然增量索引更新成功,却搜索不要更新的记录。如果不加--rotate,索引文件正常,但是依旧搜索不到新记录。后来不知怎的一想,不用删除索引文件,因为前面的maxid值已经改变了,直接更新增量索引不也可以么,试了一下,果然。

下面整个的贴一下代码。

1、首先是建立索引

/usr/local/coreseek/bin/indexer --all --config /data/coreseek/conf/post.conf

2、启动守护进程

/usr/local/coreseek/bin/searchd --config /data/coreseek/conf/post.conf

3、+记录

4、更新增量索引,这个写在脚本里,因为需要每分钟更新。

文件名:/data/coreseek/sh/build_delta_index.sh

/usr/local/coreseek/bin/indexer post_delta --config /data/coreseek/conf/post.conf --rotate

5、合并索引,这个也要写在脚本里,每天合并一次

文件名:/data/coreseek/sh/build_main_index.sh

/usr/local/coreseek/bin/indexer --merge post_main post_delta --rotate --config /data/coreseek/conf/post.conf  //合并索引
/usr/local/mysql/bin/mysql -hhostname -uusername -ppassword -Ddbname -e 'REPLACE INTO sph_counter SELECT 1, MAX(PostId) FROM Post' //更改maxid
/usr/local/coreseek/bin/indexer post_delta --config /data/coreseek/conf/post.conf --rotate >>/var/log/coreseek/deltaindexlog

//重建增量索引

再贴下crontab规则

*/1 * * * * /bin/sh /data/coreseek/sh/build_delta_index.sh
30 1 * * * /bin/sh /data/coreseek/sh/build_main_index.sh


命令执行顺序
1)indexer.exe --config etc\sphinx.conf --all
 
2)searchd.exe -c etc\sphinx.conf
每分钟都执行增量索引
3)indexer.exe delta --config etc\sphinx.conf --rotate
晚上2点执行合并索引
4)indexer.exe --merge doctest delta --rotate --config etc\sphinx.conf
5)更改数据库最大值
 mysql -h192.168.11.17 -uroot -proot -Dls_test -e 'REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents'


有这么一种常见的情况:整个数据集非常大,以至于难于经常性的重建索引,但是每次新增的记录却相当地少。一个典型的例子是:一个论坛有1000000个已经归档的帖子,但每天只有1000个新帖子。
在这种情况下可以用所谓的“主索引+增量索引”(main+delta)模式来实现“近实时”的索引更新。
这种方法的基本思路是设置两个数据源和两个索引,对很少更新或根本不更新的数据建立主索引,而对新增文档建立增量索引。在上述例子中,那1000000个已经归档的帖子放在主索引中,而每天新增的1000个帖子则放在增量索引中。增量索引更新的频率可以非常快,而文档可以在出现几分种内就可以被检索到。
确定具体某一文档的分属那个索引的分类工作可以自动完成。一个可选的方案是,建立一个计数表,记录将文档集分成两部分的那个文档ID,而每次重新构建主索引时,这个表都会被更新。
Example 4. 全自动的即时更新
# in MySQL
CREATE TABLE sph_counter
(
    counter_id INTEGER PRIMARY KEY NOT NULL,
    max_doc_id INTEGER NOT NULL
);
# in sphinx.conf
source main
{
    # ...
    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
    # ... all the other settings
}
# note how all other settings are copied from main,
# but source and path are overridden (they MUST be)
index delta : main
{
    source = delta
    path = /path/to/delta
}

请注意,上例中我们显示设置了数据源delta的sql_query_pre选项,覆盖了全局设置。必须显示地覆盖这个选项,否则对delta做索引的时候也会运行那条REPLACE查询,那样会导致delta源中选出的数据为空。可是简单地将delta的sql_query_pre设置成空也不行,因为在继承来的数据源上第一次运行这个指令的时候,继承来的所有值都会被清空,这样编码设置的部分也会丢失。因此需要再次显式调用编码设置查询。
索引合并
合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引对应的数据)。因此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 0 0

这个开关允许您在合并过程中对目标索引实施过滤。过滤器可以有多个,只有满足全部过滤条件的文档才会在最终合并后的索引中出现。在上述例子中,过滤器只允许“deleted”为0的那些条件通过,而去除所有标记为已删除(“deleted”)的记录(可以通过调用UpdateAttributes()设置文档的属性)。

在实际应用中往往有这么一种情况,数据库数据很大,比如我们的歌曲表,如果我们每次都去更新整个表的索引,对系统得开销将非常大,显然这是不合适,这时我们会发现,每天我们需要更新的数据相比较而言较少,在这种情况下我们就需要使用“主索引+增量索引”的模式来实现实时更新的功能。 这个模式实现的基本原理是设置两个数据源和两个索引,为那些基本不更新的数据建立主索引,而对于那些新增的数据建立增量索引。主索引的更新频率我们可以设置的长一些(可以设置在每天的午夜进行更新),而增量索引的更新频率,我们可以将时间设置的很短(几分钟左右),这样在用户搜索的时候,我们可以同时查询这两个索引的数据。 下面,我们通过一个简单的例子来描述一下怎样实现这种模式 以sphinx.conf中默认的数据为例:
先在mysql中插入一个计数表和两个索引表

CREATE TABLE sph_counter(
counter_id INTEGER PRIMARY KEY NOT NULL,
max_doc_id INTEGER NOT NULL
);

//主索引使用(确认之前是否已经建立过该表,如果已经建立,这里就不需要重新建了)

CREATE TABLE `sphinx` (  
`id` int(11) NOT NULL,  
`weight` int(11) NOT NULL,  
`query` varchar(255) NOT NULL,  
`CATALOGID` INT NOT NULL,  
`EDITUSERID` INT NOT NULL,  
`HITS` INT NULL,  
`ADDTIME` INT NOT NULL,   KEY
`Query` (`Query`)
) ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=‘sphinx://localhost:3312/test1‘

//增量索引使用

CREATE TABLE `sphinx1` (
`id` int(11) NOT NULL,
`weight` int(11) NOT NULL,
`query` varchar(255) NOT NULL,
`CATALOGID` INT NOT NULL,
`EDITUSERID` INT NOT NULL,
`HITS` INT NULL,
`ADDTIME` INT NOT NULL, KEY
`Query` (`Query`)
)ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=’sphinx://localhost:3312/ test1stemmed ‘

修改sphinx.conf
source src1
{
sql_query_pre = SET NAMES utf8
sql_query_pre = SET SESSION query_cache_type=OFF
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 )
… //其他可以默认
}

// 注意:sql_query_pre的个数需和src1对应,否则可能搜索不出相应结果

source src1throttled : src1
{
sql_ranged_throttle = 100
sql_query_pre = SET NAMES utf8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre =
   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 test1 //主索引
{
source = src1

}
index test1stemmed : test1 //增量索引
{
source = src1throttled

}

重建索引
/usr/local/sphinx/bin/searchd –stop
/usr/local/sphinx/bin/indexer –config /usr/local/sphinx/etc/sphinx.conf –all
/usr/local/sphinx/bin/searchd –config /usr/local/sphinx/etc/sphinx.conf

插入测试数据

INSERT INTO `test`.`documents` (
`id` ,
`group_id` ,
`group_id2` ,
`date_added` ,
`title` ,
`content`
)
VALUES (
NULL , ‘3‘, ‘11‘, NOW( ) , ‘索引合并‘, ‘合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“ 主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引对应的数据)。因此indexer有这个选项。合并索引一般比重新索引快,但在大型索引上仍然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还是比重新索引少)‘
);

执行

SELECT doc . *
FROM documents doc
JOIN sphinx ON ( doc.id = sphinx.id )
WHERE query = ‘索引‘

你会发现你刚添加的数据没有被检索出来 然后执行:

SELECT doc.* FROM documents doc join sphinx1 on (doc.id=sphinx1.id) where query=‘索引‘

你会发现数据是空的,这时我们就需要来更新增量索引了。 通过执行:

/usr/local/sphinx/bin/indexer –rotate –config /usr/local/sphinx/etc/sphinx.conf test1stemmed

命令来更新增量索引(正式使用时,我们可以将该命令配置到系统计划任务中,每隔几分钟执行一次) –rotate: 该参数可以使我们在不需要停止searchd的情况下,直接加载索引 执行完命令该命令后,我们再来查看一下增量索引的数据

SELECT doc.* FROM documents doc join sphinx1 on (doc.id=sphinx1.id) where query=‘索引‘

你会发现新添加的数据被检索出来的。 主索引的更新:

/usr/local/sphinx/bin/indexer –rotate –config /usr/local/sphinx/etc/sphinx.conf test1
collected 997 docs, 1.4 MB
sorted 0.3 Mhits, 100.0% done
total 997 docs, 1430054 bytes
total 1.428 sec, 1001459.38 bytes/sec, 698.19 docs/sec

(我们可以设置成每天的午夜执行) 只有在更新了主索引后,结果才会被更新

SELECT doc.* FROM documents doc join sphinx on (doc.id=sphinx.id) where query=‘索引‘

我们也可以通过合并索引的方式使主索引的数据保持更新

/usr/local/sphinx/bin/indexer –merge test1 test1stemmed –rotate

可以将增量索引test1stemmed合并到主索引test1中去 为创建2个shell脚本,一个用来创建主索引、一个用来创建增量索引(此步可以省略)
创建主索引脚本build_main_index.sh

#!/bin/sh
#/usr/local/sphinx/bin/searchd –stop
/usr/local/sphinx/bin/indexer test1 –config /usr/local/sphinx/etc/sphinx.conf >> /var/log/sphinx/mainindexlog
#/usr/local/sphinx/bin/searchd

创建增量索引脚本build_delta_index.sh
#!/bin/sh
#/usr/local/sphinx/bin/searchd –stop
/usr/local/sphinx/bin/indexer test1stemmed –config /usr/local/sphinx/etc/sphinx.conf –rotate>> /var/log/sphinx/deltaindexlog
/usr/local/sphinx/bin/indexer –merge test1 test1stemmed –config /usr/local/sphinx/etc/sphinx.conf –rotate >> /var/log/sphinx/deltaindexlog
#/usr/local/sphinx/bin/searchd

每隔5分钟进行索引增量合并,每天2:30重建索引

*/5 * * * * /bin/sh /opt/shell/build_delta_index.sh > /dev/null 2>&1
30 2* * * /bin/sh /opt/shell/build_main_index.sh > /dev/null 2>&1

每周一至周六上早6点增量合并,同日重建索引

1 6 * * 1-6 /bin/sh /opt/shell/build_delta_index.sh > /dev/null 2>&1
1 6 * * 7 /bin/sh /opt/shell/build_main_index.sh > /dev/null 2>&1
  评论这张
 
阅读(439)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017