2013-07-04 193 views
0

我對SQL依然很陌生,我試圖改進查詢的性能。我一直在四處搜尋,得出的結論是,使用JOINS而不是很多WHERE INS將有助於提高我的表現,但我不確定如何轉換我的表述。這是我目前的發言。MySQL查詢性能很慢

SELECT stop_id, stop_name FROM stops WHERE stop_id IN (
     SELECT DISTINCT stop_id FROM stop_times WHERE trip_id IN (
       SELECT trip_id from trips WHERE route_id = <routeid>)); 

它需要5-25秒的時間來返回不可接受的結果。我希望能在1秒以內得到它。如果有人想知道這些數據來自GTFS Feed。停靠站和旅行桌每個約有10,000行,而stop_times表約有900,000個。我在每個使用的列創建索引。以下是EXPLAIN的輸出,以及用於創建每個表的內容。

感謝您的任何幫助,如果您需要任何更多的信息讓我知道!

+----+--------------------+------------+-----------------+------------------+---------+---------+------+------+-------------+ 
| id | select_type  | table  | type   | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+--------------------+------------+-----------------+------------------+---------+---------+------+------+-------------+ 
| 1 | PRIMARY   | stops  | ALL    | NULL    | NULL | NULL | NULL | 6481 | Using where | 
| 2 | DEPENDENT SUBQUERY | stop_times | index_subquery | stop_id   | stop_id | 63  | func | 63 | Using where | 
| 3 | DEPENDENT SUBQUERY | trips  | unique_subquery | PRIMARY,route_id | PRIMARY | 62  | func | 1 | Using where | 
+----+--------------------+------------+-----------------+------------------+---------+---------+------+------+-------------+ 


| stops | CREATE TABLE `stops` (
    `stop_id` varchar(20) NOT NULL, 
    `stop_code` varchar(50) DEFAULT NULL, 
    `stop_name` varchar(255) DEFAULT NULL, 
    `stop_desc` varchar(255) DEFAULT NULL, 
    `stop_lat` decimal(8,6) DEFAULT NULL, 
    `stop_lon` decimal(8,6) DEFAULT NULL, 
    `zone_id` int(11) DEFAULT NULL, 
    `stop_url` varchar(255) DEFAULT NULL, 
    `location_type` int(2) DEFAULT NULL, 
    `parent_station` int(11) DEFAULT NULL, 
    `wheelchair_boarding` int(2) DEFAULT NULL, 
    PRIMARY KEY (`stop_id`), 
    KEY `zone_id` (`zone_id`), 
    KEY `stop_lat` (`stop_lat`), 
    KEY `stop_lon` (`stop_lon`), 
    KEY `location_type` (`location_type`), 
    KEY `parent_station` (`parent_station`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 


| stop_times | CREATE TABLE `stop_times` (
    `trip_id` varchar(20) DEFAULT NULL, 
    `arrival_time` varchar(8) DEFAULT NULL, 
    `arrival_time_seconds` int(11) DEFAULT NULL, 
    `departure_time` varchar(8) DEFAULT NULL, 
    `departure_time_seconds` int(11) DEFAULT NULL, 
    `stop_id` varchar(20) DEFAULT NULL, 
    `stop_sequence` int(11) DEFAULT NULL, 
    `stop_headsign` varchar(50) DEFAULT NULL, 
    `pickup_type` int(2) DEFAULT NULL, 
    `drop_off_type` int(2) DEFAULT NULL, 
    `shape_dist_traveled` varchar(50) DEFAULT NULL, 
    KEY `trip_id` (`trip_id`), 
    KEY `arrival_time_seconds` (`arrival_time_seconds`), 
    KEY `departure_time_seconds` (`departure_time_seconds`), 
    KEY `stop_id` (`stop_id`), 
    KEY `stop_sequence` (`stop_sequence`), 
    KEY `pickup_type` (`pickup_type`), 
    KEY `drop_off_type` (`drop_off_type`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 

| trips | CREATE TABLE `trips` (
    `route_id` varchar(20) DEFAULT NULL, 
    `service_id` varchar(20) DEFAULT NULL, 
    `trip_id` varchar(20) NOT NULL, 
    `trip_headsign` varchar(255) DEFAULT NULL, 
    `trip_short_name` varchar(255) DEFAULT NULL, 
    `direction_id` tinyint(1) DEFAULT NULL, 
    `block_id` int(11) DEFAULT NULL, 
    `shape_id` varchar(50) DEFAULT NULL, 
    PRIMARY KEY (`trip_id`), 
    KEY `route_id` (`route_id`), 
    KEY `service_id` (`service_id`), 
    KEY `direction_id` (`direction_id`), 
    KEY `block_id` (`block_id`), 
    KEY `shape_id` (`shape_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 
+0

使用'凡SELECT'一個JOIN代替。 MySQL優化後者效果不佳。 – Barmar

回答

3

你說得對,JOINS通常比WHERE子查詢更快。

試試這個:

SELECT T3.stop_id, T3.stop_name 
FROM trips AS T1 
JOIN 
stop_times AS T2 
ON T1.trip_id=T2.trip_id AND route_id = <routeid> 
JOIN stops AS T3 
ON T2.stop_id=T3.stop_id 
GROUP BY T3.stop_id, T3.stop_name 
+0

這非常奏效。非常感謝。查詢現在只需不到0.2秒!我想我必須在連接上閱讀很多內容。他們對我來說仍然有點困惑,但顯然它有很大的不同。 – btse