简体   繁体   English

使用多个JOIN优化mysql查询

[英]Optimization of mysql query with multiple JOINs

I am building a mysql query to access videos according to access rights, but the only one I could come up with takes up to 0.5s to execute on our server. 我正在建立一个mysql查询来根据访问权限访问视频,但是我想出的唯一一个查询最多需要0.5s才能在我们的服务器上执行。

The access rights are rather flexible, so a bit complex. 访问权限相当灵活,因此有点复杂。 TABLES: 表格:

vod_reunion contains 1 line per video relevant columns are: Id (unique identifier) and "active" vod_reunion每个视频包含1行,相关列为 :id(唯一标识符)和“有效”

Each video belongs to 1 or more categories as per following table: 下表列出了每个视频的1个或多个类别:

vod_appart_droit ID_theme (Id of the categorie) ID_reunion (Id of the video, so matching the one of first table) vod_appart_droit ID_theme(类别的ID)ID_reunion(视频的ID,因此与第一个表格中的一个匹配)

Each user can belong to some groups: 每个用户可以属于一些组:

appartenance_groupe defines to which group belong which user: ID_groupe ID_membre Now the actual rights: appartenance_groupe定义哪个用户属于哪个组:ID_groupe ID_membre现在的实际权限:

vod_droit : ID_groupe: Id of the group if the record is about managing access to a group, otherwise "-1" ID_membre: Id of the user if the record is about managing access directly to a user, otherwise "-1" ID_theme: Id of the category which the user or group may access Droit: access level for this groupe or user to the category with values: 2: access allowed 1: access allowed for videos of this category having their flag "active" set at is 1 in the first table "vod_reunion" 0: no access to this category -1: forbids access to videos of this category for this user or group, even if the same video belongs to an other category to which the same group has access. vod_droit :ID_groupe:如果记录是关于管理对组的访问,则为该组的ID,否则为“ -1” ID_membre:如果记录是关于直接管理对用户的访问,则为该用户的ID,否则为“ -1” ID_theme:ID用户或组可以访问的类别的类别。Droit:该组或用户对该类别的访问级别,其值:2:允许访问1:允许对其标志设置为“有效”的该类别的视频进行访问第一个表“ vod_reunion” 0:不能访问此类别-1:禁止访问此用户或组的该类别的视频,即使同一视频属于同一组可以访问的其他类别。

So here is the query: 所以这是查询:

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))

Note that the where clause is actually simplified here, I only left parts related to access right, but there are then multiple criteria used for searching & sorting. 请注意,这里实际上简化了where子句,我只剩下与访问权限相关的部分,但是有多个条件用于搜索和排序。

Would you have any help on how to accelerate this query ? 您对如何加快此查询有任何帮助吗? Note that when I run it multiple times consecutively it can go extremely fast, but I guess this is due to some caching capabilities of mysql. 请注意,当我连续多次运行它时,它的运行速度可能非常快,但是我猜这是由于mysql的某些缓存功能所致。

Thank you Timothé 谢谢提摩太

This is too long for a comment. 这个评论太长了。

First, remove the distinct if it is not necessary. 首先,如果没有必要,请删除该distinct

Second, write the WHERE clause as r.langue IN (0, 2) and be sure there is an index on the column. 其次,将WHERE子句写为r.langue IN (0, 2)并确保该列上有一个索引。

Third, if you need the distinct, remove the joins. 第三,如果需要独特的连接,则删除连接。 Instead, use NOT EXISTS in the WHERE clause. 而是在WHERE子句中使用NOT EXISTS

These are some ideas that might help performance. 这些是可能有助于提高性能的想法。 I also assume that the obvious columns are correctly indexed (the columns used in the join s for instance). 我还假定明显的列已正确索引(例如, join使用的列)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM