您的位置:首页 > 运维架构 > 网站架构

SQL Server 2005全文检索技术在网站上的应用实录(二)

2009-09-25 11:17 507 查看
或者键入如下命令:

CREATE FULLTEXT INDEX ON TableName KEY INDEX PK_IndexName ON  DB WITH CHANGE_TRACKING AUTO
ALTER FULLTEXT INDEX ON TableName ADD ColumnName

b)选择或创建新的索引目录。


图7
c)定义填充计划。


图8
至此,表的全文索引已经建立完毕,表示只要键入SQL 指令就可以完成全文检索功能。

第三步,开发存储过程并把结果集分页,以供前台页面调用返回查询的结果。

1) 建立找资本全文检索储存过程USP_CaptialInfo_FullIndex。

/*
找资本全文索引开发过程
*/
CREATE PROCEDURE USP_CaptialInfo_FullIndex
(
@TableViewQueryName Varchar( 1024 ), --传入的查询字符窜
@SearchKeyword  nvarchar(100), --传入的查询关键字
@SelectStr  Varchar( 500 ),  --选择列字符串
@Criteria  Varchar( 8000 ), --查询条件
@Sort   Varchar( 255 ),  --排序字符串
@FristTopNum  int,   --显示的第一页置顶的数目
@Page   bigint OUTPUT  ,  --显示的当前页号
@CurrentPageRow bigint,   --页大小(显示多少行)
@TotalCount  bigint output,  --通过该查询条件,返回的查询记录的总页数
@Totaltimes  bigint output  --所有搜索时间,以秒为单位
)
as
DECLARE @starttime datetime,
@endtime datetime
SELECT  @starttime = getdate()

IF  ISNULL(@SearchKeyword,'') !='' OR  RTRIM(@SearchKeyword)!=''
BEGIN
SET @TableViewQueryName =
' SELECT  '+
' ROW_NUMBER() OVER (ORDER BY RANK DESC) AS SerialNumber ,'+
' F.[rank], '+
' p.*' +
' FROM '+
' FREETEXTTABLE( CapitalInfoFactTab , (ProvinceName, CityName,
CountyName, Keyword,Title ,IndustryBName , shortcontent, ComAbout , ComBreif) ,
'+ ''''+@SearchKeyword+ ''''+') AS f '+
' INNER JOIN   CapitalInfoFactTab   AS p  '+
' ON f.[key] = p.infoID '

EXEC [USP_GetFrontDataList_ByFullIndex] @TableViewQueryName,
@SearchKeyword, @SelectStr, @Criteria, @Sort, @FristTopNum,
@Page OUTPUT , @CurrentPageRow , @TotalCount OUTPUT
END ELSE BEGIN

EXEC dbo.GetFrontDataList 'dbo.ProjectInfoFactTab', 'InfoID',
@SelectStr,@Criteria,@Sort,0, @Page output, @CurrentPageRow,
@TotalCount output
END
SELECT  @endtime = getdate()
SELECT  @Totaltimes  = DATEdiff(Ms, @starttime ,@endtime)
RETURN

2)建立通用分页存过程[USP_GetFrontDataList_ByFullIndex]。由于性能考虑,返回给前台页面需要网站数据库端即完成分页。

CREATE PROCEDURE [dbo].[USP_GetFrontDataList_ByFullIndex]
(
@TableViewQueryName  Varchar( 1024 ),

--Table或View或者Query的名字或字符串
@Key    Varchar( 50 ),  --关键字
@SelectStr   Varchar( 500 ),   --选择列字符串
@Criteria   Varchar( 8000 ),--查询条件
@Sort    Varchar( 255 ), --排序字符串
@FristTopNum   INT,      --显示的第一页置顶的数目
@Page    BIGINT  OUTPUT, --显示的当前页号
@CurrentPageRow  BIGINT,  --页大小(显示多少行)
@TotalCount   BIGINT OUTPUT   --通过该查询条件,返回的查询记录的总页数
)
AS

SET NOCOUNT ON

if charindex(';',@Criteria)>0 or charindex('--',@Criteria)>0 or charindex('/*',

@Criteria)>0 or
charindex('*/',@Criteria)>0 or charindex('syscolumns',@Criteria)>0  or

charindex('sysfiles',@Criteria)>0
or charindex('char(124)',@Criteria)>0  or charindex('1=1',@Criteria)>0
RETURN

DECLARE @TotalStr  nVarchar(4000)
DECLARE @Str   nVarchar(4000)
DECLARE @TopRowNum bigint
IF  @SelectStr IS NULL AND
RTRIM(LTRIM(@Criteria)) = ''
SET @SelectStr = '*'
IF @FristTopNum IS NULL AND @FristTopNum < 0
BEGIN
SET @FristTopNum = 0
END
ELSE IF @FristTopNum > @CurrentPageRow
BEGIN
SET @FristTopNum = @CurrentPageRow
END

IF  @CurrentPageRow > 0
BEGIN
IF @Criteria IS NOT NULL AND
RTRIM(LTRIM(@Criteria)) <> ''
BEGIN
SET  @TotalStr = 'SELECT @TotalCount=COUNT(*) FROM  ' +

