在SQL中搜索最有效的方法?

时间:2012-03-06 18:36:21

标签: mysql sql

我有一个包含75,000多行的数据库,每天添加500多个条目。

每一行都有标题和说明。

我创建了一个RSS源,它为您提供特定搜索词的最新条目(例如http://site.com/rss.rss?q=Pizza将输出搜索词“Pizza”的RSS。)

我想知道为此编写SQL查询的最佳方法是什么。现在我有:

SELECT * 
FROM 'table' 
WHERE (('title' LIKE %searcherm%) OR ('description' LIKE %searcherm%))
LIMIT 20;

但问题是执行查询需要2到10秒。

有没有更好的方法来编写查询,我是否必须缓存结果(我将如何做?)或者更改数据库结构中的某些内容会加快查询速度(索引?)

7 个答案:

答案 0 :(得分:9)

一个相对简单的解决方案是在这两个字段中加入FULLTEXT索引,然后使用此索引进行搜索。

ALTER TABLE table ADD FULLTEXT(title, description);

然后你需要进行搜索,你会做以下事情:

SELECT id FROM table
WHERE MATCH (title, description) AGAINST ('keyterm');

全文索引搜索是大多数SQL数据库中包含的自动解决方案。与做LIKES相比,它更快。这也针对您的具体情况进行了优化,因为您只对自然语言搜索术语感兴趣。

同样,全文索引具有一些用于检测相关性的限制算法。您可以阅读更多相关信息here

修改

在alter语句中,我错过了全文索引名称,它应该是:

ALTER TABLE table ADD FULLTEXT ft_index_name(title, description);

答案 1 :(得分:4)

尝试:

SELECT * FROM table
WHERE MATCH (title,description) AGAINST (searchterm);

确保在标题,说明上一起添加全文索引。

不要试图重新发明轮子。 MATCHAGAINST正是provided by mysql才能做到这一点,让您的生活变得轻松。但是,请注意全文搜索适用于MyISAM表。你也是InnoDb的can workaround。您可以通过更改表格来简单地添加FT索引:

ALTER TABLE table ADD FULLTEXT(title,description);

答案 2 :(得分:3)

如果您使用LIKE '%term%'的查询,则无法使用索引。只有在使用'term%'之类的查询时才能使用它们。考虑一下带有标签的地址簿,您可以找到以字母L开头的非常快速的联系人,但要在单词的某处找到on的联系人,您需要扫描整个地址簿。

更好的选择可能是使用全文索引:

CREATE FULLTEXT INDEX title_desc
ON table (title, description)

然后在查询中:

SELECT title, description FROM table
WHERE MATCH (title, description) AGAINST ('+Pizza')

答案 3 :(得分:0)

我会选择JohnB&g或gtr32x的答案(全文索引)。为了补充他们的答案,可以通过手动方式创建一个简单且速度极快的简单全文索引...

将标题和描述拆分为关键字,并将它们放在Keywords表中,该表具有原始RSS文章的外键。确保将Keywords中的关键字列编入索引。你可以这样做:

SELECT DISTINCT ra.* 
FROM RssArticle ra
INNER JOIN Keywords k ON k.ArticleID = ra.ArticleID
   WHERE k IN ( 'SearchTerm1', 'SearchTerm2', 'SearchTerm3')
LIMIT 20;

而且速度很快!

答案 4 :(得分:0)

尝试以下四种查询之一:

select * from myTable where concat_ws(' ',title,description) like '%pizza%';
select * from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*';
select title,description from myTable where concat_ws(' ',title,description) like '%pizza%';
select title,description from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*';

重点是在搜索之前使用concat

答案 5 :(得分:-2)

一些指示:在select语句中删除*并仅提取搜索条件,并确保将索引添加到要搜索的列中。

SELECT `title`,`description` 
FROM `table` 
WHERE `title` LIKE '%$searchterm%' OR `description` LIKE '%$searchterm%' LIMIT 25;

答案 6 :(得分:-2)

  1. 您是否为titledescription创建了索引?
  2. 您应该考虑使用Sphinx全文搜索功能。

  3. 感谢Tyler的评论。

    我重申了我的回答:

    1)在titledescription列上创建索引,但您的查询仅限于以下示例,这不是查找所有相关行的理想选择:

    SELECT * 
    FROM 'table' 
    WHERE title LIKE 'searcherm%' OR description LIKE 'searcherm%'
    LIMIT 20;
    

    2)正如其他人所提到的,使用MySQL Full-Text Search,但您只能使用MyISAM表引擎,因为它不适用于InnoDB。但是,您可以在MySQL中混合引擎,因此即使所有其他表都是InnoDB,您也可以创建此表MyISAM。

    3)使用外部全文搜索引擎,例如Sphinx。这将为您提供更相关的搜索结果(MySQL全文搜索还有很多不足之处),它会表现得更好,并且它可以将全文搜索的负担从数据库中抽象出来。