我想問一個有關如何在使用InnoDB引擎大MySQL表提高性能的問題:提高性能的一大MySQL表
中目前我的數據庫有大約200萬行的表。該表格定期存儲由不同傳感器收集的數據。該表的結構如下:
CREATE TABLE sns_value (
value_id int(11) NOT NULL AUTO_INCREMENT,
sensor_id int(11) NOT NULL,
type_id int(11) NOT NULL,
date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
value int(11) NOT NULL,
PRIMARY KEY (value_id),
KEY idx_sensor id (sensor_id),
KEY idx_date (date),
KEY idx_type_id (type_id));
起初,我還以爲在幾個月分區表的,但由於穩定增加新的傳感器,將在一個月左右達到目前的規模。
我想出的另一個解決方案是通過傳感器對錶格進行分區。但是,由於MySQL的1024個分區的限制,這不是一個選項。
我認爲,正確的解決辦法是使用具有相同結構的表中的每個傳感器:
sns_value_XXXXX
這樣將有超過1000臺3000萬的估計大小每年行數。同時,這些表格可以在幾個月內進行分區,以便最快速地訪問數據。
該解決方案會產生哪些問題?是否有更規範的解決方案?
編輯附加信息
我認爲表是關於大到我的服務器:
- 雲2xCPU和8GB內存
- LAMP(CentOS的6.5和MySQL 73年5月1日)
每個傳感器可能有多個變量類型(CO,CO2等)。
我主要有兩個慢查詢:
1)爲每個傳感器和類型(平均,最大值,最小值)每日摘要:
SELECT round(avg(value)) as mean, min(value) as min, max(value) as max, type_id
FROM sns_value
WHERE sensor_id=1 AND date BETWEEN '2014-10-29 00:00:00' AND '2014-10-29 12:00:00'
GROUP BY type_id limit 2000;
這需要超過5分鐘以上。
2)垂直到水平視圖和出口:
SELECT sns_value.date AS date,
sum((sns_value.value * (1 - abs(sign((sns_value.type_id - 101)))))) AS one,
sum((sns_value.value * (1 - abs(sign((sns_value.type_id - 141)))))) AS two,
sum((sns_value.value * (1 - abs(sign((sns_value.type_id - 151)))))) AS three
FROM sns_value
WHERE sns_value.sensor_id=1 AND sns_value.date BETWEEN '2014-10-28 12:28:29' AND '2014-10-29 12:28:29'
GROUP BY sns_value.sensor_id,sns_value.date LIMIT 4500;
這也需要超過5分鐘。
其他考慮
- 時間戳可能由於插入件的特性進行重複。
- 定期插入必須與選擇共存。
- 沒有更新或刪除在表上執行。
的假定的製造「一個表中的每個傳感器」的方法
- 錶針對每個傳感器會小得多,以便訪問會更快。
- 每個傳感器只能在一張桌子上進行選擇。
- 選擇來自不同傳感器的混合數據對時間要求不高。
更新2015年2月2日
我們已經創建了一個新表,每年的數據,這是我們也每天劃分爲。每張桌子大約有2.5億行,有365個分區。使用的新索引與Ollie建議的(sensor_id,date,type_id,value)一樣,但查詢仍然需要30秒到2分鐘。我們不使用第一個查詢(每日摘要),僅使用第二個查詢(垂直到水平視圖)。
爲了能夠對錶格進行分區,必須刪除主索引。
我們錯過了什麼嗎?有沒有辦法提高性能?
非常感謝!
當前結構發生了什麼問題? – 2014-10-28 17:57:08
大?這裏很大嗎? – TomTom 2014-10-28 18:16:12
teis數據的用途是什麼?你應該怎麼讀? – Aret 2014-10-28 19:28:18