Ваша формулировка запроса работает медленно по нескольким причинам, но я не уверен в деталях. Пожалуйста, предоставьте EXPLAIN FORMAT=JSON SELECT ...
для дальнейшего обсуждения.
А пока давайте перепишем запрос так, чтобы он работал быстрее. (И это может избавить от ошибки, с которой вы еще не сталкивались.)
Во-первых, давайте создадим отладку этого. Он выполняет 3 FT поиска в 3 отдельных запросах, а затем объединяет (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
Да, это JOINing
назад к questions
, но это оказывается быстрее.
Обратите внимание, что GROUP BY
здесь не требуется. И, если внутренний запрос имеет LIMIT
, он здесь не понадобится.
Я прошу прощения, если я не совсем все понял правильно; было больше преобразований, чем я ожидал.