'('+ @TableViewQueryName   +')'+ ' T '
+ ' WHERE ' + @Criteria
END
ELSE
BEGIN
SET  @TotalStr = 'SELECT @TotalCount=COUNT(*) FROM ' +

'('+@TableViewQueryName  +')'+ ' T '
END
PRINT @TotalStr
EXEC  sp_ExecuteSql @TotalStr, N'@TotalCount bigint output',@TotalCount output

SET @TotalCount = @TotalCount + isnull(@FristTopNum  ,0)
DECLARE @TotalPage bigint
SET @TotalPage = @TotalCount/@CurrentPageRow
IF @TotalCount%@CurrentPageRow > 0
BEGIN
SET @TotalPage = @TotalPage + 1
END
IF @Page <= 0
BEGIN
SET @Page = 1
END
IF @TotalPage > 0 AND
@Page > @TotalPage
BEGIN
SET @Page = @TotalPage
END

--组织查询语句
SET  @Str =  'SELECT   ' +   @SelectStr + ' FROM (' +

@TableViewQueryName  + ') T WHERE  T.SerialNumber >' +
cast ((@Page-1)  as varchar(10)) + '*' +cast( @CurrentPageRow as varchar(10))+

' AND T.SerialNumber <= '+
cast (@Page  as varchar(10)) + '*' +cast( @CurrentPageRow as varchar(10))

IF @Sort IS NOT NULL ANDRTRIM(LTRIM(@Sort)) <> ''
BEGIN
IF @Criteria IS NOT NULL AND  RTRIM(LTRIM(@Criteria)) <> ''
BEGIN
SET  @Str = @Str +   ' AND (' + @Criteria + ') ORDER BY '+@Sort
END
ELSE
BEGIN
SET  @Str = @Str +   ' AND  (' + @Criteria + ') ORDER BY '+@Sort
END
END
ELSE
BEGIN

IF @Criteria IS NOT NULL AND   RTRIM(LTRIM(@Criteria)) <> ''
BEGIN
SET @str = @str +  ' AND (' + @Criteria + ')  '
END

END
--对无记录时当前页数的处理
IF @TotalCount=0
BEGIN
SET @Page = 0
END
END

EXEC  sp_ExecuteSql @Str

[/code]
由于本行业网站可以提高如下几类信息资源,现列表分示如下:

ID检索内容数据表检索命令示例
1投资CapitalInfoTabDECLARE @RC int
DECLARE @TableViewQueryName varchar(1024)
DECLARE @SearchKeyword nvarchar(100)
DECLARE @SelectStr varchar(500)
DECLARE @Criteria varchar(8000)
DECLARE @Sort varchar(255)
DECLARE @FristTopNum int
DECLARE @Page bigint
DECLARE @CurrentPageRow bigint
DECLARE @TotalCount bigint
DECLARE @Totaltimes bigint
 
-- TODO: 在此处设置参数值。
SET @SearchKeyword = '地产项目'
SET @SelectStr = '*'
SET @Sort = ''
SET @Page= 1
SET @CurrentPageRow = 20
EXECUTE @RC = [InvestDM].[dbo].USP_CapitalInfo_FullIndex
@TableViewQueryName
,@SearchKeyword
,@SelectStr
,@Criteria
,@Sort
,@FristTopNum
,@Page
,@CurrentPageRow
,@TotalCount OUTPUT
,@Totaltimes OUTPUT
SELECT @Page,@TotalCount,@Totaltimes
2融资ProjectInfoTabDECLARE @SearchKeyword nvarchar(100) --传入的查询关键字
SET @SearchKeyword = '深圳'
 
SELECT p.title,
p.infoid,
f.[rank] ,
keyword,title,provinceName,cityName,CountyName
FROM
FREETEXTTABLE([ProjectInfoFactTab], (provinceName,cityName,CountyName,keyword,title), @SearchKeyword) AS f
INNER JOIN [ProjectInfoFactTab] AS p
ON f.[key] = p.infoID
ORDER BY RANK DESC
3招商MerchantInfoTabDECLARE @SearchKeyword nvarchar(100) --传入的查询关键字
SET @SearchKeyword = '深圳'
SELECT
ROW_NUMBER() OVER (ORDER BY RANK DESC) AS SerialNumber ,
F.[rank],
p.*
FROM
FREETEXTTABLE( MerchantInfoFactTab , (ProvinceName, CityName, CountyName, Keyword,
Title ,IndustryBName , shortcontent, ZoneAbout , ZoneAboutBrief, MerchantTypeName ,MerchantAttributeName,

CooperationDemandName ) ,

@SearchKeyword) AS f

INNER JOIN MerchantInfoFactTab AS p
ON f.[key] = p.infoID
4资讯NewsTabDECLARE @SearchKeyword nvarchar(100) --传入的查询关键字
SET @SearchKeyword = '深圳'
SELECT
ROW_NUMBER() OVER (ORDER BY RANK DESC) AS SerialNumber ,
F.[rank] ,
p.*
FROM
FREETEXTTABLE( NewsInfoFactTab , (AreaName, Keyword,
Title , DisplayTitle, subtitle ,Summary , Content ,NewsIndustryName , NewsTypeName ) , @SearchKeyword ) AS f
INNER JOIN NewsInfoFactTab AS p
ON f.[key] = p.infoID
五、全文检索性能考量

