优化了具有多个 JOIN 的 mysql 查询


Optimization of mysql query with multiple JOINs

我正在构建一个 mysql 查询以根据访问权限访问视频,但我唯一能想到的查询在我们的服务器上执行最多需要 0.5 秒。

访问权限相当灵活,因此有点复杂。表:

vod_reunion每个视频包含 1 行 相关列包括:ID(唯一标识符)和"活动"

每个视频属于下表中的一个或多个类别:

vod_appart_droit ID_theme(分类的ID) ID_reunion(视频的 ID,因此与第一个表的 ID 匹配)

每个用户可以属于某些组:

appartenance_groupe定义哪个组属于哪个用户: ID_groupe ID_membre现在实际权利:

vod_droit: ID_groupe:如果记录是关于管理对组的访问,则为组的 ID,否则为"-1" ID_membre:如果用户的 ID,如果记录是关于直接管理对用户的访问,否则为"-1" ID_theme:用户或组可以访问的类别的 ID 权限:此组或用户对具有以下值的类别的访问权限级别: 2:允许访问 1:允许此类别的视频在第一个表格"vod_reunion"中将其标志"有效"设置为 1 0:无法访问此类别 -1:禁止此用户或群组访问此类别的视频,即使同一视频属于同一群组有权访问的其他类别。

所以这是查询:

SELECT
     DISTINCT r.*, vu.vu
FROM
vod_reunion r
LEFT JOIN
    (
        vod_appart_droit ad
    INNER JOIN
        vod_droit vd
        ON
        ad.ID_theme = vd.ID_theme AND 
        (vd.Droit =2 OR vd.Droit=1)
    INNER JOIN
        appartenance_groupe ag
        ON
        vd.ID_groupe = ag.ID_groupe AND
        ag.ID_membre=11
    )
    ON
    r.Id = ad.ID_reunion AND 
    (vd.Droit =2 OR (vd.Droit=1 AND r.active=1))

    LEFT JOIN
    (
        vod_appart_droit adn
    INNER JOIN
        vod_droit vnd
        ON
        adn.ID_theme = vnd.ID_theme AND 
        vnd.Droit =-1
    INNER JOIN
        appartenance_groupe ang
        ON
        vnd.ID_groupe = ang.ID_groupe AND
        ang.ID_membre=11  
    )
    ON
    r.Id = adn.ID_reunion AND
    ag.ID_groupe = ang.ID_groupe

    LEFT JOIN
    (
        vod_appart_droit adm
    INNER JOIN
        vod_droit vdm
        ON
        adm.ID_theme = vdm.ID_theme AND 
        (vdm.Droit =2 OR vdm.Droit=1) AND
        vdm.ID_membre=11
    )
    ON
    r.Id = adm.ID_reunion AND 
    (vdm.Droit =2 OR (vdm.Droit=1 AND r.active=1))
    LEFT JOIN
    (
        vod_appart_droit adnm
    INNER JOIN
        vod_droit vndm
        ON
        adnm.ID_theme = vndm.ID_theme AND 
        vndm.Droit =-1 AND
        vndm.ID_membre=11
    )
    ON
    r.Id = adnm.ID_reunion
    LEFT JOIN 
    vod_vu vu ON r.Id=vu.ID_reunion AND vu.ID_membre='11'
WHERE
    (r.langue = 0 OR r.langue = 2) AND
    ((vd.Droit IS NOT NULL AND vnd.Droit IS NULL) OR
    (vdm.Droit IS NOT NULL AND vndm.Droit IS NULL))

请注意,where 子句实际上在这里得到了简化,我只留下了与访问权相关的部分,但随后有多个条件用于搜索和排序。

您对如何加速此查询有任何帮助吗?请注意,当我连续多次运行它时,它可以非常快,但我想这是由于 mysql 的一些缓存功能。

谢谢蒂莫西

这太长了,无法发表评论。

首先,如果没有必要,请移除distinct

其次,将 WHERE 子句编写为 r.langue IN (0, 2)并确保列上有索引。

第三,如果需要区分,请删除联接。 相反,请在WHERE子句中使用NOT EXISTS

这些是一些可能有助于性能的想法。 我还假设明显的列被正确索引(例如join中使用的列)。