繁体   English   中英

慢MySQL全文搜索

[英]Slow MySQL full text search

我正在使用此查询在MySQL数据库上执行全文搜索:

SELECT DISTINCT 
questions.id, 
questions.uniquecode, 
questions.spam,
questions.questiondate,
questions.userid,
questions.description,
users.login AS username,
questions.questiontext,
questions.totalvotes,
MATCH(questions.questiontext, questions.uniquecode) 
AGAINST ('rock guitarist chick*' IN BOOLEAN MODE) AS relevance 

FROM questions 

LEFT JOIN users ON questions.userid = users.id 
LEFT JOIN answer_mapping ON questions.id = answer_mapping.questionid 
LEFT JOIN answers ON answer_mapping.answerid = answers.id
LEFT JOIN tagmapping ON questions.id = tagmapping.questionid
LEFT JOIN tags ON tagmapping.tagid = tags.id 

WHERE questions.spam < 10 

AND 

(
  MATCH(questions.questiontext, questions.uniquecode) 
  AGAINST ('rock guitarist chick*' IN BOOLEAN MODE) 

OR MATCH(answers.answertext) AGAINST ('rock guitarist chick*' IN BOOLEAN MODE) 

OR MATCH (tags.tag) AGAINST ('rock guitarist chick*' IN BOOLEAN MODE)

) GROUP BY questions.id ORDER BY relevance DESC

结果非常相关,但搜索速度非常慢,并且随着表的增长而越来越慢。

表统计:

问题 - 400条记录

索引

  • 主要的BTREE - 身份证
  • BTREE - 唯一代码
  • BTREE - 质疑
  • BTREE - 用户ID
  • FULLTEXT - 问题文本
  • FULLTEXT - 唯一代码

答案 - 3,635条记录

索引

  • 主要 - BTREE - 身份证
  • BTREE - 回答日期
  • BTREE - 问题
  • FULLTEXT - answertext

answer_mapping - 4,228条记录

索引

  • 主要 - BTREE - 身份证
  • BTREE - 答案
  • BTREE - 问题
  • BTREE - 用户ID

标签 - 1,847条记录

索引

  • 主要 - BTREE - 身份证
  • BTREE - 标签
  • FULLTEXT - 标签

tagmapping - 3,389条记录

索引

  • 主要 - BTREE - 身份证
  • BTREE - tagid
  • BTREE - 问题

无论出于何种原因,当我删除标记 映射标记 JOINS时,搜索速度会大大提高。

您对如何加快查询速度有任何提示吗?

提前致谢!

好吧,你可以将你的连接组合成缓存视图或额外的表或其他东西。 让您的查询缓存处于活动状态,并将您的连接定义为选择,以便可以缓存它。 确保足够的内存等,但这不应该成为瓶颈。 很可能在你的情况下,因为...只有400条记录? 没什么......而且已经慢了? 因为其余的看起来不错。 你在运行什么样的硬件/配置?

但是,我认为这是错误的做法。 mysql不是为此而设计的。 实际上全文功能仅限于myisam。

你应该考虑使用dismax请求处理程序使用lucene / solr 它应该在大约50ms-100ms给你很好的结果,索引一些hundret千文件。 在某些时候你可以对它进行分片,因此记录的数量是非常无限的。 加上你有更好的选择,可以取得更好的结果。 例如,做模糊匹配或给予较新文档更多权重或使标签与标题更相关,进行后查询分析,分面等...

您也可以尝试运行OPTIMIZE TABLE questions

它帮助加快了我正在进行的项目中的类似查询。

参见参考: https//dev.mysql.com/doc/refman/5.7/en/fulltext-fine-tuning.html

由于多种原因,您对查询的表述工作缓慢,但我不确定细节。 请提供EXPLAIN FORMAT=JSON SELECT ...以供进一步讨论。

同时,让我们以一种应该更快的方式重写查询。 (它可能会摆脱你尚未遇到的错误。)

首先,让我们构建一个调试。 它在3个独立的查询中的3个FT搜索,然后组合( UNION只是 question_ids从每个。

    ( SELECT question_id,
         MATCH (... ) as relevance
         FROM questions
         WHERE MATCH (questiontext, ...) AGAINST ... )
    UNION ALL
    ( SELECT am.question_id,
         MATCH (... ) as relevance
         FROM answers AS a
         JOIN answer_mapping AS am ON am.answerid = a.id
         WHERE MATCH (a.answertext) AGAINST ... )
    UNION ALL
    ( SELECT tm.question_id,
         MATCH (... ) as relevance
         FROM tags AS t
         JOIN tagsmapping tm ON ...
         WHERE MATCH (t.tag) AGAINST ... )

注意每个子查询是如何设计为以带有FT索引的表开始 ,最后是question_id

现在,一个中间查询:

SELECT question_id,
         MAX(relevance)  -- (this fixes the unseen bug)
    FROM ( that query ) AS q1
    GROUP BY question_id
    ORDER BY relevance DESC  -- optional; needed for `LIMIT`
    LIMIT 20          -- to limit the rows, do it at this stage

如果运行得足够快,并提供“正确”的question_ids ,那么我们可以继续......

使用它作为子查询来获取其余数据:

SELECT .... -- the `questions` fields, using `q....`,
       ( SELECT login FROM users WHERE q.userid = id ) AS username
    FROM ( the intermediate query ) AS q2
    JOIN questions AS q
    questions q.spam < 10 
    ORDER BY q2.relevance

是的,这是JOINingquestions ,但原来要快。

请注意, GROUP BY不在此处。 并且,如果内部查询具有LIMIT ,则此处不需要它。

如果我没有把一切都搞定,我道歉; 有比我预期更多的转变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM