SQL Server 的全文搜索(Full-Text Search)是基於分詞的文本檢索功能,依賴於全文索引。全文索引不一樣於傳統的平衡樹(B-Tree)索引和列存儲索引,它是由數據表構成的,稱做倒轉索引(Invert Index),存儲分詞和行的惟一鍵的映射關係。倒轉索引是在建立全文索引或更新全文索引時,由SQL Server自動建立和維護的。全文索引主要包含三種分析器:分詞器(Word Breaker)、詞幹分析器(stemmer)和同義詞分析器。全文索引中存儲的數據是分詞及其位置等信息,分詞是基於特定語言的語法規則,按照特定的符號尋找詞語的邊界,把文本分解爲「單詞」,每個單詞叫作一個分詞(term);全文索引有時會提取分詞的詞幹,把詞幹的多種派生形式存儲爲單一詞幹,這個過程叫作提取詞幹;根據用戶提供的自定義同義詞列表,把相關的單詞轉換爲同義詞,這個過程叫作提取同義詞。html
生成全文索引是把用戶表中的文本數據進行分詞(Word breaker)和提取詞幹(Stemmer),並轉換同義詞(Thesaurus),過濾掉分詞中的停用詞(Stopword),最後把處理以後的數據存儲到全文索引中。把數據存儲到全文數據的過程叫作填充(Populate)或爬蟲(Crawl)進程,全文索引的更新方式能夠手動填充,自動填充,或增量填充。sql
一,全文搜索的基本組件數據庫
1,分詞器架構
分詞器(Word Breaker),顧名思義,用於分詞,它根據特定語言的語法規則,分割文本中的單詞,分詞器在拆分單詞時,還會記錄每一個分詞在字符串中的位置,分詞器把分詞,分詞的位置,文檔ID,全文索引列的序號等信息的組合,稱做標記(Token)。併發
例如,對於語句"Kitty is a cute cat",在全文索引填充時,分詞器把該語句拆分紅5個單詞:Kitty,is,a,cute,cat。less
雖然停用詞不會添加到全文索引中,可是分詞的位置會被考慮。「Kitty」 ,「cute」 和 「cat」的Position 分別是1,4 和 5。經過分詞的位置,全文搜索ide
2,停用詞函數
停用字詞列表(StopList)是非索引字詞的列表,每一個StopList中存儲的分詞都是不會用於搜索的分詞,叫作停用詞(StopWords),全文索引不會存儲停用詞,可是停用詞所佔的位置會被記錄,若是對停用詞進行contians查詢,即便基礎表(underly table)中的字段中存在該停用詞,全文索引也不會返回任何數據行。一般狀況下,停用詞(Stopword)都是經常使用的單詞,在語句中出現的頻率十分高,過濾掉停用詞,可以減小全文索引的size,提升全文查詢的性能。post
3,詞幹(Stemmer) 和 同義詞(Thesaurus)性能
同義詞詞典(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)是否須要同步到全文索引,
5,停用詞(STOPLIST)
停用詞(StopWord)也稱做噪音詞,每個全文索引都會關聯一個停用詞列表,默認狀況下,全文索引關聯的是系統停用詞(system stoplist)。全文引擎把停用詞從分詞中刪除,使全文索引不會包含停用詞。
STOPLIST [ = ] { OFF | SYSTEM | stoplist_name }
三,填充全文索引
填充全文索引也叫作爬蟲(crawl)進程,或填充(Population)進程。因爲建立或填充全文索引會消耗大量的系統(IO、內存)資源,所以儘可能選擇在系統空閒時對全文索引進行填充。在建立全文索引時,經過指定選項 CHANGE_TRACKING= MANUAL,或 CHANGE_TRACKING= OFF, NO POPULATION,新建的全文索引不會當即填充,用戶能夠選擇在系統空閒時,使用 alter fulltext index 語句執行填充操做。只有填充全文索引以後,全文索引才包含基礎表的分詞數據。
alter fulltext index on table_name start { full | incremental | update } population;
更新全文索引有三種方式:
在建立全文索引時,若是指定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等來開發功能更強大的全文搜索功能。
參考文檔:
CREATE FULLTEXT CATALOG (Transact-SQL)