有什么方法可以提高具有多个联接的查询的性能?

时间:2019-09-03 22:50:30

标签: postgresql

我有以下具有6个联接的查询

EXPLAIN ANALYZE 
SELECT
   property.id,
   full_address,
   street_address,
   street.street,
   city.city as city,
   state.state_code as state_code,
   zipcode.zipcode as zipcode,
   property_tax_history.tax AS property_tax,
   property_tax_history.land AS land_value,
   property_tax_history.improvements AS improvements_value,
   property_tax_history.year AS tax_year,
   property_sale_history.date_event AS event_date,
   property_sale_history.event AS event,
   property_sale_history.price AS event_price 
FROM
   property 
   INNER JOIN
      street 
      ON street.id = property.street_id 
   INNER JOIN
      city 
      ON city.id = property.city_id 
   INNER JOIN
      state 
      ON state.id = property.state_id 
   INNER JOIN
      zipcode 
      ON zipcode.id = property.zipcode_id 
   LEFT JOIN
      property_sale_history 
      ON property_sale_history.property_id = property.id 
   LEFT JOIN
      property_tax_history 
      ON property_tax_history.property_id = property.id 
WHERE
   full_address = ?;

以下是EXPLAIN ANALYZE结果

Nested Loop Left Join  (cost=2.83..296.67 rows=6 width=227) (actual time=0.606..0.766 rows=28 loops=1)
  ->  Nested Loop Left Join  (cost=2.26..62.52 rows=1 width=299) (actual time=0.544..0.551 rows=4 loops=1)
        ->  Nested Loop  (cost=1.83..41.98 rows=1 width=284) (actual time=0.522..0.525 rows=1 loops=1)
              ->  Nested Loop  (cost=1.54..33.67 rows=1 width=294) (actual time=0.482..0.485 rows=1 loops=1)
                    ->  Nested Loop  (cost=1.27..25.32 rows=1 width=307) (actual time=0.439..0.441 rows=1 loops=1)
                          ->  Nested Loop  (cost=0.98..17.02 rows=1 width=314) (actual time=0.392..0.394 rows=1 loops=1)
                                ->  Index Scan using property_full_address on property  (cost=0.56..8.57 rows=1 width=318) (actual time=0.339..0.340 rows=1 loops=1)
                                      Index Cond: (full_address = '10951097-4Th-Ave-Chula-Vista-CA-91911'::citext)
                                ->  Index Scan using street_pkey on street  (cost=0.42..8.44 rows=1 width=28) (actual time=0.046..0.046 rows=1 loops=1)
                                      Index Cond: (id = property.street_id)
                          ->  Index Scan using city_id_pk on city  (cost=0.29..8.30 rows=1 width=25) (actual time=0.044..0.044 rows=1 loops=1)
                                Index Cond: (id = property.city_id)
                    ->  Index Scan using state_id_pk on state  (cost=0.28..8.32 rows=1 width=19) (actual time=0.041..0.041 rows=1 loops=1)
                          Index Cond: (id = property.state_id)
              ->  Index Scan using zipcode_id_pk on zipcode  (cost=0.29..8.30 rows=1 width=22) (actual time=0.037..0.037 rows=1 loops=1)
                    Index Cond: (id = property.zipcode_id)
        ->  Index Scan using property_sale_history_property_id on property_sale_history  (cost=0.43..20.50 rows=4 width=31) (actual time=0.019..0.021 rows=4 loops=1)
              Index Cond: (property_id = property.id)
  ->  Index Scan using property_tax_history_property_id on property_tax_history  (cost=0.56..233.54 rows=57 width=33) (actual time=0.014..0.021 rows=7 loops=4)
        Index Cond: (property_id = property.id)
Planning Time: 9.805 ms
Execution Time: 1.628 ms

有这么多的联接,我可以看到每个联接都需要一些时间,并且它们加起来。无论如何,我可以修改查询来加快速度吗?使用SSD驱动器会有所帮助吗?

1 个答案:

答案 0 :(得分:1)

问题在这里:

LEFT JOIN property_sale_history ON property_sale_history.property_id = property.id 
LEFT JOIN property_tax_history ON property_tax_history.property_id = property.id

每个表都有独立的联接,并且两个联接的列都在结果中。

这将导致n 2 问题,并返回行数。例如,如果给定属性有3个销售行和4个税收行,则结果中该属性将有12行。这确实会损害性能,并且无法“解决”性能问题,而且这样的查询也毫无意义。

您应该使用两个单独的查询-一个用于销售历史,一个用于税收历史。

您可以考虑为两个查询的共同部分创建视图。

-

p.s。放宽对新行的注释,并在FROM后面保留所有内容的合理性将有助于提高可读性。

相关问题