2012-05-25 98 views
0

我有兩個表都是相同的,除了一個具有時間戳值列和另一個具有日期時間值列。索引是相同的。值是相同的。兩個幾乎相同的表之間的性能差異

但是當我運行SELECT station, MAX(timestamp) AS max_timestamp FROM stations GROUP BY station;如果站是帶時間戳的站點,它執行得非常快,而且如果我用日期時間一個嘗試它,那麼我沒有看到一個查詢執行。在這兩種情況下,timestamp列都被索引,只有類型發生變化。

我應該從哪裏開始尋找?或者是datetime不適合搜索和索引?

這裏是EXPLAIN給出:

+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra     | 
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+ 
| 1 | SIMPLE  | stations | range | NULL   | stamp | 33  | NULL | 1511 | Using index for group-by | 
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+ 

+----+-------------+--------+-------+---------------+---------+---------+------+---------+-------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra | 
+----+-------------+--------+-------+---------------+---------+---------+------+---------+-------+ 
| 1 | SIMPLE  |stations2 | index | NULL   | station | 2  | NULL | 3025467 |  | 
+----+-------------+--------+-------+---------------+---------+---------+------+---------+-------+ 

而且SHOW

+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| stations | CREATE TABLE `stations` (
    `station` varchar(10) COLLATE utf8_bin DEFAULT NULL, 
    `available` smallint(6) DEFAULT NULL, 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    UNIQUE KEY `stamp` (`station`,`timestamp`), 
    KEY `time` (`timestamp`), 
    KEY `timestamp` (`timestamp`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | 
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 

+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| stations2 | CREATE TABLE `stations2` (
    `station` smallint(5) unsigned NOT NULL, 
    `available` smallint(5) unsigned DEFAULT NULL, 
    `timestamp` datetime DEFAULT NULL, 
    KEY `station` (`station`), 
    KEY `timestamp` (`timestamp`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | 
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
+0

這一個似乎是一個起動器:http://stackoverflow.com/questions/4594229/mysql-integer-vs-datetime-index->​​ datetime窮人索引 – Cystack

+0

請顯示索引和EXPLAIN結果。 –

+0

你如何顯示索引:x(sql noob here) – Cystack

回答

1

你可以看到EXPLAIN沒有被用於選擇(NULL爲possible_keys)鍵。你沒有WHERE子句,所以這是有道理的。

MySQL可以利用索引來確定MAX,並且它可以利用索引來優化GROUP BY。但是,爲了能夠優化兩者結合,您需要MAX()函數中的列和GROUP BY子句中的列都處於複合索引中。在第一個表格中,您將此複合索引作爲唯一鍵稱爲「郵票」。 EXPLAIN結果顯示MySQL正在使用該索引。

在第二張表上,你沒有這個複合索引,所以MySQL必須執行更多的工作。它必須手動對結果進行分組,並通過手動掃描每一行來保持每個站的MAX值。如果您在第二張桌子上添加相同的複合索引,則會在兩者之間看到類似的效果。

但是,TIMESTAMP仍然會稍微超過DATETIME,因爲TIMESTAMP被視爲單個4字節整數值,處理速度比8字節的特殊DATETIME值快。數據集越大,您將看到的差異越大。

+0

謝謝1000次。所以有兩個問題:如果我有一個複合站時間戳索引,我應該得到相同的結果?由於我要重新開始,我應該使用INT(與UNIX)而不是DATETIME嗎?爲了提高效率...... – Cystack

+0

@Cystack,是的,如果添加索引,則EXPLAIN結果應該類似,並且應該具有類似的性能。使用TIMESTAMP將比INT(8字節)更快(僅爲4字節),這將比DATETIME(8字節但具有特殊處理)更快,但差異並不大。你可能會選擇最簡單的實現,但如果其他條件相同,則選擇TIMESTAMP。 –

+0

該死......遷移完成,時間戳實際上接近10倍快:( – Cystack

相關問題