我有3個表有以下模式:MySQL查詢優化的MAX()
CREATE TABLE `devices` (
`device_id` int(11) NOT NULL auto_increment,
`name` varchar(20) default NULL,
`appliance_id` int(11) default '0',
`sensor_type` int(11) default '0',
`display_name` VARCHAR(100),
PRIMARY KEY USING BTREE (`device_id`)
)
CREATE TABLE `channels` (
`channel_id` int(11) NOT NULL AUTO_INCREMENT,
`device_id` int(11) NOT NULL,
`channel` varchar(10) NOT NULL,
PRIMARY KEY (`channel_id`),
KEY `device_id_idx` (`device_id`)
)
CREATE TABLE `historical_data` (
`date_time` datetime NOT NULL,
`channel_id` int(11) NOT NULL,
`data` float DEFAULT NULL,
`unit` varchar(10) DEFAULT NULL,
KEY `devices_datetime_idx` (`date_time`) USING BTREE,
KEY `channel_id_idx` (`channel_id`)
)
的設置是一個設備可以具有一個或多個通道,每個通道具有許多(歷史的)的數據。
我用下面的查詢來獲取一個設備的最後歷史數據以及所有它的相關渠道:
SELECT c.channel_id, c.channel, max(h.date_time), h.data
FROM devices d
INNER JOIN channels c ON c.device_id = d.device_id
INNER JOIN historical_data h ON h.channel_id = c.channel_id
WHERE d.name = 'livingroom' AND d.appliance_id = '0'
AND d.sensor_type = 1 AND (c.channel = 'ch1')
GROUP BY c.channel
ORDER BY h.date_time, channel
查詢計劃如下所示:
+----+-------------+-------+--------+-----------------------+----------------+---------+---------------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------+----------------+---------+---------------------------+--------+-------------+
| 1 | SIMPLE | c | ALL | PRIMARY,device_id_idx | NULL | NULL | NULL | 34 | Using where |
| 1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 4 | c.device_id | 1 | Using where |
| 1 | SIMPLE | h | ref | channel_id_idx | channel_id_idx | 4 | c.channel_id | 322019 | |
+----+-------------+-------+--------+-----------------------+----------------+---------+---------------------------+--------+-------------+
3 rows in set (0.00 sec)
以上查詢是目前大約需要15秒,我想知道是否有任何提示或方法來改善查詢?
編輯:從historical_data 實施例數據
+---------------------+------------+------+------+
| date_time | channel_id | data | unit |
+---------------------+------------+------+------+
| 2011-11-20 21:30:57 | 34 | 23.5 | C |
| 2011-11-20 21:30:57 | 9 | 68 | W |
| 2011-11-20 21:30:54 | 34 | 23.5 | C |
| 2011-11-20 21:30:54 | 5 | 316 | W |
| 2011-11-20 21:30:53 | 34 | 23.5 | C |
| 2011-11-20 21:30:53 | 2 | 34 | W |
| 2011-11-20 21:30:51 | 34 | 23.4 | C |
| 2011-11-20 21:30:51 | 9 | 68 | W |
| 2011-11-20 21:30:49 | 34 | 23.4 | C |
| 2011-11-20 21:30:49 | 4 | 193 | W |
+---------------------+------------+------+------+
10 rows in set (0.00 sec)
編輯2: 複式信道選擇例如:
SELECT c.channel_id, c.channel, max(h.date_time), h.data
FROM devices d
INNER JOIN channels c ON c.device_id = d.device_id
INNER JOIN historical_data h ON h.channel_id = c.channel_id
WHERE d.name = 'livingroom' AND d.appliance_id = '0'
AND d.sensor_type = 1 AND (c.channel = 'ch1' OR c.channel = 'ch2' OR c.channel = 'ch2')
GROUP BY c.channel
ORDER BY h.date_time, channel
我使用或c.channel where子句,因爲它更容易以語法形式生成,但如果需要可以更改爲使用IN。
編輯3:我想要達到 結果舉例:
+-----------+------------+---------+---------------------+-------+
| device_id | channel_id | channel | max(h.date_time) | data |
+-----------+------------+---------+---------------------+-------+
| 28 | 9 | ch1 | 2011-11-21 20:39:36 | 0 |
| 28 | 35 | ch2 | 2011-11-21 20:30:55 | 32767 |
+-----------+------------+---------+---------------------+-------+
我已經加入了DEVICE_ID的例子,但我的選擇將只需要返回CHANNEL_ID,通道,最後DATE_TIME即最多和數據。結果應該是history_data表中每個設備的每個通道的最後一條記錄。
文章:group by by應該是:c.channel_id,c.chann el,h.data – danihp
你能進一步描述你'最近的歷史數據'是什麼意思嗎?你可以按大小排列這些表嗎?像哪個是最大的?在建議任何查詢更改之前,先了解這幾件事情是很好的。那麼您能提供樣本數據嗎?我想知道的是,只有在獲得'max(h.date_time)'時才需要'h.data' ..你已經做得很好,提供了一大堆信息。只需要更多一點!謝謝! :) – Nonym
historical_data表包含來自傳感器的讀數,目前有300,000多行。頻道表有19個記錄,而設備有10個。我想要根據特定設備的歷史數據表中的日期時間獲取最後一條記錄,以便我可以將它與來自同一傳感器的新讀數進行比較。 –