我一直在測試出不同的想法,以優化我們系統工作中的一些表格。今天,我遇到了一張表格,可以跟蹤系統中每輛車的每個視圖。在下面創建表格。當where語句中的日期改變時,MySQL EXPLAIN'type'從'range'改變爲'ref'?
SHOW CREATE TABLE vehicle_view_tracking;
CREATE TABLE `vehicle_view_tracking` (
`vehicle_view_tracking_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`public_key` varchar(45) NOT NULL,
`vehicle_id` int(10) unsigned NOT NULL,
`landing_url` longtext NOT NULL,
`landing_port` int(11) NOT NULL,
`http_referrer` longtext,
`created_on` datetime NOT NULL,
`created_on_date` date NOT NULL,
`server_host` longtext,
`server_uri` longtext,
`referrer_host` longtext,
`referrer_uri` longtext,
PRIMARY KEY (`vehicle_view_tracking_id`),
KEY `vehicleViewTrackingKeyCreatedIndex` (`public_key`,`created_on_date`),
KEY `vehicleViewTrackingKeyIndex` (`public_key`)
) ENGINE=InnoDB AUTO_INCREMENT=363439 DEFAULT CHARSET=latin1;
我當時玩的是多列和單列索引。我跑下面的查詢:
EXPLAIN EXTENDED SELECT dealership_vehicles.vehicle_make, dealership_vehicles.vehicle_model, vehicle_view_tracking.referrer_host, count(*) AS count
FROM vehicle_view_tracking
LEFT JOIN dealership_vehicles
ON dealership_vehicles.dealership_vehicle_id = vehicle_view_tracking.vehicle_id
WHERE vehicle_view_tracking.created_on_date >= '2011-09-07' AND vehicle_view_tracking.public_key IN ('ab12c3')
GROUP BY (dealership_vehicles.vehicle_make) ASC , dealership_vehicles.vehicle_model, referrer_host
+----+-------------+-----------------------+--------+----------------------------------------------------------------+------------------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+------------------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | vehicle_view_tracking | range | vehicleViewTrackingKeyCreatedIndex,vehicleViewTrackingKeyIndex | vehicleViewTrackingKeyCreatedIndex | 50 | NULL | 23086 | 100.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | dealership_vehicles | eq_ref | PRIMARY | PRIMARY | 8 | vehicle_view_tracking.vehicle_id | 1 | 100.00 | |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+------------------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
(執行時間爲實際的選擇查詢被0.309秒)
然後我更改日期從「2011-09-07」到「where子句中2011- 07-07' ,得到了以下的解釋結果
EXPLAIN EXTENDED SELECT dealership_vehicles.vehicle_make, dealership_vehicles.vehicle_model, vehicle_view_tracking.referrer_host, count(*) AS count
FROM vehicle_view_tracking
LEFT JOIN dealership_vehicles
ON dealership_vehicles.dealership_vehicle_id = vehicle_view_tracking.vehicle_id
WHERE vehicle_view_tracking.created_on_date >= '2011-07-07' AND vehicle_view_tracking.public_key IN ('ab12c3')
GROUP BY (dealership_vehicles.vehicle_make) ASC , dealership_vehicles.vehicle_model, referrer_host
+----+-------------+-----------------------+--------+----------------------------------------------------------------+-----------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+-----------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
| 1 | SIMPLE | vehicle_view_tracking | ref | vehicleViewTrackingKeyCreatedIndex,vehicleViewTrackingKeyIndex | vehicleViewTrackingKeyIndex | 47 | const | 53676 | 100.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | dealership_vehicles | eq_ref | PRIMARY | PRIMARY | 8 | vehicle_view_tracking.vehicle_id | 1 | 100.00 | |
+----+-------------+-----------------------+--------+----------------------------------------------------------------+-----------------------------+---------+----------------------------------------------+-------+----------+----------------------------------------------+
(執行時間爲實際的選擇查詢是0.670秒)
我看到4個主要變化:
- 類型從範圍變更爲REF
- 鍵從vehicleViewTrackingKeyCreatedIndex變爲vehicleViewTrackingKeyIndex
- key_len從50改變到47(由在密鑰的變化)
- 行從23086改變爲53676(所造成的更改密鑰)
此時,慢速查詢的執行時間僅爲.6秒,但我們的數據庫中只有大約10%的車輛。
它遲到了,我可能忽略了mysql文檔中的某些內容,但似乎無法找到在where子句中更改日期時鍵(爲什麼鍵和行又改變)的原因。
非常感謝幫助。我搜索了一個具有相同/相似問題的人,導致此更改的日期,但無法找到任何內容。如果我錯過了以前的帖子,請鏈接我:-)
所以簡而言之,mysql優化器認爲做出更改並使用其他索引更好/更快。我跑了另一個測試,並刪除了第二個索引(vehicleViewTrackingKeyIndex),查詢時間在0.01秒之內。看起來隨着結果集的增加,它意識到使用2列索引是沒有意義的。 – CriticalSpeak
@CriticalSpeak:是的,簡而言之。你經常不得不使用索引(並重寫查詢),因爲它的優化器存在許多缺陷,這比你在MySQL中必須要做的要多得多。如果您對此感到厭煩,請嘗試PostgreSQL。 – derobert