改进这可能5连接SQL句子

时间:2009-10-25 09:27:27

标签: sql mysql performance join

我正在使用MySQL 5,我需要用这句话来得到结果。这是我想到的第一次尝试。我知道有几种方法可以改进它,但我想先得到你的意见:

SELECT p.id, p.image, p.lat, p.lng, 
       p.category_id, p2.title, p2.description, c2.name
FROM place p
LEFT JOIN place_translation p2 ON p.id = p2.id
LEFT JOIN trip_place t ON p.id = t.place_id
LEFT JOIN category c ON p.category_id = c.id
LEFT JOIN category_translation c2 ON c.id = c2.id
WHERE c.root_id =1
AND c2.lang =  'en'
AND p2.lang =  'en'
AND t.trip_id =1
AND p.root_id =1
AND p.lft >39
AND p.rgt <44
ORDER BY p2.title

这是一种多语言服务,因此我们有place_translationcategory_translation。我们得到属于旅行的地方,属于一个城市(它是一个嵌套的集合,所以root_idlftrgt

索引是:

on table place: id, category_id
on table place_translation: id-lang index
on table trip_place: place_id, trip_id
on table category: id
on table category_translation: id-lang index

那么,根据您的经验,您如何改进它以使其变小?我知道在遇到问题之前我不必非正规化;但我想找个好基地。

谢谢!

1 个答案:

答案 0 :(得分:2)

有两件显而易见的事情。由于您对WHERE中每个表的值有条件,因此您需要在JOIN子句中找到匹配的行。这意味着您应该使用内连接,而不是左外连接。接下来,要尽快过滤结果,您可以将某些条件从WHERE移至JOIN .. ON

我也以对我有意义的方式重新排序表格,即首先你从trip_place中选择,因为你知道你只想要这次旅行的地方。然后,对于trip_place中的每一行,找到匹配的place,并为每个place找到匹配的category。翻译是最后的,因为它们不会在功能上影响查询。所以查询将是这样的:

SELECT
    p.id, p.image, p.lat, p.lng, 
    p.category_id, p2.title, p2.description, c2.name
FROM
    trip_place t
    JOIN place p ON p.id = t.place_id AND p.root_id = 1 AND p.lft > 39 AND p.rgt < 44
    JOIN category c ON p.category_id = c.id AND c.root_id = 1
    JOIN place_translation p2 ON p.id = p2.id AND p2.lang = 'en'
    JOIN category_translation c2 ON c.id = c2.id AND c2.lang = 'en'
WHERE
    t.trip_id = 1
ORDER BY p2.title

我不知道它是否真的更快,但它可能是。您应该对它们都运行EXPLAIN。从查看索引列表中,您可能应该在place (root_id, p.lft, p.rgt)上添加索引(所有索引都作为单个索引,而不是单独的每个列)。