MySQL加入循环引用查询

时间:2017-09-07 01:27:42

标签: mysql

我有一个稍微复杂的表结构,我正在尝试查询搜索功能,但我的查询保持超时。基本上,这是一本书籍搜索,我专注于搜索的主题部分。

主题表很简单(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本书/科目参考。

任何人都可以帮我弄清楚我在哪里错了吗?

1 个答案:

答案 0 :(得分:1)

你正在做两件MySQL优化不好的事情:

    {li> ORWHERE子句中。
  1. IN (SELECT ...)
  2. 使用与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)