网络编程
位置:首页>> 网络编程>> 数据库>> 使用Microsoft SQL Server 2000全文搜索功能构建Web搜索应用程序(2)

使用Microsoft SQL Server 2000全文搜索功能构建Web搜索应用程序(2)

  发布时间:2008-09-29 12:32:00 

标签:SQL,Server,2000,全文,检索,搜索,数据库

全文查询

    查询全文索引与执行SQL Server中的标准关系型查询略有不同。由于索引是在SQL Server外部进行存储和管理的,因此全文查询处理大部分由MSSearch完成(因此,那些一部分是关系型、一部分基于全文的查询将被单独处理),这样做有时会损害性能。

    从本质上说,执行全文查询时,查询词传递给MSSearch,后者遍历其内部数据结构(索引),并向SQL Server返回主键和排位值。如果执行CONTAINS或FREETEXT查询,则通常看不到主键或排位值,但如果执行CONTAINSTABLE或 FREETEXTTABLE查询,则将获得这些值,然后这些值通常会与基表合并在一起。与基表合并主键的进程需要很高的系统开销—稍后,我们将向您介绍一些巧妙的方法以尽量减少或完全避免这种合并。

    如果您通过不断思考,对全文查询如何返回数据有了一个初步了解,就可以推测出CONTAINS/FREETEXT查询仅执行CONTAINSTABLE /FREETEXTTABLE查询并与基表进行合并。有了这样的了解,您应该避免使用这些类型的查询,除非不这样做的开销更高。在Web搜索应用程序中,使用CONTAINSTABLE与FREETEXTTABLE比使用不带TABLE的同类函数好得多。

    到现在为止,您已经知道全文查询是用来从SQL Server之外存储的MSSearch索引中访问数据的特殊方法,还知道如果盲目地与基表进行合并,就会遇到麻烦。应该了解的另外一个重要内容是 CONTAINS样式查询与FREETEXT样式查询之间的本质差别。

    CONTAINS查询用于对所查询的所有词语执行完全匹配查询。无论您只查找单个单词,还是查找以“orange”开头的所有单词,系统只返回包含所有搜索词的结果。因此,CONTAINS查询速度很快,因为它们通常返回很少的结果,并且不需要执行过多的附加处理。CONTAINS查询的缺点包括令人生厌的干扰词过滤问题。经验丰富的开发人员以及过去使用过全文搜索的数据库管理员,在试图匹配只包含单个干扰词的单词或词组时,曾遇到过“您的查询只包含干扰词”这样令人吃惊的错误。要避免收到此错误,方法之一是在执行全文查询之前过滤出干扰词。向包含干扰词的CONTAINS查询返回结果是不可能的,因为此类查询只返回与整个查询字符串完全匹配的结果。由于干扰词不是全文索引项,因此包含干扰词的CONTAINS查询不会返回任何行。

    REETEXT查询消除了CONTAINS查询中偶尔出现的所有警告说明。当发出FREETEXT查询时,实际上发出的是词根查询。因此,当您搜索 “root beer”时,“root”和“beer”包含其所有形式(寻根溯源与语言相关;所用的语言由生成索引时指定的全文列语言确定,并且在所有查询的列中必须相同),并且系统将返回至少与这些词语之一匹配的所有行。

    FREETEXT查询的负面影响是它们通常比CONTAINS查询耗用更多的CPU—因为要寻根溯源以及返回更多的结果,就需要包含更复杂的排位计算。不过,基于FREETEXT的查询非常灵活,而且速度非常快,是基于Web的搜索应用程序中通常使用的最佳选择。
排位(Ranking)和优化

    我经常遇到使用全文搜索的用户,他们问我排位编号是什么意思,以及如何将排位编号转换成某种用户可以理解的值。对这个问题,回答可长可短,在这里我将进行简要回答。简单而言,这些排位编号不如结果返回的顺序那样重要。也就是说,当您按照排位对结果进行排序时,总是首先返回关联程度最高的结果。排位值本身常常变化—全文搜索使用概率排位算法,即返回的每个文档的关联性受全文索引中的任何或所有其他文档的直接影响。

    有些人认为,一种有助于增加某些行排位的技巧是在这些行的全文索引列中重复常用的搜索关键字。尽管在某种程度上,这种方法可能会提高这些行因某些关键字而首先返回的几率,但在其他情况下,可能会适得其反—而且还存在使词语查询性能降低的风险。较好的解决方案是为搜索应用程序实现“最佳选择”系统(请参阅以下示例),这样就可以确保首先返回某些文档。多次重复使用关键字会使这些特定关键字的全文索引扩大,并使得MSSearch在查找正确行和计算排位时浪费时间。如果全文索引数据量很大,并尝试使用了此方法,您可能会发现某些全文查询很耗时。如果能够实现更细致(也可能更精确)的“最佳选择”系统,您会发现它明显改善了查询性能。

    多次重复数据的另一个问题与用于组合关系型查询和全文查询的常用技巧有关。许多使用全文搜索的用户都深受此问题的困扰,每当他们试图将某种过滤器应用于全文查询返回的结果时,便会遇到这样的问题。正如前面所说的,全文查询为每个匹配行返回一个主键和一个排位—要收集有关这些行的任何详细信息,必须与它的基表进行合并。由于从无限制的全文查询中可能会返回任意数量的结果,因此合并可能需要大量系统开销。人们发现避免合并的一个有效方法是只在全文索引中添加要过滤的数据(如果可能)。换句话说,如果用户要从报纸上所有文章的正文中搜索关键字“Ichiro”,并且只希望返回该报上体育专栏中的文章,则查询语句通常如下所示:

