在同一个表上加入慢速聚合查询

时间:2013-12-09 06:49:49

标签: mysql sql expressionengine

我有一个查询来显示客户以及所有订单的总美元价值。查询大约需要100秒才能执行。

我正在查询ExpressionEngine CMS数据库。 ExpressionEngine对所有内容使用一个表exp_channel_data。因此,我必须在该表上加入客户和订单数据。我在该表中有大约14,000个客户,30,000个订单和160,000个记录。

我可以更改此查询以加快速度吗?

SELECT link.author_id          AS customer_id, 
       customers.field_id_122  AS company, 
       Sum(orders.field_id_22) AS total_orders 
FROM   exp_channel_data customers 
       JOIN exp_channel_titles link 
         ON link.author_id = customers.field_id_117 
            AND customers.channel_id = 7 
       JOIN exp_channel_data orders 
         ON orders.entry_id = link.entry_id 
            AND orders.channel_id = 3 
GROUP  BY customer_id 

谢谢,如果我应该提供其他信息,请告诉我。

更新解决方案

道歉。我注意到entry_id表客户的exp_channel_data对应author_id表的exp_channel_titles。所以我不必在联接中使用field_id_117field_id_117重复entry_id,但在TEXT字段中。加入该文本字段会减慢速度。查询现在 3秒

但是,由@DRapp发布的内部联接解决方案 1.5秒。这是他的带有次要编辑的SQL:

SELECT
  PQ.author_id CustomerID,
  c.field_id_122 CompanyName,
  PQ.totalOrders
FROM
  ( SELECT
       t.author_id
          SUM( o.field_id_22 ) as totalOrders
       FROM
          exp_channel_data o
       JOIN 
          exp_channel_titles t ON t.author_id = o.entry_id AND o.channel_id = 3
       GROUP BY
          t.author_id ) PQ
  JOIN 
     exp_channel_data c ON PQ.author_id = c.entry_id AND c.channel_id = 7
  ORDER BY CustomerID

3 个答案:

答案 0 :(得分:1)

您可以发布EXPLAIN查询的结果吗?

我猜你的表没有为这个操作编制索引。您加入的所有列都应该被编入索引。作为第一个猜测,我会考虑索引exp_channel_data.field_id_117

答案 1 :(得分:1)

如果这是同一个表,那么所有别名实例的相同列都是相同的。 如果可能的话,我会确保索引(channel_id,entry_id,field_id_117)。订单总计的查询(author_id)的另一个索引

然后,首先启动将成为内部查询的内容,只执行每个客户的订单金额总和。由于联接是“author_id”作为客户ID,因此首先查询/求和。没有完全理解(我会考虑)结构的糟糕设计,知道“Channel_ID”真正指示的是什么,你不想因为混合中的其他东西而复制求和值。

select
      o.author_id,
      sum( o.field_id_22 ) as totalOrders
   FROM
      exp_channel_data customers o
   where
      o.channel_id = 3
   group by
      o.author_id

如果每个客户(通过author_id列)这是正确的,那么可以包装如下

select
      PQ.author_id CustomerID,
      c.field_id_122 CompanyName,
      PQ.totalOrders
   from
      ( select
              o.author_id,
              sum( o.field_id_22 ) as totalOrders
           FROM
              exp_channel_data customers o
           where
              o.channel_id = 3
           group by
              o.author_id ) PQ
      JOIN exp_channel_data c
         on PQ.author_id = c.field_id_117 
        AND c.channel_id = 7

答案 2 :(得分:0)

尝试这样的事情。可能你在连接中有错误。还要检查数据库中列的连接是否正确。如果您的连接在列上不正确,则交叉连接可能需要一些时间来获取大数据。

select 
link.author_id as customer_id, 
customers.field_id_122 as company, 
sum(orders.field_id_22) as total_or_orders

from exp_channel_data customers     
join exp_channel_titles link on (link.author_id = customers.field_id_117 and
link.author_id = customer.channel_id = 7)
join exp_channel_data orders on (orders.entry_id = link.entry_id and orders.entry_id = orders.channel_id = 3)
group by customer_id