我有以下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:
已更新
我们添加了一个带有post_id
,description
的新镜像MyISAM表,并通过触发器将其与posts
表同步。现在,在这个新的MyISAM表上进行全文搜索 ~400ms (具有相同的性能负载,其中InnoDB显示 ~18sec ..这是一个巨大的性能提升)看起来像MyISAM是MySQL中的全文比InnoDB快得多。你能解释一下吗?
MySQL分析器结果:
在 AWS RDS db.t2.small 实例
上进行测试 原始InnoDB posts
表:
带有post_id的MyISAM镜像表,仅供说明:
答案 0 :(得分:5)
Here提供了一些提示,以便通过InnoDB最大限度地提高查询速度:
避免多余排序。由于InnoDB已根据排名对结果进行了排序。 MySQL查询处理层不需要 排序以获得最佳匹配结果。
避免逐行提取以获得匹配计数。 InnoDB提供所有匹配的记录。所有不在结果列表中的人 应该都排名为0,不需要检索。和InnoDB 有一个总的匹配记录计数。无需重新计票。
涵盖索引扫描。 InnoDB结果始终包含匹配记录的文档ID及其排名。所以,如果只有文件ID和 需要排名,没有必要去用户表来获取 记录自己。
- 醇>
尽早缩小搜索结果,减少用户表访问权限。如果用户想要获得前N个匹配记录,我们不需要获取 来自用户表的所有匹配记录。我们应该能够先行 选择TOP N匹配的DOC ID,然后只获取相应的 具有这些文档ID的记录。
我不认为你只能查看查询本身就不会那么快,也许尝试删除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。因此,如果全文搜索返回很多匹配项,则响应时间将与预期不符。