使用ORDER BY子句时的Mysql SLOW UNION查询

时间:2013-01-24 20:33:13

标签: mysql performance

我有两张桌子:配件和订单。

[accessories.category]包含类别列表,即红色,绿色,蓝色...... 订单表包含过去订单的列表。

我想选择:

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。

BTW:我已将我需要的所有字段编入索引。这是查询:

(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的输出。

Explain Output

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

尝试此查询,虽然它未经测试但是给它一个

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 

答案 2 :(得分:0)

尝试此查询

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