如何优化此查询...?

时间:2009-06-26 15:32:13

标签: sql mysql query-optimization

我有两张桌子,一张用于路线,一张用于机场。

路由包含超过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是我的第一弱点。

5 个答案:

答案 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_buildcarrier上提供origin复合索引,和destination

答案 4 :(得分:0)

这实际上取决于你想要获得的信息。您可能不需要两次加入机场,您可能不需要使用左连接。此外,如果您可以搜索数字字段而不是文本字段,那么也可以加快速度。

那你想要取什么?