【问题标题】:sql query slow 3 leftjoins with where clauselsql查询慢3左连接与where子句
【发布时间】:2013-11-28 14:07:41
【问题描述】:

这第一个查询有一个和更多,从 200 毫秒减慢到 9-13 秒 我不明白为什么会这样。

如果我删除所有 where 子句,如果我再添加一个子句,我会得到大约 200 毫秒,它会很慢。

SELECT DISTINCT a.* , p.*, p2.*, p3.*
FROM article a 
LEFT JOIN pro p ON a.id = p.article_id 
LEFT JOIN pro p2 ON a.id = p2.article_id
LEFT JOIN pro p3 ON a.id = p3.article_id
WHERE a.is_active = true 
AND p.name = 'hotel_stars' 
AND p2.name = 'article_journey_days' 
AND p3.name = 'article_persons' 
AND p3.int_value > 0 AND p3.int_value < 7 
AND p.int_value > 0 AND p.int_value < 5

结果

319 Datensätze

Laufzeit gesamt: 9,602.081 ms

SELECT DISTINCT a.* , p.*, p2.*, p3.*
FROM article a 
LEFT JOIN property p ON a.id = p.article_id 
LEFT JOIN property p2 ON a.id = p2.article_id
LEFT JOIN property p3 ON a.id = p3.article_id
WHERE a.is_active = true 
AND p.name = 'hotel_stars' 
AND p2.name = 'article_property_journey_days' 
AND p3.name = 'article_property_persons' 
AND p3.int_value > 0 AND p3.int_value < 7 
// AND p.int_value > 0 AND p.int_value < 5 (removed)

结果

469 Datensätze

Laufzeit gesamt: 278.453 ms

问题出在哪里? 谢谢

编辑解释计划:

HashAggregate  (cost=24113.80..24113.81 rows=1 width=3528)
  ->  Nested Loop  (cost=0.00..24113.69 rows=1 width=3528)
        Join Filter: (a.id = p2.article_id)
        ->  Nested Loop  (cost=0.00..16889.70 rows=1 width=2488)
              ->  Nested Loop  (cost=0.00..16856.58 rows=4 width=2080)
                    Join Filter: (p.article_id = p3.article_id)
                    ->  Seq Scan on property p  (cost=0.00..8335.87 rows=115 width=1040)
                          Filter: ((int_value > 0) AND (int_value < 5) AND ((name)::text = 'hotel_stars'::text))
                    ->  Materialize  (cost=0.00..8336.41 rows=107 width=1040)
                          ->  Seq Scan on property p3  (cost=0.00..8335.87 rows=107 width=1040)
                                Filter: ((int_value > 0) AND (int_value < 7) AND ((name)::text = 'article_property_persons'::text))
              ->  Index Scan using article_pkey on article a  (cost=0.00..8.27 rows=1 width=408)
                    Index Cond: (id = p.article_id)
                    Filter: is_active
        ->  Seq Scan on property p2  (cost=0.00..7185.05 rows=3115 width=1040)
              Filter: ((name)::text = 'article_property_journey_days'::text)
16 Datensätze

Laufzeit gesamt: 11.153 ms

改成

SELECT DISTINCT a.* , p.*, p2.*, p3.*
    FROM article a 
    INNER JOIN pro p ON a.id = p.article_id AND p.name = 'hotel_stars' AND p.int_value > 0 AND p.int_value < 5
    INNER JOIN pro p2 ON a.id = p2.article_id AND p2.name = 'article_journey_days' 
    INNER JOIN pro p3 ON a.id = p3.article_id  AND p3.name = 'article_persons' AND p3.int_value > 0 AND p3.int_value < 7 
    WHERE a.is_active = true 

结果:

319 Datensätze

Laufzeit gesamt: 9,315.863 ms

HashAggregate  (cost=24113.80..24113.81 rows=1 width=3528)
  ->  Nested Loop  (cost=0.00..24113.69 rows=1 width=3528)
        Join Filter: (a.id = p2.article_id)
        ->  Nested Loop  (cost=0.00..16889.70 rows=1 width=2488)
              ->  Nested Loop  (cost=0.00..16856.58 rows=4 width=2080)
                    Join Filter: (p.article_id = p3.article_id)
                    ->  Seq Scan on property p  (cost=0.00..8335.87 rows=115 width=1040)
                          Filter: ((int_value > 0) AND (int_value < 5) AND ((name)::text = 'hotel_stars'::text))
                    ->  Materialize  (cost=0.00..8336.41 rows=107 width=1040)
                          ->  Seq Scan on property p3  (cost=0.00..8335.87 rows=107 width=1040)
                                Filter: ((int_value > 0) AND (int_value < 7) AND ((name)::text = 'article_property_persons'::text))
              ->  Index Scan using article_pkey on article a  (cost=0.00..8.27 rows=1 width=408)
                    Index Cond: (id = p.article_id)
                    Filter: is_active
        ->  Seq Scan on property p2  (cost=0.00..7185.05 rows=3115 width=1040)
              Filter: ((name)::text = 'article_property_journey_days'::text)
16 Datensätze

Laufzeit gesamt: 4.314 ms

类似的问题:(

【问题讨论】:

  • 解释计划 - 索引?数据量?
  • 添加了解释计划。属性表 ~ 2000 篇文章 ~ 460
  • where 仅涉及连接表的子句应移至左连接 on 部分
  • @ foibs 我试过但结果相似:/
  • 所有表格都需要 * 吗?你可以尝试索引名称列(有 460 条记录,可能没有区别)

标签: database performance postgresql left-join


【解决方案1】:

为 p.name 和 p.article 列添加了索引。 结果速度从 13 秒提高到 180 毫秒。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 2011-02-25
    相关资源
    最近更新 更多