-- [方法1:]
--开销最高:先全部选择,然后再合并和过滤

Select ARTICLES_TBL.Author, ARTICLES_TBL.Body, ARTICLES_TBL.Dateline,
FT_TBL.[rank]
FROM FREETEXTTABLE(Articles, Body, 'Ichiro') AS FT_TBL
INNER JOIN Articles AS ARTICLES_TBL
ON FT_TBL.[key] = ARTICLES_TBL.ArticleID
Where ARTICLES_TBL.Category = 'Sports'

-- [方法2:]
--可以使用,但会导致意外结果并变慢,或者会返回不准确的结果:
--执行全文过滤,并且只提取主键和排位
--(处理在Web服务器上完成)

Select [key], [rank]
FROM CONTAINSTABLE(Articles, *, 'FORMSOF(INFLECTIONAL('Ichiro')
AND "sports"')

这两个查询要么不必要地占用大量系统开销,要么存在返回错误结果的可能性(在第二个查询中,“sports”很可能出现在所有类型的文章中)。这两项技术还存在其他变体,但这是两种非常简单的模型。如果可行,我通常建议您对数据进行水平划分。即,“类别”列的每个可能值都自成一列(或表),并且与该文章相关的可搜索关键字仅存储在此列中。采用此方法,而不是使用一个“正文”列和一个“类别”列,可以去掉“类别”列,而使用存储可搜索关键字的“Body_” 列。如以下示例所示:

--如果您可以调整架构,这非常有效–每个类别
--都成为自己的列(或表格),并且需要命中的
--全文索引也较少。这明显需要作一些解释

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领域。

0
投稿

猜你喜欢

  • IE测试通过,FF有点小BUGCls_Leibie.asp代码如下:<% '数据库字段为类属性,添加、删除、修改、操
  • 在DreamWeaver中编写CSS,这种编写习惯并不提倡,不过由于"可视化"和操作简便,使用的朋友依然很多,今天罗列一
  •     对于网页制作者来说,最烦琐的事情可能就是给页面中的图片或文字加链接了。假如页面内容很多的话,那么所做的
  • 作者:Henny Swan / co-lead of WaSP ILG译者:JunChen / member of WaSP ILG原文:h
  • 很多网站现在都有使用QQ作为在线客服工具,我们点击它可以很方便的和网站人员联系,本站为你整理了在网站上使用QQ在线客服的代码,共13种风格,
  • 说完了理论,我们来做点实事。这篇文章将介绍使用 Javascript 实现的动画组件。下面记录下当时编写这个组件的考虑的些问题,对技术细节感
  • 优雅的设计经常包含一些特殊的字体,而这些字体并不存在于用户的字体库中,我们并不能奢求每一个访客都是设计师。  :-)虽然CSS3标
  • create or replace PROCEDURE proceudre_name AS BEGIN DECLARE sPara VARC
  • 说绘画语言,西方的油画是人类视觉语言里怎么也不能忽略的浓烈一笔。14~15世纪,蛋彩画——油画前身的发明,绘画可以使用均匀过渡的色彩渐变,并
  • HTML5本地存储初探(二)完成了数据的本地存储,就要将文件存储也搞定。为了实现文件的本地存储,html5搞了一个叫 manifest 的文
  • 这个函数是前几年刚流行小偷程序的时候,偶写来用于小偷程序中截取代码的;可能有些朋友在我以前的代码中看见过了,但没有写用法,现在把调用方法及使
  • 以前写过《 10条影响CSS渲染速度的写法与建议》,今天放些数据出来,供参考;首先说明一点,CSS对网页的最后渲染出来的速度影响非
  • parent.html  中的代码为:<iframe marginwidth="0"
  • 使用access数据库时可能用到的数据转换:类型转换涵数:函数 返回类型 expression 参数范围CBool Boolean 任何有效
  • 1、选取最适用的字段属性MySQL 可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快。因此,在创建
  • 如何在服务器端调用winzip命令行对上传的多个文件打包压缩?要解决这个问题,首先要了解一下Windows Scripting Host,简
  • 五花八门的SQL产品多得要命,或许你早顾不得其它甩开袖子就动手干了。但你要同时采用ASP和SQL的话就可能会头晕。MySQL、SQL Ser
  • 常见的双倍边距类问题都遇到过,但很少遇到这种有意思的,所以记录一下。这个BUG是发生在Standards模式下(就是包含XHTML或者HTM
  • 使用jmail组件发送邮件:Function JMail(Send_From,Send_To,Send_Subject,Send_
  • 本文将展示一个开源JavaScript库,该脚本库给AJAX应用程序带来了书签和后退按钮支持。在学习完这个教程后,开发人员将能够获得对一个A
手机版 网络编程 asp之家 www.aspxhome.com