MySQL ORDER BY非常慢。如何优化?

时间:2014-02-19 18:05:28

标签: mysql sql performance optimization bigdata

我正在为极慢的查询寻找解决问题的方法,希望你能帮助我。

首先,我想做的是以下几点:
我有一张桌子,让我们将它命名为 item_table ,其中包含一些商品信息。每个项目都有 orderid 。这里的问题是:此订单ID 不唯一 项目的每次更改都是“逐步”记录的。这是一个例子:

             order_id     max_vol   remain_vol
Purchase 1   2007468329   8753      4126
Purchase 2   2007468329   8753      4122
Purchase 3   2007468329   8753      4006

解释一下:
每次有人购买商品时,都会有一个新订单具有相同的订单ID和更改的剩余量( remain_vol )。 max_vol 是卖家在开始时在库存中输入的总量。一个商品可以有多个订单ID,但每次卖家插入一些东西(即使它是同一个商品),它都会获得一个新的订单ID。

我现在要做的是以下内容:
我想得到销售量最多的单品。这意味着我只希望获得MAX(remain_vol)MIN(remain_vol)之间的差异,而我只希望得到任何已售出商品的商品(=max_vol != remain_vol)

更具体一点:
这是我的数据表的创建表:

CREATE TABLE `data` (    
    `orderid` bigint(20) DEFAULT NULL,    
    `regionid` int(11) DEFAULT NULL,    
    `systemid` int(11) DEFAULT NULL,
    `stationid` int(11) DEFAULT NULL,
    `typeid` int(11) DEFAULT NULL,
    `bid` int(11) DEFAULT NULL,
    `price` float DEFAULT NULL,
    `minvolume` int(11) DEFAULT NULL,
    `volremain` int(11) DEFAULT NULL,
    `volenter` int(11) DEFAULT NULL,
    `issued` datetime DEFAULT NULL,
    `duration` varchar(32) DEFAULT NULL,
    `range` int(11) DEFAULT NULL,
    `reportedby` int(11) DEFAULT NULL,
    `reportedtime` datetime DEFAULT NULL,
      KEY `orderid` (`orderid`) USING BTREE,
      KEY `volremain` (`volremain`) USING BTREE,
      KEY `volenter` (`volenter`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

我提到的 max_row 列在 volenter 表中, remaining_vol volremain

此表包含约6,000万个条目

有谁知道如何解决这个问题?
我已经尝试了一些查询,但它们都需要很长时间才能执行。

亲切的问候和希望解决方案
- Lyrex

2 个答案:

答案 0 :(得分:0)

我认为问题在于表的结构方式。当用户购买商品时,您不应该在表格中添加新条目。这种方法有很多问题。

首先,订单应该有唯一的订单ID,除非有充分的理由不这样做。您应该做的是使订单ID唯一,并为其指定字段init_volmax_volsold。当用户购买商品时,您会增加字段sold。如果您想获得销售量最大的单位,请按sold降序排序。

这样你就不会不必要地增长表格了。您的所有查询都变得更加简单和快捷。

答案 1 :(得分:0)

每个问题和一些假设,希望这个答案可以帮助你。

我会在

的数据表上创建一个覆盖索引
( typeid, orderid, remain_vol )

不知道列的基础,我假设(是的,我知道假设),TYPEID是某种买入或卖出的指标。如果你只是寻找'卖',那么这可以帮助查询。通过使用orderid将有助于分组,并且remaining_vol列可以防止返回原始数据页以应用查询。

我的“item_table”上也有覆盖索引,类似于

(orderid, item)

因此可以有效地加入结果销售订单和项目(例如股票名称) 也可以在那里进行快速参考而无需转到原始数据页面。

那说,我会尝试像

这样的东西
SELECT
      t.item,
      SUM( PreAgg.MaxVol ) as TotalVolPerItem,
      SUM( PreAgg.MinVol ) as TotalRemainingToSell
   from
      item_table t
      JOIN (SELECT
                  d.orderid,
                  MAX( d.remain_vol ) as MaxVol,
                  MIN( d.remain_vol ) as MinVol
               from
                  data d
               where
                  d.typeid = 'sell'  (or whatever flag indicator if this is correct assumption)
               group by
                  d.orderid
               having
                  MIN( d.remain_vol ) > 0 ) PreAgg
         ON t.orderid = PreAgg.orderID
   group by
      t.item

“HAVING”子句基于剩余的最小剩余值。例如,如果订单是500的东西,并逐渐卖掉400,300,200,150,76,剩下的76将是你正在考虑的。