除了硬件资源 [如内存(3GB 限制)、磁盘速度和 CPU 速度] 以外,全文搜索性能还受到 Microsoft SQL Server 和 Microsoft Full-Text Engine for SQL Server (MSFTESQL) 服务对这些资源的争用情况的影响。MSFTESQL 服务只对磁盘进行写操作,而 SQL Server 会对磁盘进行读写操作。从性能角度出发,关键是很好地优化 MSFTESQL 服务,以便获得最佳使用效果。

全文搜索性能包含两个方面:

◆全文索引性能
◆全文查询性能

全文索引性能

Microsoft SQL Server 2005 中的全文搜索的索引性能很大程度上取决于下面两个因素:

◆SQL Server 创建全文批花费的时间。
◆MSFTESQL 服务使用这些批的速度。

若要达到最佳性能,需要优化 SQL Server 与 MSFTESQL 服务之间的交互。如果 MSFTESQL 服务处理不完 SQL Server 生成的批,该服务将暂停,并生成一个爬网日志消息来指示此暂停状态。有关如何解决此问题的信息,请参阅Microsoft SQL Server 全文引擎 (MSFTESQL) 服务已暂停。

另一方面,如果 SQL Server 没有生成足够的全文批, 使 MSFTESQL 服务充分运行,该服务就会闲置,这样就不能达到最佳性能。若要确保 MSFTESQL 服务处于最佳使用状况,需要跟踪并优化下列计数器:

正在处理的批计数器 - Microsoft Full-Text Engine Filter Daemon (MSFTELFD)

此计数器应当等于系统中的 CPU 数或其两倍。当 CPU 使用值为 0、1 或 2 时,指示 SQL Server 执行情况不好。例如,如果计算机上具有 4 个 CPU,此数值就应该为 4 或 8。

已就绪的批队列 - MSFTESQL 服务

如果批数较少,可以执行下列操作:

◆增加全文批的大小。
◆确保基表具有聚集索引。
◆将 SQL 日志、数据库文件和全文目录分别放在单独的磁盘上。
◆默认情况下,全文批的大小是每批 1600 行。如果计算机上有八个频率为 700Mhz 的 CPU,推荐采用的批大小为 5000 行。

注意:

增加批大小会导致批的生成速度变慢,而且 MSFTSQL 要执行更多的操作来处理每个批。此外,请记住全文批的大小受共享内存区域大小的限制。共享内存区域大小的默认值为 4Mb。

爬网范围

◆使用 sp_configure 最大全文爬网范围选项增大爬网范围计数器。理想情况下,此值应该是 CPU 数的两倍。
◆使用 UPDATE STATISTICS 语句更新基表的统计信息。

提高全文查询性能的建议

下面列出了有助于提高全文查询性能的建议。

使用 ALTER INDEX REORGANIZE 对基表的索引进行碎片整理。

使用 ALTER FULLTEXT CATALOG REORGANIZE 重新组织全文目录。切记要在进行性能测试之前执行此操作,因为它会引起该目录中全文索引的主合并。

仅选择较小的列作为全文键列。即使支持 900 字节的列,也不建议您使用这么大的键列来创建全文索引。

将多个 CONTAINS 合并为一个 CONTAIN。在 Microsoft SQL Server 中,您可以在 CONTAINS 查询中指定一个包含若干列的列表。

如果只需要全文键或排名的信息,请分别使用 CONTAINSTABLE 或 FREETEXTTABLE,而不要使用 CONTAINS 或 FREETEXT。

使用 FREETEXTTABLE 和 CONTAINSTABLE 语法的 TOP_N_BY_RANK 选项来限制结果数并提高性能。如果您不是对可能查询到的所有信息都感兴趣,可使用此选项。

六、需求规划

我们知道做好网站检索不仅仅面临纯技术的问题,而且本身需要事前的需求规划,这里给出了全网搜索在功能性需求和非功能性需求上的典型需求。

功能性的需求:

(1)哪些业务数据需要提供全文的检索服务?
(2)这些业务数据中那些关键信息是业务人员关心的?
(3)需要支持哪些国家的语言?
(4)有哪些行业术语、常用缩略词、替换词?
(5)需要哪些检索功能,分别基于什么范畴的关键字展开检索?

非功能性的需求:

(1)业务上以前是否尝试过关系数据库查询、多维数据分析解决手头的问题?
(2)检索时效性要求。
(3)习惯的检索操作平台(浏览器 / 桌面),查询结果的展示方式。
(4)授权控制。
(5)查询结果的导出和发布方式要求。

七、结束语

本文提供了网站如何设计和实现基于SQL Server 2005的全文检索实例,希望能对正在使用SQL Server 2005构建网站搜索的同仁有所裨益。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: