关 键 词:
搜索 Microsoft
这两个查询要么不必要地占用大量系统开销,要么存在返回错误结果的可能性(在第二个查询中,“sports”很可能出现在所有类型的文章中)。这两项技术还存在其他变体,但这是两种非常简单的模型。如果可行,我通常建议您对数据进行水平划分。即,“类别”列的每个可能值都自成一列(或表),并且与该文章相关的可搜索关键字仅存储在此列中。采用此方法,而不是使用一个“正文”列和一个“类别”列,可以去掉“类别”列,而使用存储可搜索关键字的“Body_<category>”列。如以下示例所示:-- 如果您可以调整架构,这非常有效 ‐\ 每个类别-- 都成为自己的列(或表格),并且需要命中的-- 全文索引也较少。这明显需要作一些解释……SELECT [key], [rank] FROM FREETEXTTABLE(Articles, Body_Sports, @#Ichiro@#)
对于包含大量数据,且这些数据可适应此架构(或许是主架构)更改的系统,其性能会得到显著的提高。但在何时应用多个过滤器或不应用过滤器方面却有着明显的限制。当然,还有其他的方法可以解决这些问题。通过以上示例,您会了解一种将某些搜索条件抽象到架构的方法 - 实际上是“欺骗”优化程序(更确切的说是“成为”优化程序),因为在 SQL Server 本身的全文查询中当前不存在本地优化。其他性能技巧人们在聊天时常常问我的另一个问题是如何才能分页显示全文查询结果。换句话说,如果我要发出“root beer”查询,一次在某一 Web 页上显示 40 个结果,并且只希望返回该页面上的 40 个结果(例如,如果我在第三页,我希望仅返回第 81 至第 120 条结果)。对于分页显示结果,我曾见过多种方法,但没有一种方法能够做到百分之百有效。我所推荐的方法可以最大程度地减少全文查询执行的次数(实际上,对于要分页显示的每个结果集只需执行一次),并将 Web 服务器用作一个简单的缓存。从更高的层面来讲,您只需在全文查询中检索一个完整的主键和排位值行集合(如果需要,可以在架构中使用最佳选择并提取常用过滤器),并将其存储在 Web 服务器的内存中(这取决于您的应用程序和负载,想象将 <32 字节的典型主键大小与 <4 字节的排位大小相加 [等于 <36 字节],然后乘以通常返回的结果集 <1000 行,最后等于 <35K。假定一个在任何给定时间返回 <1000 个活动查询结果集中的一个活动缓存集,您将发现此活动缓存集在 Web 服务器上占用的内存少于 35MB - 这还可以接受)。为了分页显示结果,该进程只遍历 Web 服务器的内存中存储的数组,并对 SQL Server 发出 SELECT 以便只显示需要显示的行和列。这又回到了全文查询仅返回主键和排位的概念中 - SELECT(甚至许多这样的查询语句)比全文查询的速度快许多倍。使用 SELECT 而不是与基表合并多个行,并结合多个其他策略,您可以保留 SQL Server 计算机上更多的 CPU 周期,并且更有效、更划算地利用 Web 领域。另一种可以替代 Web 服务器端缓存的方法是在 SQL Server 自身中缓存结果集,并定义多种用于浏览这些结果的方法。虽然本文着重说明 Web 服务器 (asp) 级别的应用程序设计,但 SQL Server 的可编程功能还为生成高性能的 Web 搜索应用程序提供了强大的框架。小结Microsoft SQL Server 2000 的全文搜索功能为索引和查询数据库中存储的非结构化文本数据提供了可靠、快速而灵活的方法。如果要广泛地将这种快速、准确的搜索功能应用于各种应用程序,那么很有必要充分利用其速度和精确性,来实现全文搜索解决方案。通过分布计算负载并通过某些巧妙的方式对数据进行组织,可以省下钱来购买其他硬件和软件,以摆脱因不必要的缓慢查询带来的困扰。在开发优秀的搜索应用程序时,通常要考虑到许多因素和注意事项,希望本文提供的信息和示例对您学习使用 SQL Server 2000 生成出色的 Web 搜索应用程序会有所帮助。附录 A:实现全文搜索功能的最佳选择改进全文查询性能和有效性的一种可行方法是实现“最佳选择”系统。此系统是一种很简单的方法,可确保某些与特定查询表达式匹配的行先于其他行返回。最佳选择没有复杂的预编程逻辑(例如,SharePoint Portal Server 就包含这样的逻辑),因此,通常是首选办法。在本示例中挑选出最佳选择,并将唯一的主键和一些关键字存储在单独的表中。FREETEXTTABLE 查询对(非常小的)最佳选择表执行,并且从该查询中返回的任何结果都与对基表的 FREETEXTTABLE 查询结果一同返回。在给定这些搜索条件下,最先返回的将是所有“最佳选择”行,随后是被 MSSearch 视为关联程度最高的行(以递减顺序返回)。下面是一个非常简单的用于创建最佳选择系统的示例脚本。use myDb
create table documentTable(ftkey int not null, document ntext)create unique index DTftkey_idx on documentTable(ftKey)
/* 在此插入文档 (要生成全文索引的所有文档)*/
-- 为所有文档表创建全文目录和索引exec sp_fulltext_catalog @#documents_cat@#, @#create@#, @#f:\\ftCats@#exec sp_fulltext_table @#documentTable@#, @#create@#, @#documents_cat@#, @#DTftkey_idx@#exec sp_fulltext_column @#documentTable@#, @#document@#, @#add@#exec sp_fulltext_table @#documentTable@#, @#start_change_tracking@#exec sp_fulltext_table @#documentTable@#, @#start_background_updateindex@#
/* 现在创建最佳选择表和索引 (添加应该始终最先返回的文档)*/create table bestBets(ftKey int not null, keywords ntext)create unique index BBftkey_idx on bestBets(ftKey)
/* 在此插入最佳选择*/
-- 为最佳选择表创建全文目录和索引exec sp_fulltext_catalog @#bestBets_cat@#, @#create@#, @#f:\\ftCats@#exec sp_fulltext_table @#bestBets@#, @#create@#, @#bestBets_cat@#, @#BBftkey_idx@#exec sp_fulltext_column @#bestBets@#, @#keywords@#, @#add@#exec sp_fulltext_table @#bestBets@#, @#start_change_tracking@#exec sp_fulltext_table @#bestBets@#, @#start_background_updateindex@#
首先创建了一个通用的“所有文档”表,用于存储所有要全文索引的文档。通常情况下,文档表中包含其他列,但在本文中,只包含两列 - 主键索引和文档本身。全文目录和索引是为文档表而创建的。接着创建了“最佳选择”表,用于存储所有全文查询中首先返回的特殊文档。此表只需具有全文主键列和文档本身(对将某些文档作为查询目标的策略进行优化,包括在该文档本身不包含的文档中添加其他关键字)。全文目录和索引是为最佳选择表而创建的。最佳选择表和文档表可以共享文档(最佳选择文档还存储在常规文档表中,它们共享同一个主键值),也可以相互排斥(最佳选择文档只存储在最佳选择表中)。为便于检索,使最佳选择表与文档表互斥更为容易 - 这样做就无需从最佳选择和返回的普通搜索结果行集合中删除共享操作。另一方面,使用此方法维护文档可能很难实现,因为在此方法中,要在查询中添加逻辑来删除返回的行集合之间的共享文档。如果给定上面的表,则可以创建两个存储过程,以便对最佳选择表和文档表进行搜索。可使用 Web 服务器级别的逻辑或其他存储过程来缓存和显示所需结果(与最佳选择一起使用时,请参阅下面有关缓存、显示和分页的一个完整、有效的示例)。首先,创建一个用于检索最佳选择行(如果有)的存储过程:create procedure BBSearch @searchTerm varchar(1024) as

