【问题标题】:Mysql SLOW UNION query when using ORDER BY clause使用 ORDER BY 子句时的 Mysql SLOW UNION 查询
【发布时间】:2013-01-25 18:01:36
【问题描述】:

我有两张表:附件和订单。

[accessories.category] ​​包含类别列表,即 Red、Green、Blue ... orders 表包含过去订单的列表。

我要选择:

10 records from [accessories.category] WHERE category = 'Red' AND
10 records from [accessories.category] WHERE category = 'Green' AND
10 records from [accessories.category] WHERE category = 'Blue'

我还想引用连接 [accessories.catno] 的订单表,它等于 [orders.catno],仅显示 [accessories.stocklevel] >0 的产品,并按 COUNT(orders.sold) DESC (首先显示畅销商品)。

因为我想从每个类别中获取一定数量的记录,所以我认为 UNION ALL 查询是合适的,而且确实有效。 问题是投入生产的速度不够快,因为在我的开发盒上执行需要 0.3 秒。 如果我删除“ORDER BY sold DESC”,查询只需 0.0236 秒,这是可以接受的。问题是我不能丢失 ORDER BY。

顺便说一句:我已经索引了我需要的所有字段。这是查询:

(SELECT 
accessories.catno, 
accessories.category, 
accessories.header, 
accessories.description, 
accessories.specialoffer, 
accessories.picture, 
accessories.unit, 
accessories.addinfo, 
accessories.post, 
accessories.price, 
accessories.vat, 
accessories.soundclip, 
COUNT(orders.catno) AS sold 
FROM 
accessories, orders 
WHERE 
orders.catno = accessories.catno 
AND 
accessories.category = 'Red' 
AND accessories.stocklevel > 0 AND 
accessories.category = 'Red' 
GROUP BY catno 
ORDER BY sold DESC 
LIMIT 10) 

UNION ALL 

(SELECT 
accessories.catno, 
accessories.category, 
accessories.header, 
accessories.description, 
accessories.specialoffer, 
accessories.picture, 
accessories.unit, 
accessories.addinfo, 
accessories.post, 
accessories.price, 
accessories.vat, 
accessories.soundclip, 
COUNT(orders.catno) AS sold 
FROM 
accessories, orders 
WHERE 
orders.catno = accessories.catno 
AND 
accessories.category = 'Green' 
AND accessories.stocklevel > 0 AND 
accessories.category = 'Green' 
GROUP BY catno 
ORDER BY sold DESC 
LIMIT 10) 

UNION ALL

(SELECT 
accessories.catno, 
accessories.category, 
accessories.header, 
accessories.description, 
accessories.specialoffer, 
accessories.picture, 
accessories.unit, 
accessories.addinfo, 
accessories.post, 
accessories.price, 
accessories.vat, 
accessories.soundclip, 
COUNT(orders.catno) AS sold 
FROM 
accessories, orders 
WHERE 
orders.catno = accessories.catno 
AND 
accessories.category = 'Blue' 
AND accessories.stocklevel > 0 AND 
accessories.category = 'Blue' 
GROUP BY catno 
ORDER BY sold DESC 
LIMIT 10) 

不确定我是否在此查询中要求太多,或者我是否需要重新考虑。 有任何想法吗?

已添加 EXPLAIN 的输出。

【问题讨论】:

  • 你确定你在sold上有索引吗?
  • 我猜问题出在COUNT。如果您可以对其进行非规范化并使用触发器对其进行更新,它应该会运行得更快。
  • 在您的查询中显示 EXPLAIN 的输出?
  • @MikeBrant: sold 是一个计数,而不是一列,所以没有索引
  • 那是你的问题,你正在对没有索引的东西进行排序。

标签: mysql performance


【解决方案1】:

正如 Alex 建议的那样,您可以制作一个专栏并使用触发器使其保持最新状态。或者您可以定期运行查询(每小时?每 5 分钟一次?每 1 分钟一次?)并将结果保存在另一个表中(或者更好的是,缓存我猜你正在从中生成的 html 并完全避免查询)。

