我有两张桌子,一张用于路线,一张用于机场。
路由包含超过9000行,并且我已经为每列编制了索引。 机场只有2000行,我也为每列写了索引。
当我运行此查询时,最多可能需要35秒才能返回300行:
SELECT routes.* , a1.name as origin_name, a2.name as destination_name FROM routes
LEFT JOIN airports a1 ON a1.IATA = routes.origin
LEFT JOIN airports a2 ON a2.IATA = routes.destination
WHERE routes_build.carrier = "Carrier Name"
使用“DESCRIBE”运行它我得到了followinf信息,但我不是100%肯定它告诉我的内容。
id | Select Type | Table | Type | possible_keys | Key | Key_len | ref | rows | Extra
--------------------------------------------------------------------------------------------------------------------------------------
1 | SIMPLE | routes_build | ref | carrier,carrier_2 | carrier | 678 | const | 26 | Using where
--------------------------------------------------------------------------------------------------------------------------------------
1 | SIMPLE | a1 | ALL | NULL | NULL | NULL | NULL | 5389 |
--------------------------------------------------------------------------------------------------------------------------------------
1 | SIMPLE | a2 | ALL | NULL | NULL | NULL | NULL | 5389 |
--------------------------------------------------------------------------------------------------------------------------------------
我能想到的唯一选择是运行两个单独的查询并将它们与PHP连接起来,尽管如此,我无法相信这样的东西可以杀死一个mysql服务器。像往常一样,我怀疑我做的事情很愚蠢。 SQL是我的第一弱点。
答案 0 :(得分:3)
就个人而言,我首先要删除左连接并用内连接替换它们,因为每个路径必须有一个起点和终点。
答案 1 :(得分:1)
SELECT routes.*, a1.name as origin_name, a2.name as destination_name
FROM routes_build
LEFT JOIN
airports a1
ON a1.IATA = routes_build.origin
LEFT JOIN
airports a2
ON a2.IATA = routes_build.destination
WHERE routes_build.carrier = "Carrier Name"
从EXPLAIN PLAN
我可以看到您在airports.IATA
上没有索引。
您应该创建它以使查询快速运行。
名称还表明它应该是UNIQUE
索引,因为IATA
代码是唯一的。
<强>更新强>
请发布您的表格定义。发出此查询以显示它:
SHOW CREATE TABLE airports
另请注意,FULLTEXT
上的IATA
索引无效,除非您将ft_max_word_len
MySQL
配置设置为3
或更少。
默认情况下,它是4
。
IATA
代码长度为3
个字符,MySQL
不使用默认设置FULLTEXT
搜索此类短字。
答案 2 :(得分:1)
它告诉你它没有使用索引加入机场表。看看“行”栏是如此巨大,5000多?这是为了回答您的查询而必须阅读的行数。
我不知道为什么,因为你声称你已经索引了每一列。什么是IATA?这是独特的吗?我相信如果mysql决定索引是低效的,它可能会忽略它。
编辑:如果IATA是一个唯一的字符串,也许只尝试索引一半? (您可以选择要索引的字符数)这可能会为mysql提供一个可以使用的索引。
答案 3 :(得分:0)
在您实施Martin Robins的优秀建议(即从查询中删除单词LEFT
的每个实例)之后,尝试在routes_build
,carrier
上提供origin
复合索引,和destination
。
答案 4 :(得分:0)
这实际上取决于你想要获得的信息。您可能不需要两次加入机场,您可能不需要使用左连接。此外,如果您可以搜索数字字段而不是文本字段,那么也可以加快速度。
那你想要取什么?