2013-07-28 151 views
2

使用volkszaehler.org我需要從一百萬+行表中檢索數據,下面是什麼ORM創建:MySQL優化GROUP BY索引性能?

CREATE TABLE `data` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `channel_id` int(11) DEFAULT NULL, 
    `timestamp` bigint(20) NOT NULL, 
    `value` double NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `ts_uniq` (`channel_id`,`timestamp`), 
    KEY `IDX_ADF3F36372F5A1AA` (`channel_id`) 
) 

現在,選擇分組數據是緩慢的,尤其是當像樹莓派低性能平臺上運行:

SELECT MAX(timestamp) AS timestamp, SUM(value) AS value, COUNT(timestamp) AS count 
FROM data WHERE channel_id = 4 AND timestamp >= 1356994800000 AND timestamp <= 1375009341000 
GROUP BY YEAR(FROM_UNIXTIME(timestamp/1000)), DAYOFYEAR(FROM_UNIXTIME(timestamp/1000)); 

解釋:

SIMPLE data ref ts_uniq,IDX_ADF3F36372F5A1AA ts_uniq 5 const 2066 Using where; Using temporary; Using filesort 

查詢需要通過50K的記錄,發生在酷睿i5 1.5秒,並且已經6S上RasPi 。

除了減少數據量之外,還有什麼可以提高性能嗎?

+0

第二個想法我也不確定是否真的需要KEY'IDX_ADF3F36372F5A1AA'('channel_id'),因爲這應該已經被UNIQUE KEY覆蓋了? – andig

回答

1

增加數據量而不是減少它,這就是你所需要的:你在GROUP BY子句中有兩個函數,如果你在觸發器中事先計算YEAR(FROM_UNIXTIME(timestamp/1000))DAYOFYEAR(FROM_UNIXTIME(timestamp/1000))並將值存儲到附加字段,你的SELECT語句將會要快得多。

除此之外,您可以簡單地將timestamp截斷爲最近的一天,將其除以1000 * 3600 * 24 = 86400000並將其僅分配一個字段,因爲我無法看到按年份和年份分組另外,當你只能按日期組:

SELECT 
MAX(timestamp) AS timestamp, 
SUM(value) AS value, 
COUNT(timestamp) AS count 
FROM data WHERE 
channel_id = 4 AND 
timestamp >= 1356994800000 AND 
timestamp <= 1375009341000 
GROUP BY timestamp/86400000; 

個人,在那之後我想補充日期字段,索引,並在觸發更新,這樣我就可以刪除GROUP BY所有算術表達式。在這種情況下,索引將被使用。

+0

存儲過程不是一個選項,因爲查詢不是靜態的。相反,volkszaehler允許按秒,分,小時,日,月,年分組計數器數據 - 可能分開存儲太多選項。我嘗試過簡化GROUP BY,發現它並沒有改善我的查詢時間,這導致我得出這樣的結論,即問題更多的是數據量,需要總結。看起來像減少基表中的數據仍然是要走的路(基本上減少歷史計數器數據的時間分辨率)。 – andig

+0

@andig「存儲過程」?我從來沒有提到存儲過程。正如你所看到的,我提到了觸發器。無論如何,從不按功能結果分組。 –

+0

可以理解,但是都不會使我的分數無效?性能沒有通過取消功能而得到改善。 – andig