簡體   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