7

我有一个看起来像这样的新闻文章的搜索功能(包含超过 5 个搜索项):

SELECT TOP 5 *
FROM NewsArticles
WHERE (headline LIKE '% sustainable %'OR
headline LIKE '% sustainability %' OR
headline LIKE '% conservation %' OR
headline LIKE '% environmental % OR
headline LIKE '% environmentally %') 
OR
(body LIKE '% sustainable %'OR
body LIKE '% sustainability %' OR
body LIKE '% conservation %' OR
body LIKE '% environmental % OR
body LIKE '% environmentally %')
ORDER BY publishDate DESC 

此查询旨在提取与可持续发展相关的前 5 个新闻报道,并位于我的主要可持续发展主页上。但是,它需要一段时间才能运行,并且页面加载速度很慢。所以我正在寻找加快速度的方法。有这么多 LIKE 子句似乎很麻烦,所以我尝试了这样的 JOIN 方法:

CREATE TABLE #SearchItem (Search varchar(255))

INSERT INTO #SearchItem VALUES
('sustainable'),
('sustainability'),
('conservation'),
('environmental'),
('environmentally')

SELECT TOP 5 *
FROM NewsArticles as n
JOIN #SearchItem as s
ON n.headline COLLATE DATABASE_DEFAULT LIKE '% ' + s.Search + ' %' OR 
n.body COLLATE DATABASE_DEFAULT LIKE '% ' + s.Search + ' %'
ORDER BY n.publishDate DESC

这似乎对性能非常有效,但似乎有时会带回重复的文章,其中一个搜索词同时出现在正文和标题中(通常是这种情况)。我尝试使用“SELECT DISTINCT TOP 5 *”这个词,但这给了我一个错误,说“ntext 数据类型不能被选为 DISTINCT,因为它不可比较”。是否可以在不进行 2 次单独搜索和使用 UNION 的情况下阻止它带回重复项?

4

5 回答 5

4

如果您正在执行这些类型的搜索,则应使用全文搜索。您需要在 BOL 中阅读有关如何设置它的信息,因为它很复杂。但是,当您将通配符作为第一个字符时,SQL Server 无法使用索引,这就是速度慢的原因。

于 2013-08-15T16:58:37.127 回答
2

如果有一个新闻文章键,您可以使用一个查询来连接回自身,例如:

select top 5 *
from NewsArticles as na
join 
    ( 
        SELECT distinct idNo , publishDate 
        FROM NewsArticles as n
        JOIN #SearchItem as s
        ON n.headline COLLATE DATABASE_DEFAULT LIKE '% ' + s.Search + ' %' OR 
        n.body COLLATE DATABASE_DEFAULT LIKE '% ' + s.Search + ' %'
    ) as sk
        on sk.idNo = na.idNo
ORDER BY sk.publishDate DESC
于 2013-08-15T16:48:38.297 回答
1

由于您在多个单词上获得了多次点击,因此您可以使用选定的 ID 作为实际选择文章的过滤器:

Select TOP 5 * 
from NewsArticles 
where ID in (SELECT ID
    FROM NewsArticles as n
    JOIN #SearchItem as s
    ON n.headline COLLATE DATABASE_DEFAULT LIKE '% ' + s.Search + ' %' OR 
       n.body COLLATE DATABASE_DEFAULT LIKE '% ' + s.Search + ' %'
)
ORDER BY publishDate DESC

它应该仍然相当快(与原始查询相比)并且没有重复。

(如在 Rawheiser 的回复中,假设 ID 字段实际存在:))

于 2013-08-15T16:52:53.503 回答
1

您也可以尝试全文搜索。就像是

SELECT TOP 5 * FROM NewsArticles 
WHERE CONTAINS((headline,body), 'FORMSOF(INFLECTIONAL, sustainable) OR conservation OR FORMSOF(INFLECTIONAL, environmental)')

但是,正如 HLGEM 所说,阅读有关设置 FTS 的信息很重要。只需为这两列创建索引就足够了,因为您正在搜索单个单词,但是一旦添加了短语,您就想开始编辑停用词、中断词和干扰词。

于 2013-08-15T17:00:45.767 回答
0

我会这样的

在此处输入图像描述

我将编写一个不区分大小写的索引过程,该过程将在 nights 运行,这将:

  • 解析文章,插入SEARCH_TERM它找到的任何新词
  • 插入SEARCH_INDEX表示给定文章具有给定搜索词的元组
  • 将 标记NEWS_ARTICLE为已编入索引。
  • 下一次运行将仅索引尚未被索引的文章

示例查询可以是这样的,并且会快速点亮,因为您不会使用LIKE

select
    distinct n.headline
from
    search_item s
    join search_index x on (s.id = x.search_item_id)
    join news_article n on (x.news_article_id = n.id)
where
    s.term in ('sustainable','sustainability','conservation',
               'environmental','environmentally')

稍后,您可以为搜索词创建同义词,并创建一个返回词及其同义词的视图,如果您希望将来进行更多语义搜索。

于 2013-08-15T18:01:16.950 回答