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 毫秒。分析后发现,大部分时间都花在创建排序索引上。 (完整详细信息: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;
执行此查询需要 23 毫秒并进行全表扫描,我不喜欢全表扫描。
问题是,查询 #1 是我需要使用的查询,因为排序非常重要。
我可以做些什么来加速该查询/重写它并获得相同的结果(如#1)?
感谢任何意见和帮助。
最佳答案
也许您只是期望太多? 350ms 执行一次
MATCH(作者、标题、内容) AGAINST('搜索关键字')
- 排序依据
120k 唱片对我来说听起来并不算太糟糕;特别是如果 content
是“大”...
请记住,为了让“SLOW QUERY”发挥作用,系统必须读取每一行,计算分数,然后最后对所有分数进行排序,找出最低的 10 个值并然后返回它的所有相关行信息。如果您省略ORDER BY
,那么它只会选择前10行,并且只需要计算分数
对于这 10 行。
也就是说,我认为 EXPLAIN
有点误导,因为它似乎将所有事情都归咎于 SORT,而很可能是 MATCH 占用了大部分时间。我猜测 MATCH()
运算符以“惰性”方式执行,因此仅在请求数据时运行,在本例中是在排序发生时运行。
要解决这个问题,只需添加一个新列 score
并将查询分成两部分。
更新文章 SET Score = MATCH()
等... => 我猜大约需要 300 毫秒从文章中选择文章 ID、标题、作者、内容、日期、分数 ORDER BY 分数 DESC LIMIT 10;
=> 我猜大约需要 50 毫秒
当然,这不是可行的解决方案,但如果我是对的,它会告诉你,你的问题不在于排序,而在于全文搜索......
PS:您忘记提及表上的索引是什么,了解一下也可能有用。比照https://dev.mysql.com/doc/refman/5.7/en/innodb-fulltext-index.html
关于mysql - 查询优化,我还能做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42247703/