SQL Server 使用全文索引進行頁面搜索


標簽:SQL SERVER/MSSQL SERVER/數據庫/DBA/全文索引

概述  

全文引擎使用全文索引中的信息來編譯可快速搜索表中的特定詞或詞組的全文查詢。全文索引將有關重要的詞及其位置的信息存儲在數據庫表的一列或多列中。全文索引是一種特殊類型的基於標記的功能性索引,它是由 SQL Server 全文引擎生成和維護的。生成全文索引的過程不同於生成其他類型的索引。全文引擎並非基於特定行中存儲的值來構造 B 樹結構,而是基於要編制索引的文本中的各個標記來生成倒排、堆積且壓縮的索引結構。在 SQL Server 2008 中,全文索引大小僅受運行 SQL Server 實例的計算機的可用內存資源限制。

最近遇到一個需求,需要在一個100萬的表中通過關鍵字對一個大型字符字段進行檢索,類似於百度搜索引擎的搜索,查詢出所有包含關鍵字的數據並進行分頁處理,並且將匹配度最高的數據排在第一位,要求查詢響應時間控制在1秒左右。

 測試環境:SQL Server 2008 r2

 

目錄

全文索引概念

  • 全文索引是針對數據表,只能對表創建全文索引,不能對數據庫創建全文索引。
  • 每個數據庫可以不包含全文目錄或包含多個全文目錄,一個全文目錄可以包含多個全文索引,但一個全文索引只能用於構成一個全文目錄。
  • 一個數據表只能創建一個全文索引,一個全文索引可以包含多個字段。
  • 創建全文索引的表必須要有一個唯一的非空索引,並且這個唯一的非空的索引只能是一個字段,不能是組合字段。
  • 每個表只允許有一個全文索引。若要對某個表創建全文索引,該表必須具有一個唯一且非 Null 的列。您可以對以下類型的列創建全文索引:charvarcharncharnvarchartextntextimagexmlvarbinaryvarbinary(max),從而可對這些列進行全文搜索。對數據類型為 varbinaryvarbinary(max)imagexml 的列創建全文索引需要您指定類型列。類型列是用來存儲每行中文檔的文件擴展名(.doc、.pdf、xls 等)的表列。

 

全文搜索由全文引擎提供支持。全文引擎有兩個角色:索引支持和查詢支持。

全文搜索體系結構:

從 SQL Server 2008 開始,全文搜索體系結構包括以下進程:

  • SQL Server 進程 (sqlservr.exe)
  • 篩選器后台程序宿主進程 (fdhost.exe)。

SQL Server 進程組件:

    • 用戶表
      這些表包含要進行全文索引的數據。

    • 全文收集器
      全文收集器使用全文爬網線程。它負責計划和驅動對全文索引的填充,並負責監視全文目錄。

    • 同義詞庫文件
      這些文件包含搜索項的同義詞。

    • 非索引字表對象
      非索引字表對象包含對搜索無用的常見詞列表。

    • SQL Server 查詢處理器
      查詢處理器編譯並執行 SQL 查詢。如果 SQL 查詢包含全文搜索查詢,則在編譯和執行期間該查詢都會發送到全文引擎。查詢結果將與全文索引相匹配。

    • 全文引擎
      SQL Server 中的全文引擎現已與查詢處理器完全集成。全文引擎編譯和執行全文查詢。作為查詢執行的一部分,全文引擎可能會接收來自同義詞庫和非索引字表的輸入。在 SQL Server 2008 和更高版本中,SQL Server 的全文引擎在 SQL Server 查詢處理器內部運行。

    • 索引編寫器(索引器)
      索引編寫器生成用於存儲索引標記的結構。

    • 篩選器后台程序管理器
      篩選器后台程序管理器負責監視全文引擎篩選器后台程序宿主的狀態。

篩選器后台程序宿主組件:

篩選器后台程序宿主是一個由全文引擎啟動的進程。它運行下列全文搜索組件,這些組件負責對表中的數據進行訪問、篩選和斷字,同時還負責對查詢輸入進行斷字和提取詞干:

篩選器后台程序宿主的組件如下:

    • 協議處理程序
      此組件從內存中取出數據,以進行進一步的處理,並訪問指定數據庫的用戶表中的數據。其職責之一是從全文索引列中收集數據,並將所收集的數據傳遞給篩選器后台程序宿主,從而由該宿主根據需要應用篩選和斷字符。

    • 篩選器
      某些數據類型需要篩選,然后才能為文檔中的數據(包括 varbinaryvarbinary(max)imagexml 列中的數據)創建全文索引。給定文檔采用何種篩選器取決於文檔類型。例如,Microsoft Word (.doc) 文檔、Microsoft Excel (.xls) 文檔和 XML (.xml) 文檔分別使用不同的篩選器。然后,篩選器從文檔中提取文本塊區,刪除嵌入的格式並保留文本,如有可能的話也會保留有關文本位置的信息。結果將以文本化信息流的形式出現。

    • 斷字符和詞干分析器
      斷字符是特定於語言的組件,它根據給定語言的詞匯規則查找詞邊界(“斷字”)。每個斷字符都與用於組合動詞及執行變形擴展的特定於語言的詞干分析器組件相關聯。在創建索引時,篩選器后台程序宿主使用斷字符和詞干分析器來對給定表列中的文本數據執行語言分析。與全文索引中的表列相關的語言將決定為列創建索引時要使用的斷字符和詞干分析器。

 

創建全文索引

啟動服務

 在SQL Server配置管理工具中,找到'SQL Full-text Filter Daemon Launcher'服務用本地用戶啟動。

創建全文目錄

 打開需要創建全文目錄的數據庫-存儲-全文目錄-右鍵新建全文目錄

用語句創建全文目錄 

