全文检索

现有的数据库系统,绝大多数是以结构化数据为检索的主要目标,因此实现相对简单。比如数值检索,可以建立一张排序好的索引表,这样速度可以得到提高。但对于非结构化数据,即全文数据,要想实现检索,一般都是采用模糊查询的方式实现的。这种方式不仅速度慢,而且容易将汉字错误切分,于是产生了全文检索技术。

全文检索技术是智能信息管理的关键技术之一,其主要目的就是实现对大容量的非结构化数据的快速查找。DM实现了全文检索功能,并将其作为DM服务器的一个较独立的组件,提供更加准确的全文检索功能,较好地解决了模糊查询方式带来的问题。

18.1 全文检索概述

DM全文检索根据已有词库建立全文索引,文本查询完全在索引上进行。全文索引为在字符串数据中进行复杂的词搜索提供了有效支持。

用户可以在指定表的文本列上创建和删除全文索引。创建全文索引后全文索引未插入任何索引信息。当用户填充全文索引时,系统才将定义了全文索引的文本列的内容进行分词,并根据分词结果填充索引。用户可以在进行全文索引填充的列上使用CONTAINS谓词进行全文检索。

DM全文索引改进了原有的分词算法,为全文检索提供了更好的基础。在创建全文索引成功后,假设索引名为INDEX_NAME,则系统会自动产生如下相关的辅助表(后面简称I表,P表,N表,D表):CTI$INDEX_NAME$I,CTI$INDEX_NAME$P, CTI$INDEX_NAME$N和CTI$INDEX_NAME$D,其表结构如表18.1~18.4所示。I表主键为(WORD、FIRSTID、WID),用于保存分词结果,记录词的基本信息,通过该信息就可以快速地定位到该词的基表记录;P表主键为(PND_DOCID),用于保存基表发生的增量数据变化,用于修改全文索引时的增量填充。N表主键为(N_DOCID),用于保存原表记录rowid和新词条记录的docid的映射关系,N_DOCID是unique的;D表主键为(DOCID),保存了所有将被删除的docid,被删除的docid即将不能通过全文索引查询到。另外,如果原表有自定义聚集主键,那么P表和N表会将该自定义聚集主键列“复制”到各自表中。

表18.1 CTI$INDEX_NAME$I表结构
序号 字段名 类型 长度 精度 刻度 说明
1 WID BIGINT 8 19 0 词ID
2 WORD VARCHAR 64 64 0 词文本,相同的词重复存储
3 TYPE SMALLINT 2 5 0 词类型
4 FIRSTID BIGINT 8 19 0 开始ROWID,用于范围查找
5 LASTID BIGINT 8 19 0 结束ROWID
6 COUNT INTEGER 4 10 0 词所在的文档数(即ROWID的个数)
7 ID_INFO VARBINARY 4000 4000 0 保存所在文档所有的ROWID,连续存放
表18.2 CTI$INDEX_NAME$P表结构
序号 字段名 类型 长度 精度 刻度 说明
1 PND_ROWID BIGINT 8 19 0 原表记录的ROWID
2 PND_TYPE SMALLINT 2 5 0 INS/UPD/DEL类型
cluster key ... ... ... ... 原表上的自定义聚集主键
表18.3 CTI$INDEX_NAME$N表结构
序号 字段名 类型 长度 精度 刻度 说明
1 N_DOCID BIGINT 8 19 0 与原表ROWID
2 N_ROWID BIGINT 8 19 0 原表记录ROWID
cluster key ... ... ... ... 原表上的自定义聚集主键
表18.4 CTI$INDEX_NAME$D表结构
序号 字段名 类型 长度 精度 刻度 说明
1 DOCID BIGINT 8 19 0 待删除词的DOCID

例如对示例库bookshop中的address表的address1列创建全文索引,创建的SQL语句如下。

CREATE CONTEXT INDEX cti_address ON person.address (address1) LEXER DEFAULT_LEXER;

执行成功之后,该索引信息会保存到ctisys模式下的SYSCONTEXTINDEXES系统表中,4个自动生成的辅助表CTI$ CTI_ADDRESS$I,CTI$ CTI_ADDRESS$P, CTI$ CTI_ADDRESS$N和CTI$ CTI_ADDRESS$D信息保存在SYSOBJECTS系统表中。这四张表由服务器自动维护,用户可以查询,但不可以直接修改表内容。

DM全文索引创建的过程中,用户可以为分词器定义分词参数,即控制分词器分词的数量,包括5种分词参数:

  1. CHINESE_LEXER,中文最少分词;
  2. CHINESE_VGRAM_LEXER,机械双字分词;
  3. CHINESE_FP_LEXER,中文最多分词;
  4. ENGLISH_LEXER,英文分词;
  5. DEFAULT_LEXER,默认分词,为中文最少分词。

指定中文分词参数可以切分英文,但是指定英文分词参数不可以切分中文,所以使用英文分词算法对中文文本进行分词时,分词结果将为空。

中文最多分词可以将存在二义性的词划分出来,例如“和服装”会生成“和”、“和服”、“服”、“服装”和“装”。那么在查询其中任何一个词的时候都可以检索到该文本。与之相对应的是最少分词,其消除了存在二义性的词,即前面举例的文本分词的结果为“和”、“服装”两个词,这样可以减少大量冗余词的存储,能进行更准确的匹配。英文分词即根据英文分隔符的分词,对超过32个字节的英文单词进行了拆分处理。

