查询优化,我还能做啥?

Posted

技术标签:

【中文标题】查询优化,我还能做啥?【英文标题】:Query Optimization, What more can I do?查询优化,我还能做什么? 【发布时间】:2017-02-15 11:10:56 【问题描述】:
Table type: MyISAM
Rows: 120k
Data Length: 30MB
Index Length: 40MB

my.ini,MySQL 5.6.2 Windows

read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 16M

Windows Server 2012,12GB RAM,SSD 400MB/s

1 慢查询:

SELECT article_id, title, author, content, pdate, MATCH(author, title, content) 
AGAINST('Search Keyword') AS score FROM articles ORDER BY score DESC LIMIT 10;

执行此查询需要 352 毫秒使用索引。 profiling 后,显示大部分时间都花在了创建排序索引上。 (完整详情:http://pastebin.com/raw/jT58DCN5)

2 更快的查询:

SELECT article_id, title, author, content, pdate, MATCH(author, title, content) 
AGAINST('Search Keyword') AS score FROM articles LIMIT 10;

执行此查询需要 23ms 并进行全表扫描,我不喜欢全表扫描。

问题/疑问是,查询 #1 是我需要使用的,因为排序非常重要。

我能做些什么来加快查询/重写它并获得相同的结果(如 #1)?

感谢任何意见和帮助。

【问题讨论】:

【参考方案1】:

也许您只是期望过高? 350ms 做一个

MATCH(author, title, content) AGAINST('Search Keyword') 订购人

对我来说,120k 唱片听起来并不太寒酸;特别是如果content 是“大”...

请记住,要使您的“慢查询”起作用,系统必须读取每一行,计算分数,然后最后对所有分数进行排序,找出最低的 10 个值并然后为其返回所有相关的行信息。如果您省略了 ORDER BY,那么它只会选择 前 10 行,并且只需要计算这 10 行的 score

也就是说,我认为EXPLAIN 有点误导,因为它似乎将所有事情都归咎于 SORT,而很可能是 MATCH 占用了大部分时间。我猜MATCH() 运算符是以“惰性”方式执行的,因此仅在要求数据时运行,在这种情况下是在排序发生时。

要解决这个问题,只需添加一个新列score 并将查询分成两部分。

UPDATE articles SET score = MATCH() 等... => 我猜大约需要 300 毫秒 SELECT article_id, title, author, content, pdate, score FROM articles ORDER BY score DESC LIMIT 10; => 我猜大概需要 50 毫秒

当然,这不是可行的解决方案,但如果我是对的,它会告诉您您的问题不在于 SORT,而是在于全文搜索......

PS:您忘记提及表上的索引是什么,知道也可能有用。 cfhttps://dev.mysql.com/doc/refman/5.7/en/innodb-fulltext-index.html

【讨论】:

嗯,内容不大,varchar 255是content字段的最大长度,也就是最大的那个。我有关于作者、标题、内容的所有类型 varchar 的索引,并且符合 FULL TEXT SEARCH 要求。我并不是说我对现在的情况不满意,但该网站正在发展,我只是想确保在投资其他任何东西之前,我已经用这些资源做了可能做的事情。我确实有一些其他选项可能是更有效的优化选项,而不是那个查询。非常感谢任何其他可以提供帮助的意见。【参考方案2】:

试试这些变体:

AGAINST('word')
AGAINST('+word')
AGAINST('+word' IN BOOLEAN MODE)

试试

SELECT ... MATCH ...,
    FROM tbl
    WHERE  MATCH ...  -- repeat the test here
    ...

测试是消除根本不匹配的行,从而大大减少要排序的行数。 (同样,取决于+BOOLEAN。)

(我通常使用所有三个:+BOOLEANWHERE MATCH。)

key_buffer_size = 2G 也可能有帮助。

您应该考虑迁移到 InnoDB,因为 FT 更快。

【讨论】:

以上是关于查询优化,我还能做啥?的主要内容,如果未能解决你的问题,请参考以下文章

Postgres:按日期时间优化查询

启用僵尸对象不足以帮助调试我的问题 - 我还能做啥?

当 sleep() 不能很好地与警报一起工作时,我还能做啥“睡眠”?

如何优化mysql中的大表?

如何优化使用游标的 PL/SQL 代码

K:leetcode 5381.查询带键的排列 这题简单,但我还能优化。精益求精,才是算法的乐趣所在!