在这种情况下如何提高搜索速度?

时间:2009-11-22 20:15:43

标签: mysql query-optimization

我在我的网站上实施了搜索,它运行以下查询:

SELECT COUNT(mov_id) AS total_things 
FROM content
    WHERE con_status = 1 AND con_incomplete = 0 AND con_type = 1 
            AND ((con_title) LIKE ('%search keyword%') 
            OR soundex(con_title) LIKE soundex('search keyword')
            OR MATCH (con_title) AGAINST ('search keyword'));

+----+-------------+--------+------+---------------+----------+---------+-------------------+-------+-------------+
| id | select_type | table  | type | possible_keys | key      | key_len | ref               | rows  | Extra       |
+----+-------------+--------+------+---------------+----------+---------+-------------------+-------+-------------+
|  1 | SIMPLE      | movies | ref  | con_type      | con_type | 12      | const,const,const | 11804 | Using where |
+----+-------------+--------+------+---------------+----------+---------+-------------------+-------+-------------+

64058查询

总时间:200817,平均时间:3.13492459958163

需要2到25秒才能完成

行分析1882 - 12104


SELECT 
            con_id, 
            con_title, 
            con_desc,
            MATCH (con_title) AGAINST ('search keyword') AS relevancy 
    FROM content
    WHERE con_status = 1 AND con_incomplete = 0 AND con_type = 1 
            AND ((con_title) LIKE ('%search keyword%') 
            OR soundex(con_title) LIKE soundex('search keyword')
            OR MATCH (con_title) AGAINST ('search keyword')) 
    ORDER BY relevancy DESC 
    LIMIT 0, 24;

+----+-------------+--------+------+---------------+----------+---------+-------------------+-------+-----------------------------+
| id | select_type | table  | type | possible_keys | key      | key_len | ref               | rows  | Extra                       |
+----+-------------+--------+------+---------------+----------+---------+-------------------+-------+-----------------------------+
|  1 | SIMPLE      | movies | ref  | con_type      | con_type | 12      | const,const,const | 11803 | Using where; Using filesort |
+----+-------------+--------+------+---------------+----------+---------+-------------------+-------+-----------------------------+

78321查询

总时间:200657,平均时间:2.56198209930925

需要2到16秒才能完成

行分析0 - 15752

这基本上就像一个贫民窟“模糊搜索”,以忽略人们可能犯的错别字。

不幸的是,它非常慢(即使我删除了soundex()或FULLTEXT搜索。如何在这种情况下提高搜索速度?

5 个答案:

答案 0 :(得分:2)

伤害的WHERE子句部分是%之后的第一个LIKE。为了加快速度,您可以将关键字规范化,将它们移到单独的表中:

table moviekeywords: movieid, keyword
table movies:        movieid, ...

这允许您使用moviekeywords条件或至少=搜索like 'humphrey%'表。两种变体都可以用索引快速制作。

答案 1 :(得分:0)

只要您继续使用soundex和LIKE(%nnn%),您将运行所有中间结果的完整扫描。为了说明这一点:如果省略了其他谓词(在con_status,con_incomplete和con_type列上),您将始终运行全表扫描。

我建议删除或缩减模糊谓词。例如,只运行LIKE('nnn%')将比%nnn%快得多(如果该列被索引),但当然搜索结果不会模糊。也许使soundex成为一种并不总能运行的高级搜索选项。

如果您无法在任何问题上妥协,那么至少要确保您的con_status,con_incomplete和con_type列都已编入索引。

答案 2 :(得分:0)

如果原始更严格的查询中的COUNT没有返回任何结果,那么我将“模糊搜索”作为后备选项。到目前为止,我的结果使用

非常快
 SOUNDS LIKE ('blah')

答案 3 :(得分:0)

再次考虑Andomar的解决方案 - 大多数关键字搜索允许您指定多个关键字。您不能使用当前查询执行此操作。 “终结者”没有问题 - 为此,你只需添加一个关键词“终结者”。

使用关键字列的索引,它会很快。

答案 4 :(得分:0)

所以看起来你只有大约15,000行。如果你不希望你的表增长超过十万条左右,也许你应该将所有标题保留在内存中并避免访问数据库,直到你知道你想要哪些条目。

也就是说,在启动时和定期间隔,只查询数据库中的所有标题,将每个标题分成单词,并保持单词到行键的映射。这应该占用不到1MB的内存,访问它应该非常快,最重要的是你可以添加你喜欢的任何模糊匹配或启发式评分机制(不修改你的模式)。

只是一个想法。