CREATE FULLTEXT CATALOG [FD_HouseSearch]WITH ACCENT_SENSITIVITY = ON
AS DEFAULT
AUTHORIZATION [dbo]

創建全文索引

 右鍵需要創建全文索引的表-全文索引-定義全文索引

1.全文索引必須要有一個唯一非空索引,這里選擇主鍵。

2.選擇需要全文搜索的列,並且選擇斷字符語言,因為該字段主要用來存儲中文,所以這里也選擇了簡體中文。

斷字符:斷字符用來對全文搜索數據進行語言分析,查找單詞的邊界,也就是怎樣將一段很長的內容拆分成日常的詞語或字。例如“全文搜索”,可能會斷字成“全文”、‘搜索’、‘全’、‘文’、‘搜’、‘索’等符合中國人正常的習慣的詞或字。

3.選擇跟蹤方式,這里選擇自動跟蹤,就是表發生更改時自動填充索引。

4.選擇全文目錄、索引文件、非索引字表

非索引字表:在剛才的斷字中講了怎樣斷字,這里就是將斷的字保存在一張表中,該處選擇系統默認的非索引字表.

 

----查詢斷字表
SELECT TOP 1000 * FROM sys.dm_fts_index_keywords(db_id(''), object_id(''))

 

5.填充計划

可以新建填充計划來填充全文索引,填充計划可以是完全填充、增量填充、更新填充。

用語句創建全文索引

--語句少了很多默認參數,其它就按系統默認即可
CREATE
FULLTEXT INDEX ON dbo.Housetest (Description ) KEY INDEX PK_Housetest ON FD_HouseSearch

 

全文謂詞

全文查詢使用全文謂詞(CONTAINS 和 FREETEXT)以及全文函數(CONTAINSTABLE 和 FREETEXTTABLE)。它們支持復雜的 Transact-SQL 語法,這種語法支持各種形式的查詢詞。若要編寫全文查詢,必須了解何時以及如何使用這些謂詞和函數。

CONTAINS 謂詞可以搜索:

    • 詞或短語。
    • 詞或短語的前綴。
    • 與另一個詞相鄰的詞。
    • 由另一個詞的詞形變化而生成的詞(例如,drive 一詞是 drives、drove、driving 和 driven 詞形變化的詞干)。
    • 使用同義詞庫確定的另一個詞的同義詞(例如,metal 一詞可能有 aluminum 和 steel 等同義詞)。
---下面的示例將查找包含 "Mountain"
USE
AdventureWorks2008R2; GO SELECT Name, ListPrice FROM Production.Product WHERE CONTAINS(Name, 'Mountain'); GO

--下面的示例將查找包含 "Mountain"或 "Road"
USE AdventureWorks2008R2;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Mountain" OR "Road" ')
GO
---下面的示例返回的所有產品名稱中,其 Name 列中至少有一個詞以前輟 chain 開頭
USE AdventureWorks2008R2;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Chain*" ');
GO
 
           

FREETEXT謂詞的用法這里就不做解釋了!

需求

 現在來說一下我最近的需求,表數據100萬條,數據這里就不弄出來了,只把方案說一下,title類似於文章的標題,Description是內容也是全文索引字段

方案1:like,測試后果斷排除

方案2:直接使用全文搜索進行,排序消耗大。

方案3:由於查詢需要對Title進行排序,建Title字段的倒序索引包含其它字段,最后選擇該方案(創建Title字段的倒序索引很重要)。

--給出部分字段
CREATE
TABLE [dbo].[Housetest]( [ID] [int] IDENTITY(1,1) NOT NULL, [Title] [varchar](200) NULL, [Description] [nvarchar](max) NOT NULL, [IsOnline] [tinyint] NOT NULL, CONSTRAINT [PK_Housetest] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

創建索引

CREATE INDEX IX_Housetest ON Housetest
(Title DESC
)
INCLUDE
(ID,
Description,
IsOnline
)

查詢Description包含“美園”,並且如果Title是“美園”則排在第一位,並且以分頁的形式顯示,每頁20條記錄。

select  * from (SELECT  ROW_NUMBER() OVER(Order by (case when Title='美園' Then 1 Else 0 End) desc ) as RowsNumber,ID,Title,Description
  From Housetest Where contains(Description,'美園') and IsOnline=1) tab1 where RowsNumber between 1 and 20

 

總結

大家不要拿這個與搜索引擎做對比,肯定是沒法比的,因為我這里只需要解決需求就好,所以方案適合我目前的需求。 

全文索引功能類似於百度的搜索引擎,但是百度這類搜索引擎有自己的數據字典,在關鍵字表中對關鍵字進行排序,保存關鍵字對應的 文檔id,一個文檔只會保留很少的關鍵字,就跟平時寫文章要添加標簽一樣,一般一篇文章就幾個標簽,當搜索的時候匹配的速度就會非常快,這就需要一個很完善的數據字典表。

全文搜索還有另外的一個功能就是FileStream,需要添加文件流,在服務中啟用該功能可以在字段中將文檔以二進制的形式保存在字段當中,這樣大型文檔也可以隨數據庫一起備份,很多網站存儲圖片都是存儲圖片的路徑,這樣備份數據庫的時候圖片不會一起備份。

全文索引帶來好處的同時也會對性能有一定的影響,特別是在進行篩選操作的時候對服務器性能會帶來影響,所以選擇一個功能的同時需要考慮對性能帶來的影響。

 

 

備注:

    作者:pursuer.chen

    博客:http://www.cnblogs.com/chenmh

本站點所有隨筆都是原創,歡迎大家轉載;但轉載時必須注明文章來源,且在文章開頭明顯處給明鏈接,否則保留追究責任的權利。

《歡迎交流討論》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM