zoukankan      html  css  js  c++  java
  • Sql Server 数据库建全文搜索

    摘自:https://www.cnblogs.com/ljhdo/p/5041605.html

    SQL Server 的全文搜索(Full-Text Search)是基于分词的文本检索功能,依赖于全文索引。全文索引不同于传统的平衡树(B-Tree)索引和列存储索引,它是由数据表构成的,称作倒转索引(Invert Index),存储分词和行的唯一键的映射关系。倒转索引是在创建全文索引或更新全文索引时,由SQL Server自动创建和维护的。全文索引主要包含三种分析器:分词器(Word Breaker)、词干分析器(stemmer)和同义词分析器。全文索引中存储的数据是分词及其位置等信息,分词是基于特定语言的语法规则,按照特定的符号寻找词语的边界,把文本分解为“单词”,每一个单词叫做一个分词(term);全文索引有时会提取分词的词干,把词干的多种派生形式存储为单一词干,这个过程叫做提取词干;根据用户提供的自定义同义词列表,把相关的单词转换为同义词,这个过程叫做提取同义词。

    生成全文索引是把用户表中的文本数据进行分词(Word breaker)和提取词干(Stemmer),并转换同义词(Thesaurus),过滤掉分词中的停用词(Stopword),最后把处理之后的数据存储到全文索引中。把数据存储到全文数据的过程叫做填充(Populate)或爬虫(Crawl)进程,全文索引的更新方式可以手动填充,自动填充,或增量填充。

    一,全文搜索的基本组件

    1,分词器

    分词器(Word Breaker),顾名思义,用于分词,它根据特定语言的语法规则,分割文本中的单词,分词器在拆分单词时,还会记录每个分词在字符串中的位置,分词器把分词,分词的位置,文档ID,全文索引列的序号等信息的组合,称作标记(Token)。

    例如,对于语句"Kitty is a cute cat",在全文索引填充时,分词器把该语句拆分成5个单词:Kitty,is,a,cute,cat。 如果使用默认的停用词列表,那么“is”,“a”都是停用词,全文索引会把停用词丢失,只存储分词:Kitty,cute,cat。

    虽然停用词不会添加到全文索引中,但是分词的位置会被考虑。“Kitty” ,“cute” 和  “cat”的Position 分别是1,4 和 5。通过分词的位置,全文搜索能够进行位置相邻的查询:两个分词之间最多存在N个单词。例如,查询语句:contains(column, 'near((Kitty,cate),3)') 的含义是存在两个word,“Kitty” 和 “cate”,其最大距离是3,从column中查询出包含该条件的phrase,字符串“Kitty is a cute cat.”  满足匹配条件。

    2,停用词

    停用字词列表(StopList)是非索引字词的列表,每个StopList中存储的分词都是不会用于搜索的分词,叫做停用词(StopWords),全文索引不会存储停用词,但是停用词所占的位置会被记录,如果对停用词进行contians查询,即使基础表(underly table)中的字段中存在该停用词,全文索引也不会返回任何数据行。通常情况下,停用词(Stopword)都是常用的单词,在语句中出现的频率十分高,过滤掉停用词,能够减少全文索引的size,提高全文查询的性能。

    3,词干Stemmer) 和 同义词(Thesaurus)

    词干抽取器(Stemmer )用于把同源单词转换为其根形式,能够转换为相同根形式的单词是同源的。例如,对于单词run,有很多同源的单词:

    • ran
    • running
    • runs
    • runner (perhaps)

    同义词词典(Thesaurus)是一个XML文件,用于定义特定语言的同义词列表,例如,我们可以设置“Author” , “Writer” ,“journalist”是同义词。

    二,创建全文索引

    创建全文索引之前,必须创建全文目录(Full-Text Catalog),全文目录用于组织全文索引,是全文索引的容器。每一个全文索引必须属于一个全文目录。全文目录是个逻辑结构,跟数据库的架构(Schema)相同,根据全文索引的存储位置无关。

    create fulltext catalog catalog_test
    as default;

    为了创建全文索引,基础表上必须存在一个唯一的(unique)、单列的(single-column)、非空的(non-nullable)的索引,全文引擎使用该索引把基础表上的每行数据映射唯一索引键上,倒转索引存储的就是该索引键和分词之间的映射关系。

    create unique index uidx_dbLogID 
    on [dbo].[DatabaseLog]
    ([DatabaseLogID]);

    每个表只能创建一个全文索引,创建全文索引时,必须考虑全文索引存储的文件组,全文索引关联的停用词列表,全文索引的更新方式,以及跟文本关联的语言,全文索引列必须是文本字段,例如:

    复制代码
    create fulltext index 
    on [dbo].[DatabaseLog]
    (
    [tsql] language 1033
    )
    key index ui_dbLogID
    on (catalog_test,filegroup [primary]) 
    with(change_tracking=off ,no population ,stoplist=system);
    复制代码

    1,语言(language)

    选项 language 是可选的,用于指定列级别的语言,该选项的值可以是语言的名称或LCID,如果没有指定language选项,那么使用SQL Server实例的默认语言。从系统视图 sys.fulltext_languages (Transact-SQL)中查看系统支持的语言及其对应的LCID 和名称。

    2,全文目录(fulltext_catalog)

    选项fulltext_catalog_name 用于指定全文索引的分组,

    3,文件组(filegroup)

    选项 filegroup filegroup_name 用于指定全文索引存储的文件组,如果没有指定文件组,那么全文索引和基础表存储在相同的文件组中。由于更新全文索引是IO密集型操作,因此,为了更快的更新全文索引,最好把全文索引存储在不同于基础表的的物理硬盘或文件组上,以达到最大的IO并发。

    4,填充全文索引的方式

    和普通的索引相同,当基础表数据更新时,全文索引必须自动更新,这是系统默认的行为,也可以配置手动更新全文索引,或者间隔特定的时间点自动更新全文索引。

    选项CHANGE_TRACKING 用于指定跟全文索引列相关的数据更新(Update,Delete,或Insert)是否需要同步到全文索引,

    • CHANGE_TRACKING = MANUAL :手动更新
    • CHANGE_TRACKING =AUTO:自动更新,默认设置,当基础表数据变化时,全文索引自动更新,
    • CHANGE_TRACKING =OFF , NO POPULATION:不更新,指定选项NO POPULATION,表明在创建全文索引之后,SQL Server不会更新(populate)全文索引;如果未指定选项NO POPULATION,在创建全文索引之后,SQL Server更新全文索引。

    5,停用词(STOPLIST)

    停用词(StopWord)也称作噪音词,每一个全文索引都会关联一个停用词列表,默认情况下,全文索引关联的是系统停用词(system stoplist)。全文引擎把停用词从分词中删除,使全文索引不会包含停用词。

    STOPLIST [ = ] { OFF | SYSTEM | stoplist_name }  

    三,填充全文索引

    填充全文索引也叫做爬虫(crawl)进程,或填充(Population)进程。由于创建或填充全文索引会消耗大量的系统(IO、内存)资源,因此尽量选择在系统空闲时对全文索引进行填充。在创建全文索引时,通过指定选项 CHANGE_TRACKINGMANUAL,或 CHANGE_TRACKINGOFF, NO POPULATION新建的全文索引不会立即填充,用户可以选择在系统空闲时,使用 alter fulltext index 语句执行填充操作。只有填充全文索引之后,全文索引才包含基础表的分词数据。

    alter fulltext index 
    on table_name
    start { full | incremental | update } population;

    更新全文索引有三种方式:

    • FULL POPULATION:全部填充,从基础表中获取每一行,重新编入全文索引;
    • INCREMENTAL POPULATION:增量填充,前提是基础表中包含timestamp字段,从上一次填充之后,只把更新之后的数据编入全文索引;
    • UPDATE POPULATION:更新填充,从上一次填充之后执行更新(insert、update、或delete)操作的数据行重新编入索引;

    在创建全文索引时,如果指定CHANGE_TRACKING=AUTO   或   CHANGE_TRACKING=  OFF , 那么新建的全文索引会立即开始填充进程。 

    四,使用 contains 谓词查询全文索引

    如果想要在查询中使用全文索引,通常使用CONTAINS谓词来调用全文索引,实现比LIKE关键字更复杂的文本匹配查询,而LIKE关键字是模糊匹配,不会调用全文索引。

    例如,利用contains谓词执行单个分词的完全匹配查询:

    select [tsql] 
    from [dbo].[DatabaseLog] 
    where contains([tsql], 'searchword', language 1033);

    全文查询跟Like相比,速度更快,支持的搜索功能更复杂,使用contains谓词,不仅能够执行分词的完全匹配或分词的前缀匹配查询,还能够执行基于词根的查询,基于自定义同义词的查询,基于距离和顺序的相邻分词查询。但是,和Like 相比,contains谓词不能进行后缀匹配查询。

    contains谓词返回的结果是布尔值,如果全文索引列中包含指定的关键字或查找模式(pattern),返回TRUE;否则,返回FALSE。

    contains谓词支持word查询和短语查询,word是指单个分词,短语(phrase)是由多个word和间隔的空格组成的,对于短语,必须使用双引号,将多个word组成一个短语。

    1,逻辑组合查询

    使用and ,and not, 或 or 逻辑运算符 匹配多个word 或 多个phrase

    CONTAINS(Name, '"Mountain" OR "Road" ')
    CONTAINS(Name, ' Mountain OR Road ')

    2,前缀查询

    使用contains谓词进行前缀匹配,和like 'prefix%'功能相同,只不过contains谓词使用“*”作为通配符,“*”匹配0,1或多个字符,前缀匹配的写法是:'"prefix*"',全文索引只能执行前缀匹配。

    CONTAINS(Name, ' "Chain*" ')
    CONTAINS(Name, '"chain*" OR "full*"')

    3,查询同义词(thesaurus)或词干(stemmer)

    Stemmer(词干),例如,根据语法规程,英语的动词 根据数(单数,复数),人称,时态的不同而存在不同的变化形式,这些单词都是同源的。

    CONTAINS(Description, ' FORMSOF (INFLECTIONAL, ride) ')

    THESAURUS (同义词),需要导入XML进行配置,SQL Server 提供一个默认的Thesaurus file,是Empty的。如果在Thesaurus file 配置“Author”,“Writer”,“journalist” 是同义词,在使用fulltext index查询时,只要满足任意一个同义词,都匹配成功。

    CONTAINS(Description, ' FORMSOF (THESAURUS, author) ')

    4,距离查询

    使用 near 函数,查询匹配相邻分词的数据行,near函数的定义如下,用于需要在查询模式中指定距离查询的查询模式:

    NEAR ( ( { <simple_term> | <prefix_term> } [ ,…n ] )  [, <maximum_distance> ] [, <match_order> ] ) 

    例如:使用Near 函数指定相邻分词的距离和匹配顺序,near((term1,term2,term3),5)表示任意两个term之间的距离不能超过5, near((term1,term2,term3),5,true),表示任意两个term的距离不能超过5,并且按照 term1,term2,term3的顺序存在于字符串中。

    复制代码
    --regardless of the intervening distance and regardless of order
    CONTAINS(column_name, 'NEAR(term1,"term3 term4")')
    --searches for "AA" and "BB", in either order, within a maximum distance of five
    CONTAINS(column_name, 'NEAR((AA,BB),5)')
    --in the specified order with regardless of the distance
    CONTAINS(column_name, 'NEAR ((Monday, Tuesday, Wednesday), MAX, TRUE)')
    复制代码

    对于 near((term1,term2,term3),5,true),term1 和 term5之间最多存在5个term,不包括内部的搜索分词,“term2”,例如:

    CONTAINS(column_name, 'NEAR((AA,BB,CC),5)')

    这个查询会匹配下面的文本,注意,内部的搜索分词CC没有计算距离:

    BB one two CC three four five AA

    例如,在原文本中,分词bike和control的最大距离不能超过10,分词bike必须出现在分词control的前面:

    CONTAINS(Comments , 'NEAR((bike,control), 10, TRUE)')

    SQL Server提供的全文搜索功能,比LIKE关键字丰富,具备初级的全文搜索功能,速度快,维护简单,缺点是,全文搜索功能非常有限,在实际的开发中,可以配合开源的全文搜索引擎,例如,Solr,Elasticsearch等来开发功能更强大的全文搜索功能。

    摘自:https://www.cnblogs.com/ljhdo/p/5041605.html

  • 相关阅读:
    ant 软件包不存在报错
    在 Internet Explorer 中使用 Windows 窗体控件
    智能客户端
    Back to the Future with Smart Clients
    "Automation 服务器不能创建对象" 的解决方案
    Top 10 Reasons for Developers to Create Smart Clients
    Updater Application Block for .NET
    Smart Client Application Model and the .NET Framework 1.1
    Security and Versioning Models in the Windows Forms Engine Help You Create and Deploy Smart Clients
    智能客户端技术总结(二)
  • 原文地址:https://www.cnblogs.com/shuaichao/p/12175354.html
Copyright © 2011-2022 走看看