【讨论】:

  • 我认为问题与没有出售索引有关,因为我将 sold 更改为“COUNT(orders.price) AS sold”(orders.price 是一个索引字段) ,对查询执行速度没有影响。
  • @Alex:- 感谢您的意见 :)。我创建了字段 [orders.sold],用实际随机整数填充它并将其设置为索引。我离开了 ORDER BY sold 子句,查询执行速度飙升至 0.6 秒。不知道我知道这是为什么?
  • 对该查询的解释可能会告诉您。您可能想要一个关于类别的综合索引,已售
  • 这永远行不通。即使我能够优化查询,解决方案也不会是可扩展的。最后,我创建了每个类别前 20 名畅销书的新表格。当我运行此查询时,执行时间仅为:0.0019 秒。完美。
【解决方案2】:

试试这个查询,虽然它未经测试,但试一试

SET @level = 0;
SET @group = '';

SELECT 
    *
FROM (
    SELECT
      accessories.catno,
      accessories.category,
      accessories.header,
      accessories.description,
      accessories.specialoffer,
      accessories.picture,
      accessories.unit,
      accessories.addinfo,
      accessories.post,
      accessories.price,
      accessories.vat,
      accessories.soundclip,
      COUNT(orders.catno)      AS sold,
          @level := IF(@group = accessories.category, @level+1, 1) AS level, 
          @group := accessories.category as E_Group 
    FROM accessories,
      orders
      left join orders
        on orders.catno = accessories.catno
    WHERE accessories.stocklevel > 0
    GROUP BY orders.catno, accessories.category
    ORDER BY orders.sold DESC
) rs
WHERE level < 11 

【讨论】:

    【解决方案3】:

    试试这个查询

     (  SELECT * FROM ( SELECT
    accessories.catno, 
    accessories.category, 
    accessories.header, 
    accessories.description, 
    accessories.specialoffer, 
    accessories.picture, 
    accessories.unit, 
    accessories.addinfo, 
    accessories.post, 
    accessories.price, 
    accessories.vat, 
    accessories.soundclip, 
    COUNT(orders.catno) AS sold 
    FROM 
    accessories, orders 
    WHERE 
    orders.catno = accessories.catno 
    AND 
    accessories.category = 'Red' 
    AND accessories.stocklevel > 0 AND 
    accessories.category = 'Red' 
    GROUP BY catno )
    ORDER BY sold DESC 
    LIMIT 10 )
    
    UNION ALL 
    
    ( SELECT * FROM (SELECT
    accessories.catno, 
    accessories.category, 
    accessories.header, 
    accessories.description, 
    accessories.specialoffer, 
    accessories.picture, 
    accessories.unit, 
    accessories.addinfo, 
    accessories.post, 
    accessories.price, 
    accessories.vat, 
    accessories.soundclip, 
    COUNT(orders.catno) AS sold 
    FROM 
    accessories, orders 
    WHERE 
    orders.catno = accessories.catno 
    AND 
    accessories.category = 'Green' 
    AND accessories.stocklevel > 0 AND 
    accessories.category = 'Green' 
    GROUP BY catno )
    ORDER BY sold DESC 
    LIMIT 10)
    
    UNION ALL
    
    ( SELECT * FROM ( SELECT 
    accessories.catno, 
    accessories.category, 
    accessories.header, 
    accessories.description, 
    accessories.specialoffer, 
    accessories.picture, 
    accessories.unit, 
    accessories.addinfo, 
    accessories.post, 
    accessories.price, 
    accessories.vat, 
    accessories.soundclip, 
    COUNT(orders.catno) AS sold 
    FROM 
    accessories, orders 
    WHERE 
    orders.catno = accessories.catno 
    AND 
    accessories.category = 'Blue' 
    AND accessories.stocklevel > 0 AND 
    accessories.category = 'Blue' 
    GROUP BY catno )
    ORDER BY sold DESC 
    LIMIT 10)
    

    【讨论】:

    • #1064 - 您的 SQL 语法有错误;查看与您的 MySQL 服务器版本相对应的手册,了解在第 1 行的“UNION ALL (SELECT Accessories.catno, Accessories.category, Accessories.header, a') 附近使用的正确语法
    • 恐怕不走运。不确定那个嵌套的 SELECT?
    猜你喜欢
    • 2014-06-05
    • 2011-04-01
    • 2021-03-30
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多