2017-01-13 59 views
0
  • 我目前有一張600,000,000行的表。
  • 我想通過使用Group By子句對數據執行Daily Average來減少我的報告應用程序的行數。

然後將使用我的報告應用程序中較小的數據子集(減少99%)。查看或存儲過程的聚合查詢?

由於這將每天「建造」什麼是最好的工具 - 存儲過程,視圖或其他東西?

+0

您將有一份工作可以執行查詢,將結果保存到表中並執行其他簿記操作。 –

+0

視圖沒有實現或緩存,所以如果要生成新的聚合結果,將它們存儲在表中,然後查詢您將使用存儲過程提供的過程方法,則不會獲得使用它的性能優勢。 –

+0

因此,建議使用存儲過程每天運行一項將新記錄插入到新表中的作業? – OmisNomis

回答

1

構建和維護彙總表。最初,您需要運行一個大的GROUP BY來收集所有的舊數據。之後,每晚的工作將計算前一天的COUNT(*)SUM(...)等。

然後'報告'對這個新表格運行得更快。

該表的關鍵將包括日(不是日期+時間),以及您可能需要用於報告的幾列。

Blog with more details

我發現典型的加速是10倍;你可能會獲得100倍(減少99%)。

最好的工具是你通過cron運行的腳本(或者MySQL EVENT)。它可以簡單地做類似

INSERT INTO SummaryTable (dy, ..., ct, tot, ...) 
SELECT DATE(datetime), ..., -- key 
     COUNT(*), SUM(..), ... -- data 
    FROM FactTable 
    WHERE datetime >= CURDATE() - INTERVAL 1 DAY 
    AND datetime < CURDATE(); 

這一個SQL語句可能是所有需要的。是的,它可能在一個存儲過程中,但這與直接在夜間腳本中沒有多大區別。

在某些情況下,使用INSERT ... ON DUPLICATE KEY UPDATE ... SELECT ...可能會更好(但會變得混亂)。

在談到「平均數」,考慮以下因素:

  • 一個每天平均可以計算每個夜晚:AVG(...),但
  • 一個平均或許應該來計算,而不是每日平均值,但從SUM(daily_sums)/SUM(daily_counts)。也就是說,彙總表可能需要COUNT(*)SUM(...)

要初始填充此彙總表,我會編寫一次性腳本,以便每天慢慢地遍歷600M行。當然,你可以一次完成所有的事情,但是對其他事情的干涉可能是「不好的」。

更好的辦法是每晚的腳本包含代碼以「拾取停止的位置」。這樣,如果腳本無法運行一晚,它會在第二天晚上修復該遺漏。或者您可以在發現問題時手動運行它。額外的跑步不會傷害任何東西。

當你在這裏,想想你可能需要的其他彙總表。我通常發現數據倉庫應用程序需要3-7個彙總表。另一方面,請記住每週和每月的摘要可以從每日摘要表中(足夠有效地)推導出來。在一些情況下,我有一個小時總結表,一個事情,然後每天表不同的事情。

600M行很大。將「舊」數據清除嗎?一旦你有了你需要的彙總表,不再需要「舊」數據了嗎? Blog on using Partitioning for such

+0

謝謝你輸入所有這些。這幫助我通過創建存儲過程來獲得我正在尋找的內容,存儲過程插入昨天的平均值,然後創建一個執行它的事件。 – OmisNomis