提高MySQL全文搜索查询的性能

时间:2015-07-02 10:38:26

标签: mysql sql full-text-search

我有以下MySQL查询:

SELECT p.*, MATCH (p.description) AGAINST ('random text that you can use in sample web pages or typography samples') AS score 
FROM posts p 
WHERE p.post_id <> 23 
AND MATCH (p.description) AGAINST ('random text that you can use in sample web pages or typography samples') > 0 
ORDER BY score DESC LIMIT 1

有108,000行,需要 ~200ms 。有265,000行,需要 ~500ms

在性能测试(约80个并发用户)下,它显示 ~18sec 平均延迟。

有没有办法提高此查询的效果?

EXPLAIN OUTPUT:

enter image description here

已更新

我们添加了一个带有post_iddescription的新镜像MyISAM表,并通过触发器将其与posts表同步。现在,在这个新的MyISAM表上进行全文搜索 ~400ms (具有相同的性能负载,其中InnoDB显示 ~18sec ..这是一个巨大的性能提升)看起来像MyISAM是MySQL中的全文比InnoDB快得多。你能解释一下吗?

MySQL分析器结果:

AWS RDS db.t2.small 实例

上进行测试

原始InnoDB posts表:

enter image description here

带有post_id的MyISAM镜像表,仅供说明:

enter image description here

3 个答案:

答案 0 :(得分:5)

Here提供了一些提示,以便通过InnoDB最大限度地提高查询速度:

  
      
  1. 避免多余排序。由于InnoDB已根据排名对结果进行了排序。 MySQL查询处理层不需要   排序以获得最佳匹配结果。

  2.   
  3. 避免逐行提取以获得匹配计数。 InnoDB提供所有匹配的记录。所有不在结果列表中的人   应该都排名为0,不需要检索。和InnoDB   有一个总的匹配记录计数。无需重新计票。

  4.   
  5. 涵盖索引扫描。 InnoDB结果始终包含匹配记录的文档ID及其排名。所以,如果只有文件ID和   需要排名,没有必要去用户表来获取   记录自己。

  6.   
  7. 尽早缩小搜索结果,减少用户表访问权限。如果用户想要获得前N个匹配记录,我们不需要获取   来自用户表的所有匹配记录。我们应该能够先行   选择TOP N匹配的DOC ID,然后只获取相应的   具有这些文档ID的记录。

  8.   

我不认为你只能查看查询本身就不会那么快,也许尝试删除ORDER BY部分以避免不必要的排序。要深入研究这个问题,可以使用MySQLs inbuild profiler对查询进行概要分析。

除此之外,您可以查看MySQL服务器的配置。看一下this chapter of the MySQL manual,它包含了一些关于如何根据需要调整全文索引的良好信息。

如果您已经最大化了MySQL服务器配置的功能,那么请考虑查看硬件本身 - 有时甚至是丢失的成本解决方案,例如将表移动到另一个,更快的硬盘驱动器可以创造奇迹。

答案 1 :(得分:3)

评论太长了。

我对性能命中的最佳猜测是查询返回的行数。要对此进行测试,只需删除order by score并查看是否可以提高性能。

如果没有,则问题是全文索引。如果是,则问题是order by。如果是这样,问题就变得有点困难了。一些想法:

  • 确定硬件解决方案以加快排序(将中间文件放入内存中)。
  • 修改查询,使其返回的值更少。这可能涉及更改停用词列表,将查询更改为布尔模式或其他想法。
  • 寻找另一种预过滤结果的方法。

答案 2 :(得分:0)

这里的问题是WHERE p.post_id <> 23 以这样一种方式设计系统,使非索引列不必添加到WHERE子句中。基本上,MySQL将搜索全文索引列,然后过滤post_id。因此,如果全文搜索返回很多匹配项,则响应时间将与预期不符。