全文检索的中文分词依赖系统词库,该词库是只读的,不允许修改。

18.2 创建全文索引

在DM中,全文索引必须在基表上定义,而不能在系统表、视图、临时表、列存储表、外部表上定义。同一列只能创建一个全文索引。DM定义全文索引时,不需要在表上先建立主关键字索引。创建全文索引的列类型可为CHAR、CHARACTER、VARCHAR、VARCHAR2、LONGVARCHAR、TEXT或CLOB,例如上节对address表创建的全文索引列为VARCHAR 类型。DM的全文索引现只支持简体中文、英文语言。较为详细的语法介绍可参考《DM8_SQL语言使用手册》。

18.3 更新全文索引

全文索引本质是借助辅助关系表存储索引数据。当对基表执行数据更新操作后,数据并不会立刻填充到辅助表中,需要用户主动同步数据用以更新全文索引,未同步到辅助表中的记录将无法通过全文索引查询到结果。

全文索引的更新包括两种方式:完全更新和增量更新。

  1. 完全更新

删除原有的全文索引,对基表进行全表扫描,逐一重构索引信息。在创建全文索引成功后,需完完全更新全文索引才可以执行有效的全文检索。完全更新全文索引没有次数限制,用户可以根据需要在增量更新或者是完全更新失败以及发生系统故障后都可以执行完全更新全文索引。另外,完全更新由于完全丢弃辅助表已有数据,重新开始对基表数据进行分词并填充到辅助表,因此服务器允许这种情况下更改分词算法。

例如执行如下SQL可以对address表的全文索引进行完全更新:

  ALTER CONTEXT INDEX cti_address ON person.address REBUILD;
  1. 增量更新

在上一次完全更新之后,表数据发生了变化,就可以使用增量更新来更新索引。增量更新只对新发生改变的数据进行重新分词生成索引信息,所以其代价是较小的。此时,也可以使用完全更新达到同样的更新索引的效果,但代价较大。

对全文索引的基表进行数据的增删改操作时,会将该数据的操作类型和ROWID信息保存到CTI$INDEX_NAME$P表中。

例如执行如下SQL可以对address表的全文索引进行增量更新:

  ALTER CONTEXT INDEX cti_address ON person.address INCREMENT;

DM在执行更新全文索引的过程中如果在更新过程中发生任何错误,服务器将回滚到最近一次事务提交成功时的状态。

增量更新还有一种特殊情况,实时自动增量更新,即在创建全文索引时指定同步方式为"SYNC TRANSACTION",此种方式不需要用户手动更新全文索引,而是在每次事务提交时由服务器自动完成增量更新动作。

18.4 执行全文检索

全文检索采用的分词算法与全文索引数据同步时采用的分词算法保持一致,用户可以通过系统表"CTISYS.SYSCONTEXTINDEXES"查询"WSEG_TYPE"得知全文索引的分词算法。全文检索首先对查询关键字或者句子进行分词,并将分词结果在I表中进行匹配,然后将匹配结果返回。DM8支持对中英文关键字或者句子的布尔查询。

全文检索支持的检索类型有:

  1. 支持英文单词的检索(单词不区分大小写);
  2. 支持全角英文的检索;
  3. 支持简体中文词语的检索;
  4. 支持常见单个汉字词的检索;
  5. 支持简体中文长句子的检索;
  6. 支持中英文混合的检索。

全文检索支持的检索方式有:

  1. 在CONTAINS谓词内支持AND、OR和AND NOT的短语查询组合条件,例如查询address表中地址在洪山区太阳城的记录:
  SELECT * FROM person.address WHERE CONTAINS(address1, '洪山区' AND '太阳城');
  1. 全文检索支持单词或者句子的检索,例如查询address表中地址在江汉区发展大道的记录:
  SELECT * FROM person.address WHERE CONTAINS(address1, '江汉区发展大道');
  1. 不支持模糊方式的全文检索,例如查询“江汉区*”。
  2. 检索条件子句可以和其他子句共同组成 WHERE的检索条件,例如查询address表中地址在武汉市洪山区的记录。
  SELECT * FROM person.address WHERE CONTAINS(address1, '洪山区') AND city LIKE '%武汉市%';

全文查询

图18.1 全文查询

如上图所示,DM全文检索时对查询的文本做了预处理,首先根据词文本进行最少分词,并依据词频信息找出查询关键字,然后对这些关键字进行优先级排序,这样可以在第一次检索时找出所需文本的最小结果集,然后在该结果集的基础上再进行依次筛选,最终获得查询文本,这样能较大地提高查询性能。

18.5 删除全文索引

删除全文索引时,数据字典中相应的索引信息和全文索引内容都会被删除。删除索引有两种方式:使用语句删除和当模式对象发生改变时系统自动删除。第一种方式仅删除指定的基表的全文索引信息;第二种方式会删除模式对象(如数据库、基表等)上的所有全文索引。全文索引一旦删除就不能回滚,基于该表的全文检索就会失败,只能通过重新构建获得新的全文索引。例如删除address表,则会将表的全文索引cti_address也删除,包括与全文索引相关的动态表。

  DROP CONTEXT INDEX cti_address ON person.address;

删除成功后,查询ctisys模式下的SYSCONTEXTINDEXES系统表会发现cti_address全文索引已删除。

微信扫码
分享文档
扫一扫
联系客服