我有一个稍微复杂的表结构,我正在尝试查询搜索功能,但我的查询保持超时。基本上,这是一本书籍搜索,我专注于搜索的主题部分。
主题表很简单(id和title),但是有一个链表可以将它引回给自己,称为subject_subjects,这会使事情变得复杂。
**subjects_subjects**
id (key)
subject_id (reference to subjects table)
see_subject_id (another reference to subjects table)
循环引用的原因是捕获不包含任何书籍的主题,但指向的主题。例如,“旅行”主题下没有书籍,因此该主题链接到包含书籍的“探索者”和“旅行”。关键是要使搜索更容易。
所以我要做的是让用户搜索“旅行”,但返回“探索者”和“旅行”的结果。这是我的查询超时:
SELECT
BK.id,
BK.title
FROM
books BK
LEFT OUTER JOIN
books_subjects BS
ON BS.book_id = BK.id
WHERE
BS.subject_id IN (1639,3173)
OR BS.subject_id IN
(
SELECT
SS.see_subject_id
FROM
subjects_subjects SS
WHERE
SS.subject_id IN (1639,3173)
)
GROUP BY
BK.books_id
额外信息:数据库中有17000本书和3000多个科目,大约有84000本书/科目参考。
任何人都可以帮我弄清楚我在哪里错了吗?
答案 0 :(得分:1)
你正在做两件MySQL优化不好的事情:
OR
在WHERE
子句中。
IN (SELECT ...)
使用与OR
结合的两个查询,而不是OR
。而不是IN (SELECT ...)
使用JOIN
。
此外,如果您不需要从第一个表中返回第二个表中没有匹配项的行,则不应使用LEFT JOIN
,请使用INNER JOIN
。
SELECT b.id, b.title
FROM books AS b
JOIN books_subjects AS bs ON bs.book_id = b.id
WHERE bs.subject_id IN (1639, 3173)
UNION
SELECT books AS b
JOIN books_subjects AS bs ON bs.book_id = b.id
JOIN subjects_subjects AS ss ON bs.subject_id = ss.see_subject_id
WHERE ss.subject_id IN (1639, 3173)