2013-12-09 52 views
0

我有一個查詢來顯示客戶和他們所有訂單的總美元價值。該查詢大約需要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 

謝謝,請讓我知道如果我應該包括其他信息。

Update解決方案

我的道歉。我注意到entry_idexp_channel_data表客戶對應author_idexp_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 
+2

您可以發佈一個EXPLAIN查詢的結果包裹?我猜測你的表格在這個操作中沒有很好的索引。您加入的所有列都應該被編入索引。作爲第一個猜測,我會看看索引exp_channel_data.field_id_117。 – AllInOne

+0

你是對的,'exp_channel_data。field_id_117'沒有索引。它實際上是一個TEXT字段,除了該表中的關鍵字段以外的所有字段。所以我把它改成了varchar,所以我可以添加一個索引,這對我有很大的幫助。原來我並不需要'field_id_117',雖然在我的更新中。謝謝! –

回答

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 
+0

非常感謝。後來我意識到,我並不需要在連接中使用'field_id_117',這是主要問題,但是您的查詢速度仍然快了一倍。 –

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 
+0

謝謝。我試着用查詢中的連接條件,但不幸的是沒有返回結果。 –

+0

您指定的連接或列名可能是錯誤的。不用別名就試試。還應儘可能少地使用連接表。 – Aditya

1

你可以發佈EXPLAIN查詢的結果嗎?

我猜你的表沒有很好地爲這個操作索引。您加入的所有列都應該被編入索引。作爲第一個猜測我會看看索引exp_channel_data.field_id_117

+0

你是對的,'exp_channel_data.field_id_117'是魔鬼。這是一個TEXT字段,因此甚至無法編入索引。幸運的是,後來我發現我不必使用它。 –