【问题标题】:Optimize a mysql query with left join, group by and order by使用左连接、分组和排序优化 mysql 查询
【发布时间】:2017-03-08 17:15:00
【问题描述】:

这个查询不是我写的,我必须优化:

SELECT DISTINCT r.itemid
              , r.catid
              , i.title
              , i.owner
              , i.image
              , i.background
              , i.icon 
           FROM jos_sobi2_cat_items_relations r
           LEFT 
           JOIN jos_sobi2_item i
             ON i.itemid = r.itemid 
          WHERE
              ( i.published = 1 
            AND r.catid > 1 

            AND  ( i.publish_down > '2016-10-26 13:08:02' 
                OR i.publish_down = '0000-00-00 00:00:00' 
                 ) 

            AND i.itemid IN ( SELECT itemid 
                                FROM jos_sobi2_item 
                               WHERE ( published = 1

                                   AND ( publish_down > '2016-10-26 13:08:02' 
                                      OR publish_down = '0000-00-00 00:00:00'
                                       )

                                     )
                            )
              )
          GROUP 
             BY i.itemid 
          ORDER 
             BY i.publish_up DESC 
          LIMIT 0,14

这是解释mysql的命令:

“items”表确实只有 itemid 字段的主键。 “关系”表确实有这 3 个索引:

- catid,itemid PRIMARY BTREE
- itemid BTREE
- catid BTREE

我看到如果我删除 DISTINCT 或 GROUP BY 子句,查询速度很快,否则执行需要超过 1 分钟。

我的第一个想法是删除 DISTINCT 子句,因为 GROUP BY 子句已经完成了这项工作。但我不确定。

对如何优化有帮助吗?

谢谢。

【问题讨论】:

  • 此查询甚至无法在其他数据库上运行,包括某些版本的 MySQL,因为您选择的是非聚合列。
  • 很遗憾不是我写的,所以才求助
  • published = 1 是否暗示 `publish_down = '0...' 不可能发生?
  • LEFT JOIN i,然后你 GROUP BYORDER BY i.... -- LEFT JOIN 在行丢失时提供 NULL。也许应该删除LEFT??

标签: mysql performance join


【解决方案1】:

起初,items.itemid IN (...) 是多余的,您在查询中已经有了这些条件。不需要 LEFT JOIN,项目行在 where 条件下,不能缺少。您也不需要 distinct 或 group by,[relation.itemid,relation.catid] 是主键,它不能包含重复项。所以结果是:

SELECT relation.itemid, relation.catid, title, owner, image, background, icon FROM
    `jos_sobi2_cat_items_relations` AS relation
JOIN `jos_sobi2_item` AS items ON relation.itemid = items.itemid WHERE
    `published` = '1' AND
    relation.catid > 1 AND
    (`publish_down` > '2016-10-26 13:08:02' OR `publish_down` = '0000-00-00 00:00:00' )     
ORDER BY items.publish_up DESC, relation.itemid, relation.catid LIMIT 0, 14

您可以将结果与原始查询进行比较。我在relation.itemid 和relation.catid 上添加了顺序,以便结果是确定性的。如果需要,您可以在 items.publish_up 上添加索引以加快查询速度。

【讨论】:

  • 为了获得相同的结果,我必须添加 DISTINCT 和 GROUP BY 子句,但问题仍然存在。查询太慢了。
  • 我预计引擎会自动按选择中的所有列分组,我没有意识到mysql实际上以不同的方式解释它。在这种情况下,查询不相等。但我建议您重新考虑您的查询应该做什么,因为它不像您现在拥有的那样具有确定性。它不能被优化,因为它的结果是不可预测的。
猜你喜欢
  • 2017-04-04
  • 2016-01-26
  • 2020-02-14
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 2012-11-26
相关资源
最近更新 更多