作者: eaglet
转载需注明出处
对于大部分应用来说,全文搜索功能只是应用的部分功能而非全部功能,很多系统在设计之初往往缺乏全文搜索方面的设计,搜索功能多是用数据库的 like 语句来实现,随着系统容量的增大和用户数量的增加,这种 like 无论从性能还是功能方面都无法满足站内搜索的需要。HubbleDotNet 为这部分用户提供了松耦合度的系统集成方案,用户只需一小时不到时间就可以实现现有系统的全文搜索功能的后台部分,无需对现有数据库表结构做任何改动,无需编写大量代码。其中自动和现有表数据同步是这个解决方案中的重要一环。本文重点介绍如何设置,以完成全文索引和现有数据表的数据同步。
适用版本:HubbleDotNet 0.9.6.0
项目首页:http://www.hubbledotnet.com/
下载地址:http://hubbledotnet.codeplex.com/
适用范围:本文适用于被动模式索引的两种模式 Append Only 和 Updatable
功能简介:
针对现有数据表进行索引,只能使用被动模式建立索引
详见:为数据库现有表或视图建立全文索引(一) Append Only 模式 和 HubbleDotNet 开源全文搜索数据库项目--为数据库现有表建立全文索引(二) Updatable 模式
在0.9 版本以前,被动模式索引(IndexOnly=true) 是无法实现自动同步的,由于HubbleDotNet 全文索引和数据库之间缺乏触发机制,数据库中数据表的增加,更改和删除无法被hubbledotnet 获知,用户必须手工方式和数据库同步,详见:通过程序和现有表或视图同步 。
0.9.6.0 版本以后,HubbleDotNet 提供了自动和数据库现有表同步的机制,用户只要调用 Hubble.SqlClient 中提供的一个类,就可以触发HubbleDotNet 和数据库进行同步,用户可以根据自己的实际情况确定何时触发同步,同步周期是多少。HubbleDotNet 暂时没有提供自动的同步任务,这是因为目前这方面需求还不是很明确,不同项目可能对同步的触发时间和同步周期有不同的要求,比如有的用户可能希望夜里才触发同步,有的用户可能希望每5分钟就同步一次等等。由于需求差异较大,HubbleDotNet 目前版本暂时确定把这个触发同步的主动权交给用户,当然这个触发同步操作是非常简单的,只需3行代码就可以完成。
下面重点谈谈如何设置自动同步
Append only 模式
Append only 模式下,自动同步设置非常简单,只需要在Table Info 中将 TableSynchronization 设置为ture。就可以了。
同步流程
如上图所示,用户在执行Hubble.SqlClient 提供的类TableSynchronization 的Synchronize方法后,会先判断目前是否正在同步,如果正在同步,将返回False,用户可以在等待本次同步完成后,再执行这个方法触发同步。触发同步成功后,HubbleDotNet 的Server 端将扫描数据库中未建立索引的新增记录,对这些记录进行索引,索引完成后,按照用户指定的优化方案对索引进行优化。
HubbleDotNet 的查询分析器(QueryAnalyzer) 提供了同步数据调用的界面,这个也作为同步数据的示例代码供使用者参考。
下面给出一个简单的例子,表结构如下:
同步设置如下:
执行同步操作
点 Start 开始同步
参数说明:
Step: 表示同步时每次从数据库读取多少条记录。假如设置为5000,待同步的记录为12000条,则开始同步后,Server 端会进行3次批量索引,前两次每次批量索引5000条,最后一次2000条。批量索引完所有待同步的记录后开始优化。如果搞不清这个地方是干什么的,请保持这个数值不变,5000是我测试过的一个比较理想的数值。
Optimize option:指明优化策略。默认按最小方式优化。如果索引文件较大,按最小方式优化会比较耗时,可以选择按这种方式优化,即 Middle 方式。
点 Start 后,同步操作就开始执行,你可以点 Stop 去停止同步。
同步完成
Updatable 模式
Updatable 模式即原来的 Append, update, delete 模式。这种模式由于存在删除和更改操作,同步工作会比较复杂一些。我们需要建立一个辅助表来实现
下面以具体例子来说明:
要索引的表结构
创建辅助触发表 (TriggerTable)
create table HBTrigger_EnglishNews
(
Serial bigint identity(1,1) not null primary key,
Id int not null,
Opr char(16),
Fields nvarchar(4000) null,
)
表结构如上所述,辅助触发表必须遵照这个表结构创建,表名可以随便设置。
Id 字段对于索引表中Docid Field 这个字段,这里对于索引表中的Id 字段。如果索引表中DocId Field 字段是 bigint ,这里需要指定为bigin。
Opr 字段告诉hubbledotnet 改动是更新,还是删除。
Fields 字段只有更新(Update)时有效,告诉hubbledotnet 更新操作修改了哪几个字段。
如果你的数据库不是SQL SERVER ,请按照这个表结构创建对应数据库的辅助触发表。
注意:辅助触发表必须和主表在同一个数据库中。 由于要用到对Opr 和 Serial 同时查询,所以建议按上述SQL建一个复合索引。
设置 TableInfo
按下图所示设置 TableSynchronization 设置为ture 并指定辅助触发表的表名。
创建一个更新触发器
如果你的现有表有更新操作,你就必须创建更新触发器,数据更新时,更新触发器会把哪些Id,哪些字段更新的信息写入到辅助触发表中。
凡是Tokenized 和 Untokenized 类型的字段都需要在更新触发器中设置,更新触发器的示例代码如下:
Create Trigger HBTrigger_EnglishNews_Update On EnglishNews for Update As DECLARE @updateFields nvarchar(4000) set @updateFields = '' if Update(GroupId) begin set @updateFields = @updateFields + 'GroupId,' end if Update(SiteId) begin set @updateFields = @updateFields + 'SiteId,' end if Update(Time) begin set @updateFields = @updateFields + 'Time,' end if Update(Title) begin set @updateFields = @updateFields + 'Title,' end if Update(Content) begin set @updateFields = @updateFields + 'Content,' end if @updateFields <> '' begin insert into HBTrigger_EnglishNews select id, 'Update', @updateFields from Inserted end
其中EnglishNews 是主表的表名,HBTrigger_EnglishNews 是辅助触发表的表名。
GroupId, SiteId 等等是主表中 untokenized 和 tokenized 字段,这个触发器的工作就是记录表更新时哪些字段发生了变化。
在对具体表实现这个触发器时不可以照搬这个代码,需要根据具体表的索引字段对Time,Title, Content 等等这些地方进行修改。
同样如果数据库不是 SQL SERVER ,请按照对应数据库的触发器语法建立触发器。
创建一个删除触发器
如果你的现有表有删除操作,你就必须创建删除触发器,数据被删除时,删除触发器会把哪些被删除的Id信息写入到辅助触发表中。
Create Trigger HBTrigger_EnglishNews_Delete
On EnglishNews
for Delete
As
insert into HBTrigger_EnglishNews select id, 'Delete', '' from Deleted
增量的同步
对于增量(Insert)数据的同步,Updatable 和 Append only 的方式类似,不需要通过触发器来实现,所以如果你的表频繁增量,你完全没有比较担心触发器对数据插入性能的影响,因为增量时不会触发任何触发器。
执行同步操作
点 Start 开始同步
参数说明:
Step: 表示同步时每次从数据库读取多少条记录。假如设置为5000,待同步的记录为12000条,则开始同步后,Server 端会进行3次批量索引,前两次每次批量索引5000条,最后一次2000条。批量索引完所有待同步的记录后开始优化。如果搞不清这个地方是干什么的,请保持这个数值不变,5000是我测试过的一个比较理想的数值。
Optimize option:指明优化策略。默认按最小方式优化。如果索引文件较大,按最小方式优化会比较耗时,可以选择按这种方式优化,即 Middle 方式。
点 Start 后,同步操作就开始执行,你可以点 Stop 去停止同步。
同步完成
同步流程
触发器对性能的影响
触发器只对更改和删除操作的性能造成影响,由于触发器只记录更改或删除的ID号和更改字段,而不记录更改的实际内容,所以即使有影响,这个影响也是有限的。如果某些应用中,使用者觉得这种影响无法接受,那么只能参照这篇文章通过程序和现有表或视图同步 通过程序手动同步数据了。
通过后台任务自动定时同步
你可以有两种方式来触发同步,一种是通过 HubbleDotNet 的后台任务自动来实现定时同步,见下面文章
你也可以通过自己写程序来触发同步操作,下面是程序调用方法
程序调用
可参考 QueryAnalyzer 下的 FormTableSynchronization.cs
引用 Hubble.SQLClient
TableSynchronization 的实例化
TableSynchronization _TableSync;
TableSynchronization.OptimizeOption option = TableSynchronization.OptimizeOption.Minimum;
int step = (int)numericUpDownStep.Value;
HubbleConnection conn = new HubbleConnection(connectString);
conn.Open();
_TableSync = new TableSynchronization(DataAccess.Conn, TableName, step, option);
触发同步:
_TableSync.Synchronize();
这个函数返回True ,表示触发同步成功。
获取同步进度:
double progress = _TableSync.GetProgress();
这个函数会返回同步进度的百分比,如果返回 100, 表示同步完成。
停止同步
_TableSync.Stop();
如果当前表正在同步,这些这个函数,同步操作将被终止。