使用多个JOIN优化mysql查询

时间:2015-06-15 11:05:24

标签: php mysql

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

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

vod_reunion 每个视频包含1行     相关列是:Id(唯一标识符)和“活动”

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

vod_appart_droit     ID_theme(类别的ID)     ID_reunion(视频的ID,所以匹配第一个表格之一)

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

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

vod_droit :     ID_groupe:如果记录是关于管理对组的访问权限,则为组的ID,否则为“-1”     ID_membre:用户的ID,如果记录是关于直接管理对用户的访问,否则为“-1”     ID_theme:用户或组可以访问的类别的ID     Droit:此groupe或用户访问级别为值的类别:         2:允许访问         1:允许此类别的视频在第一个表“vod_reunion”中将其标记为“active”设置为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的一些缓存功能。

谢谢 Timothé

1 个答案:

答案 0 :(得分:0)

评论太长了。

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

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

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

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