2012-06-30 44 views
2

緩慢性能比較我有如下表所示百萬行:MySQL在大桌子

CREATE TABLE `points` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `DateNumber` int(10) unsigned DEFAULT NULL, 
    `Count` int(10) unsigned DEFAULT NULL, 
    `FPTKeyId` int(10) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `id_UNIQUE` (`id`), 
    KEY `index3` (`FPTKeyId`,`DateNumber`) USING HASH 
) ENGINE=InnoDB AUTO_INCREMENT=16755134 DEFAULT CHARSET=utf8$$ 

正如你可以看到我已經創建的索引。我不知道我做得對不對。 問題是查詢執行速度超慢。

讓我們來簡單的查詢

SELECT fptkeyid, count FROM points group by fptkeyid 

我cannt得到的結果,因爲通過查詢超時(10分鐘)中止。我做錯了什麼?

+1

注意:'PRIMARY KEY'在默認情況下始終是唯一的,所以'UNIQUE KEY(id)'很可能是不必要的。 – biziclop

+0

我搜索了'mysql group by by not using index',發現這個很好,很長的閱讀:http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html – biziclop

+0

請添加基本信息,所以我們可以回答這個問題。顯示一些示例行,對查詢的解釋,硬件的一般概念以及您在發佈之前所做的一些測量。這樣你就可以得到更適合你情況的具體答案。 –

回答

-1

我認爲問題在於你的服務器帶寬。擁有一百萬行可能需要至少高兆字節的帶寬。

+0

即時在我的本地機器上執行查詢 – Neir0

3

小心MySQL的愚蠢行爲:GROUP BY ing暗指執行ORDER BY

爲防止出現這種情況,請明確添加ORDER BY NULL,以防止不必要的排序。

http://dev.mysql.com/doc/refman/5.0/en/select.html說:

如果使用GROUP BY,輸出行根據GROUP,如果你有一個ORDER BY爲同一列排序BY 列。爲了避免 開銷排序是GROUP BY生產的,添加ORDER BY NULL:

SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL; 

+

http://dev.mysql.com/doc/refman/5.6/en/group-by-optimization.html說:

使用索引GROUP BY最重要的前提條件是 所有GROUP BY列引用來自相同索引 的屬性,並且索引按順序存儲其鍵(例如,這是一個 BTREE索引而不是HASH索引)。

+0

不幸它仍然運行緩慢 – Neir0

+0

577秒爲這個查詢 – Neir0

+0

@ Neir0那麼,如果你有很多數以百萬計的行,MySQL必須通過每個人,當你不'在查詢中沒有任何where子句。這需要時間。如果您需要頻繁運行諸如此類的查詢,則可能需要有一個彙總表,用於存儲這些彙總。 – nos

1

我會親自從您的AUTO_INCREMENT值開始。對於每個新記錄,您已將其設置爲增加16,755,134。您的字段值設置爲INT UNSIGNED,這意味着值的範圍是0 to 4,294,967,295(或接近43億)。這意味着在字段超出數據類型限制之前,您將只有256,從而危及PRIMARY KEY INDEX的用途。

你可以改變數據類型BIGINT UNSIGNED,你將有0 to 18,446,744,073,709,551,615值範圍(或略多於18.4百萬的三次方),這將讓你有高達1,100,960,700,983(或略多於1.1萬億)唯一值與此AUTO_INCREMENT值。

我會先問你是否真的需要你AUTO_INCREMENT值設置爲如此龐大的數目,如果沒有,那麼我會建議改變,爲1(或至少一些較小的數字)作爲存儲字段值INT vs BIGINT將在諸如此類的較大表格內節省大量磁盤空間。無論哪種方式,你應該得到一個更穩定的PRIMARY KEY INDEX這應該有助於改善查詢。

1

您的查詢是沒有意義的:

SELECT fptkeyid, count FROM points group by fptkeyid 

您按fptkeyid所以算不用武之地了。應該有一個聚合函數。不是計數字段。接下來,這個計數也是一個MySQL函數,它使得對於一個字段使用相同的名稱不是非常有用/可取的。

你不需要這樣的:

SELECT fptkeyid, SUM(`count`) FROM points group by fptkeyid 

如果不是,請解釋一下你的結果從查詢的期望。

創建一個包含50萬條測試數據的數據庫,以查看我是否能找到與您的問題相同的內容。這是什麼解釋告訴我:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE points index NULL index3 10 NULL 433756 

而且在SUM查詢:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE points index NULL index3 10 NULL 491781 

兩個查詢是在一秒鐘內一臺筆記本電腦(MacBook Air的)來完成,沒有什麼需要長時間。插入雖然需要一些時間,但幾分鐘才能獲得50萬條記錄。但檢索和計算不。

我們需要更多來回答你的問題完全完整。也許數據庫的配置是錯誤的,例如幾乎沒有分配內存?