2013-07-11 51 views
0

我有一個查詢可以通過聚合進行總結。優化具有8.5億行的MySQL表上的聚合

該表稱爲「連接」,擁有大約8.43億行。

CREATE TABLE `connections` (
    `app_id` varchar(16) DEFAULT NULL, 
    `user_id` bigint(20) DEFAULT NULL, 
    `time_started_dt` datetime DEFAULT NULL, 
    `device` varchar(255) DEFAULT NULL, 
    `os` varchar(255) DEFAULT NULL, 
    `firmware` varchar(255) DEFAULT NULL, 
    KEY `app_id` (`bid`), 
    KEY `time_started_dt` (`time_started_dt`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

當我嘗試運行查詢時,如下面的查詢,它需要超過10個小時,我最終將其殺死。有沒有人看到我所做的任何錯誤,對我如何優化查詢有任何建議?

SELECT 
app_id, 
MAX(time_started_dt), 
MIN(time_started_dt), 
COUNT(*) 
FROM 
connections 
GROUP BY 
app_id 
+2

'app_id'上沒有索引? –

+0

可能在該索引中包含time_started_dt,但app_id顯然非常重要。 –

+0

@juergen d我其實確實有'app_id'索引... bid是一個錯字。 – user1152532

回答

1

我建議你上(app_id, time_started_dt)創建複合指數:

ALTER TABLE connections ADD INDEX(app_id, time_started_dt) 
1

要獲得查詢來執行,你真的需要一個合適的覆蓋索引,以app_id作爲前導列,例如

CREATE INDEX `connections_IX1` ON `connections` (`app_id`,` time_start_dt`); 

注:創建索引可能需要幾個小時,而且操作將防止插入/更新/在運行時刪除表。

EXPLAIN將顯示您的查詢的建議執行計劃。通過覆蓋索引,您會在計劃中看到「使用索引」。 (「覆蓋索引」是MySQL可以用來滿足查詢而不必訪問基礎表的索引,也就是說,查詢可以完全從索引中得到滿足)。

隨着大量的在這張表中的行,你可能也想考慮分區。

0

我試過你對隨機生成的數據(大約100萬行)的查詢。添加PRIMATY KEY可以將查詢性能提高10%。如其他人已經建議的那樣,複合索引應該被添加到表格中。索引time_started_dt沒用。

CREATE TABLE `connections` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `app_id` varchar(16) DEFAULT NULL, 
    `user_id` bigint(20) DEFAULT NULL, 
    `time_started_dt` datetime DEFAULT NULL, 
    `device` varchar(255) DEFAULT NULL, 
    `os` varchar(255) DEFAULT NULL, 
    `firmware` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `composite_idx` (`app_id`,`time_started_dt`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8;