【问题标题】:query optimisation with join on ordered data对有序数据进行联接的查询优化
【发布时间】:2012-11-30 20:36:33
【问题描述】:

我的问题是关于查询 sql 的优化。

我的查询检索成员列表及其上一次培训。

为了获得最新的培训,我对返回所有成员培训的完整列表的查询结果进行联接。

此查询有效,但速度很慢,如果有人能提供更快执行的解决方案,我真的很感兴趣。

我的查询(大约 16 秒):

SELECT 
    m.nom,
    m.prenom,
    m.ville,
    m.maj,
    mbf.libelle,
    mbf.datefin,
    m.id as idmb
FROM
    membres m
    LEFT JOIN (
        select *
        from membreform
        where idformation = 1
        order by datefin DESC
    ) as mbf ON mbf.idmembre = m.id
WHERE
    role > 0 AND visible = 1
group by m.id
ORDER BY m.maj DESC
limit 0 , 20

我的数据结构:

membreform(1000 个条目)

  • id int(11) NOT NULL AUTO_INCREMENT,
  • idmembre int(11) 非空,
  • libelle varchar(128) NOT NULL,
  • idformation int(11) 非空,
  • datedebut 日期不为空,
  • datefin date NOT NULL DEFAULT '0000-00-00',
  • descript 文本不为空,
  • 密钥id(id),
  • 密钥idmembre(idmembre),
  • 密钥idformation (idformation)

成员(500 个条目)

  • id int(3) NOT NULL AUTO_INCREMENT,
  • nom varchar(255) NOT NULL,
  • prenom varchar(255) 非空,
  • ville varchar(255) NOT NULL,
  • email varchar(255) NOT NULL,
  • maj datetime NOT NULL,
  • role tinyint(4) NOT NULL DEFAULT '1',
  • 主键 (id),
  • 密钥role(role),
  • 密钥maj (maj)

我用另一种方式测试过(大约 0.40 秒),但我觉得不是很干净

SELECT 
    m.nom,
    m.prenom,
    m.ville,
    m.maj,
    m.id as idmb,
    (select 
            libelle
        from
            membreform
        where
            idformation = 1
                AND m.id = membreform.idmembre
        order by datefin DESC
        limit 1
    ) libelle,
    (select 
            datefin
        from
            membreform
        where
            idformation = 1
                AND m.id = membreform.idmembre
        order by datefin DESC
        limit 1
    ) datefin
FROM
    membres m
WHERE
    role > 0 AND visible = 1
group by m.id
ORDER BY m.maj DESC
limit 0 , 20

我愿意接受任何建议,因为我有点卡住了

谢谢

【问题讨论】:

    标签: optimization join


    【解决方案1】:

    您可以使用临时表来提高性能。例如(MS SQL) 1 步 - 通过添加所有相关的 where 条件将 memberform 数据放入临时表中

    选择 * 进入#TempMembreform 来自 membreform 其中 idformation = 1 ... 按 datefin DESC 排序

    2 步 - 像在上面的第一个示例中那样执行左外连接。 例如

    SELECT 
        m.nom,
        m.prenom,
        m.ville,
        m.maj,
        mbf.libelle,
        mbf.datefin,
        m.id as idmb
    FROM
        membres m
        LEFT JOIN #TempMembreForm as mbf 
            ON mbf.idmembre = m.id
    WHERE
        role > 0 AND visible = 1
    group by m.id
    ORDER BY m.maj DESC
    limit 0 , 20
    

    3 步 - 如果数据不是关键任务(例如银行交易),则添加 NOLOCK 关键字

    select *
    INTO #TempMembreform 
    from membreform WITH(NOLOCK)
    where idformation = 1
    order by datefin DESC
    
    SELECT 
        m.nom,
        m.prenom,
        m.ville,
        m.maj,
        mbf.libelle,
        mbf.datefin,
        m.id as idmb
    FROM
        membres m with(nolock)
        LEFT JOIN #TempMembreForm as mbf 
            ON mbf.idmembre = m.id
    WHERE
        role > 0 AND visible = 1
    group by m.id
    ORDER BY m.maj DESC
    limit 0 , 20
    

    My profile

    【讨论】:

    • 感谢您的快速答复。经过几次测试后,我可以通过简单的修改来加快查询速度> 我在连接查询中指定了字段(而不是 *)> 执行现在需要 0.12 秒 :) 我很惊讶这个简单的更改会产生如此大的影响,但是事实上它有效!
    猜你喜欢
    • 2016-10-27
    • 2012-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多