2014-10-29 117 views
0

我有一張名爲的表格,其中包含近1,5M行的DATA_TIMESLOTS。 表以這種方式取得:MYSQL GROUP BY PERFORMANCE

+-------+---------------+-----------+ 
| ID | SRV_TIMESTAMP | DEVICE_ID | 
+-------+---------------+-----------+ 
| 134322| 1414583866 |  A1323 | 
| 134323| 1414583832 |  B1423 | 
| 134324| 1414583876 |  A1323 | 
| 134325| 1414583883 |  B1423 | 
| 134326| 1414583896 |  A1323 | 
| 134327| 1414583964 |  C1524 | 
| 134328| 1414581065 |  A1323 | 
| .... |  ........ |  ..... | 
+-------+---------------+-----------+ 

ID是增量PK,SRV_TIMESTAMPDEVICE_ID形式的羣集主鍵(如不同的DEVICE_ID可能具有相同的srv_timestamp ) 另一個名爲的表格包含了近1,5M行的DATA_RAW。這張桌子是這樣製作的:

+--------------+---------+---------+---------+---------+ 
| TIMESLOT_ID | POWER#1 | POWER#2 | POWER#3 | POWER#4 | 
+--------------+---------+---------+---------+---------+ 
|  134322| 342532 | 354365 | 643654 | 77687 | 
|  134323| 439642 | 269436 | 363466 | 16436 | 
|  134324| 436252 | 326436 | 643645 | 31616 | 
|  134325| 564326 | 867867 | 176471 | 16466 | 
|  134326| 148585 | 643633 | 754277 | 43643 | 
|  134327| 345298 | 754765 | 626364 | 32632 | 
|  134328| 324898 | 532575 | 634366 | 65436 | 
|  .... |  .. |  .. |  .. |  .. | 
+--------------+---------+---------+---------+---------+ 

顯然TIMESLOT_ID是這張表的PK。 正如你所看到的TIMESLOT_ID是第一個表的外鍵。 現在我需要獲得每天的統計數據如下:

SELECT 
T.DEVICE_ID AS DEVICE_ID, 
DAY(T.SRV_TIMESTAMP) AS SRV_DAY, 
MONTH(T.SRV_TIMESTAMP) AS SRV_MONTH, 
YEAR(T.SRV_TIMESTAMP) AS SRV_YEAR, 
SUM(D.POWER#1) AS DAY_POWER#1, 
SUM(D.POWER#2) AS DAY_POWER#2, 
SUM(D.POWER#3) AS DAY_POWER#3, 
SUM(D.POWER#4) AS DAY_POWER#4 
FROM DATA_RAW AS D 
INNER JOIN DATA_TIMESLOTS AS T ON T.ID=D.TIMESLOT_ID 
GROUP BY 
T.DEVICE_ID, 
YEAR(T.SRV_TIMESTAMP), 
MONTH(T.SRV_TIMESTAMP), 
DAY(T.SRV_TIMESTAMP) 

查詢工作正常,但它是令人難以置信的速度慢(64位4 CPU/4GB的機器上1.5米的記錄運行約60秒)。我懷疑,儘管我已經好放在DEVICE_IDSRV_TIMESTAMP指標在DATA_TIMESLOTS領域表,這些索引是因爲DAY()月無效()YEAR()功能。所以我嘗試使用DATE()函數,但結果是一樣的。所以問題是:我是否需要在日期,月份,年份中添加其他字段,以便在表格上添加適當的索引並浪費一些空間以提高性能,或者還有另一種方法可以在沒有這樣的情況下獲得此結果浪費空間?

那麼我已經對我的SQLSERVER Express 2005(Microsoft)進行了一些測試,我不得不承認上述問題已完全解決。已經證實,在函數應用於鍵或索引後,MySQL無法保留鍵或索引。相當嚴重的限制恕我直言。 解決方案似乎是: 1)爲日,月,年添加3個附加字段 2)索引這些字段 3)在這些字段上創建羣組 另一方面,我認真考慮刪除時間戳字段在此之後完全沒用。我學到的教訓是,在MySQL時間戳類型中絕不能將它用作鍵或索引,比如對其應用函數時(如日,月,小時,年等),索引將被視爲無效...

+0

你能爲此準備一個sqlfiddle嗎? – 2014-10-29 12:48:00

+0

需要相當多的空間來通過上傳1,5百萬行來複制問題...沒有任何意義。 – 2014-10-29 13:54:12

+0

它確實看到架構(表和索引),顯然它沒有意義上傳所有數據。也用'explain'顯示查詢計劃將會很有用 – 2014-10-29 17:57:02

回答

0

你的索引和解釋是什麼樣的?考慮將Y/M/D組合併爲TO_DAYS調用,您將在同一列上調用三個函數。

+0

我不明白爲什麼我應該對已經分組的東西進行分組。我還沒有在MySQL中找到關於這個函數TO_DAYS的任何信息。無論如何,它似乎是一個MySQL問題,因爲MSSQL服務器中的相同表運行得很快。根本原因是MySQL在對其進行操作時會破壞索引。相當愚蠢的問題,事實上其他數據庫不會受到這種限制。 – 2014-10-29 14:00:30

+1

請在做出這樣明顯的陳述之前對自己的索引進行教育。 MSSQL沒有這樣的事情,它只是在計算值上增加一個索引,你可以輕易地做到,或者只是更好的設計。 – winmutt 2014-10-30 02:52:23

+0

對不起@winmutt。我的意圖不是要激怒任何人。我爲此道歉。我瞭解到,進行查詢非常容易,因此查詢是一個完全不同的東西。當然,這是一個索引問題,但我無法理解我的錯誤在哪裏,因爲MSSQL上的相同結構和查詢不會顯示相同的行爲。如何避免date()或month()這樣的函數將索引字段作爲參數使查詢引擎避免使用索引減慢性能?我想這個問題應該是相當普遍的,當然我在某個地方失敗了...... – 2014-10-30 17:09:08