我有一个包含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秒。
有没有更好的方法来编写查询,我是否必须缓存结果(我将如何做?)或者更改数据库结构中的某些内容会加快查询速度(索引?)
答案 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);
确保在标题,说明上一起添加全文索引。
不要试图重新发明轮子。 MATCH
和AGAINST
正是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)
title
和description
创建了索引?感谢Tyler的评论。
我重申了我的回答:
1)在title
和description
列上创建索引,但您的查询仅限于以下示例,这不是查找所有相关行的理想选择:
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全文搜索还有很多不足之处),它会表现得更好,并且它可以将全文搜索的负担从数据库中抽象出来。