Postgres查询缓慢

时间:2018-07-09 10:00:51

标签: sql postgresql indexing

OS X上的Postgres 10.3

为什么在#1和#3中会扫描“事件”中的所有行?

为什么将DISTINCT添加到#2(下面的视图#4查询)会导致截然不同的(快速)执行和执行计划?

我对Postgres有非常肤浅的知识(一般来说可以使用DB理论),所以不知道这些怪癖,索引是下一级别。

最初,我正在使用Node + Sequelize执行连接#3,该连接速度很慢,因此尝试了IN。如果“ collection_item”的计数为1,则快速执行。

如果可以避免,我宁愿使用Sequelize生成的查询,而不是手工制作的。

感谢您的帮助。

1-慢进:

select "event".* from "event" 
where id in (
  select item_id 
  from collection_item 
  where "collection_item"."collection_id" = 2 and collection_item.item_type = 'event'
)

分析:

Merge Semi Join  (cost=2.08..12.60 rows=4 width=1870) (actual time=0.079..6294.739 rows=7 loops=1)                                                |
  Merge Cond: (event.id = collection_item.item_id)                                                                                                |
  ->  Index Scan using idx_event_id on event  (cost=0.43..1066819.90 rows=10000215 width=1870) (actual time=0.012..5525.787 rows=9109726 loops=1) |
  ->  Sort  (cost=1.62..1.64 rows=4 width=4) (actual time=0.028..0.029 rows=7 loops=1)                                                            |
        Sort Key: collection_item.item_id                                                                                                         |
        Sort Method: quicksort  Memory: 25kB                                                                                                      |
        ->  Seq Scan on collection_item  (cost=0.00..1.58 rows=4 width=4) (actual time=0.018..0.022 rows=7 loops=1)                               |
              Filter: ((collection_id = 2) AND ((item_type)::text = 'event'::text))                                                               |
              Rows Removed by Filter: 33                                                                                                          |
Planning time: 0.412 ms                                                                                                                           |
Execution time: 6296.260 ms                                                                                                                       |

2-快速输入

select "event".* from "event" 
where id = any(
  (
    select array(
        select item_id 
        from collection_item 
        where "collection_item"."collection_id" = 2 and collection_item.item_type = 'event'
    )
  )::integer[]
) 

分析

Index Scan using idx_event_id on event  (cost=2.03..76.86 rows=10 width=1870) (actual time=0.092..0.119 rows=7 loops=1) |
  Index Cond: (id = ANY ($1))                                                                                           |
  InitPlan 2 (returns $1)                                                                                               |
    ->  Result  (cost=1.58..1.59 rows=1 width=32) (actual time=0.043..0.043 rows=1 loops=1)                             |
          InitPlan 1 (returns $0)                                                                                       |
            ->  Seq Scan on collection_item  (cost=0.00..1.58 rows=4 width=4) (actual time=0.035..0.039 rows=7 loops=1) |
                  Filter: ((collection_id = 2) AND ((item_type)::text = 'event'::text))                                 |
                  Rows Removed by Filter: 33                                                                            |
Planning time: 0.204 ms                                                                                                 |
Execution time: 0.147 ms                                                                                                |

3-慢速加入

explain analyse SELECT "event"."id", "event"."parent_event_id", "event"."name", "event"."longlink", "event"."summary", "event"."description", "event"."organiser_id", "event"."creator_id", "event"."location_type", "event"."primary_location_id", "event"."primary_event_date_id", "event"."page_template_id", "event"."data", "event"."image", "event"."status", "event"."type", "event"."count_interested", "event"."count_attending", "event"."count_likes", "event"."count_collections", "event"."count_comments", "event"."count_views", "event"."pricing_id", "event"."event_series_id", "event"."owner_type", "event"."owner_id", "event"."publish_at", "event"."calendar_visibility", "event"."max_attendees", "event"."min_attendees", "event"."registration_cost", "event"."registration_visibility", "event"."interest_visibility", "event"."itinerary_id", "event"."ext_id", "event"."ext_application", "event"."lowest_price", "event"."highest_price", "event"."registrations_close_at", "event"."registrations_open_at", "event"."registrations_closed", "event"."tags", "event"."exclude_from_related", "event"."rewards_label", "event"."createdAt", "event"."updatedAt", "collectionItem"."id" AS "collectionItem.id", "primaryLocation"."id" AS "primaryLocation.id", "primaryLocation"."name" AS "primaryLocation.name", "primaryLocation"."description" AS "primaryLocation.description", "primaryLocation"."lat" AS "primaryLocation.lat", "primaryLocation"."lng" AS "primaryLocation.lng", "primaryLocation"."formatted_address" AS "primaryLocation.formatted_address", "primaryLocation"."status" AS "primaryLocation.status", "primaryLocation"."address_1" AS "primaryLocation.address_1", "primaryLocation"."address_2" AS "primaryLocation.address_2", "primaryLocation"."address_3" AS "primaryLocation.address_3", "primaryLocation"."building" AS "primaryLocation.building", "primaryLocation"."city" AS "primaryLocation.city", "primaryLocation"."region" AS "primaryLocation.region", "primaryLocation"."country" AS "primaryLocation.country", "primaryLocation"."post_code" AS "primaryLocation.post_code", "primaryLocation"."owner_type" AS "primaryLocation.owner_type", "primaryLocation"."owner_id" AS "primaryLocation.owner_id", "primaryLocation"."instructions" AS "primaryLocation.instructions", "primaryLocation"."event_count" AS "primaryLocation.event_count", "primaryLocation"."parking_instructions" AS "primaryLocation.parking_instructions", "primaryLocation"."visibility" AS "primaryLocation.visibility", "primaryLocation"."createdAt" AS "primaryLocation.createdAt", "primaryLocation"."updatedAt" AS "primaryLocation.updatedAt", "primaryEventDate"."id" AS "primaryEventDate.id", "primaryEventDate"."event_id" AS "primaryEventDate.event_id", "primaryEventDate"."start_date" AS "primaryEventDate.start_date", "primaryEventDate"."start_time" AS "primaryEventDate.start_time", "primaryEventDate"."start_datetime" AS "primaryEventDate.start_datetime", "primaryEventDate"."end_date"AS "primaryEventDate.end_date", "primaryEventDate"."end_time" AS "primaryEventDate.end_time", "primaryEventDate"."end_datetime" AS "primaryEventDate.end_datetime", "primaryEventDate"."name" AS "primaryEventDate.name", "primaryEventDate"."status" AS "primaryEventDate.status", "primaryEventDate"."details" AS "primaryEventDate.details", "primaryEventDate"."visible_from" AS "primaryEventDate.visible_from", "primaryEventDate"."visible_to" AS "primaryEventDate.visible_to", "primaryEventDate"."type" AS "primaryEventDate.type", "primaryEventDate"."search_visibility" AS "primaryEventDate.search_visibility", "primaryEventDate"."calendar_visibility" AS "primaryEventDate.calendar_visibility", "primaryEventDate"."tz" AS "primaryEventDate.tz", "primaryEventDate"."createdAt" AS "primaryEventDate.createdAt", "primaryEventDate"."updatedAt" AS "primaryEventDate.updatedAt", "userEventTrack"."collection_count" AS "userEventTrack.collection_count", "userEventTrack"."liked" AS "userEventTrack.liked" 
FROM "event" AS "event" 
INNER JOIN "collection_item" AS "collectionItem" ON "event"."id" = "collectionItem"."item_id" AND "collectionItem"."item_type" = 'event' AND "collectionItem"."collection_id" =2 
LEFT OUTER JOIN "location" AS "primaryLocation" ON "event"."primary_location_id" = "primaryLocation"."id" 
LEFT OUTER JOIN "event_date" AS "primaryEventDate" ON "event"."primary_event_date_id" = "primaryEventDate"."id" 
LEFT OUTER JOIN "user_event_track" AS "userEventTrack" ON "event"."id" = "userEventTrack"."event_id" AND "userEventTrack"."user_id" = 1 LIMIT 20;

分析:

Limit  (cost=2.90..16.42 rows=4 width=3676) (actual time=0.100..6207.552 rows=7 loops=1)                                                                                  |
  ->  Nested Loop Left Join  (cost=2.90..16.42 rows=4 width=3676) (actual time=0.100..6207.550 rows=7 loops=1)                                                            |
        ->  Nested Loop Left Join  (cost=2.76..15.74 rows=4 width=3664) (actual time=0.094..6207.502 rows=7 loops=1)                                                      |
              ->  Nested Loop Left Join  (cost=2.22..13.24 rows=4 width=3359) (actual time=0.092..6207.492 rows=7 loops=1)                                                |
                    ->  Merge Join  (cost=2.08..12.60 rows=4 width=1836) (actual time=0.089..6207.012 rows=7 loops=1)                                                     |
                          Merge Cond: (event.id = "collectionItem".item_id)                                                                                               |
                          ->  Index Scan using idx_event_id on event  (cost=0.43..1066819.90 rows=10000215 width=1832) (actual time=0.018..5455.081 rows=9109726 loops=1) |
                          ->  Sort  (cost=1.62..1.64 rows=4 width=8) (actual time=0.027..0.028 rows=7 loops=1)                                                            |
                                Sort Key: "collectionItem".item_id                                                                                                        |
                                Sort Method: quicksort  Memory: 25kB                                                                                                      |
                                ->  Seq Scan on collection_item "collectionItem"  (cost=0.00..1.58 rows=4 width=8) (actual time=0.014..0.019 rows=7 loops=1)              |
                                      Filter: (((item_type)::text = 'event'::text) AND (collection_id = 2))                                                               |
                                      Rows Removed by Filter: 33                                                                                                          |
                    ->  Index Scan using location_pkey on location "primaryLocation"  (cost=0.14..0.16 rows=1 width=1523) (actual time=0.067..0.067 rows=0 loops=7)       |
                          Index Cond: (event.primary_location_id = id)                                                                                                    |
              ->  Index Scan using event_date_pkey on event_date "primaryEventDate"  (cost=0.55..0.63 rows=1 width=305) (actual time=0.000..0.000 rows=0 loops=7)         |
                    Index Cond: (event.primary_event_date_id = id)                                                                                                        |
        ->  Index Scan using idx_usereventtrack_event on user_event_track "userEventTrack"  (cost=0.14..0.16 rows=1 width=16) (actual time=0.005..0.006 rows=1 loops=7)   |
              Index Cond: (event.id = event_id)                                                                                                                           |
              Filter: (user_id = 1)                                                                                                                                       |
Planning time: 6.875 ms                                                                                                                                                   |
Execution time: 6208.728 ms                                                                                                                                               |

4-快速输入-与#1相同,但具有DISTINCT

select "event".* from "event" 
where id in (
  select DISTINCT item_id 
  from collection_item 
  where "collection_item"."collection_id" = 2 and collection_item.item_type = 'event'
)

分析

Nested Loop  (cost=2.03..27.01 rows=3 width=1870) (actual time=0.088..0.143 rows=7 loops=1)                                 
  ->  HashAggregate  (cost=1.59..1.62 rows=3 width=4) (actual time=0.054..0.056 rows=7 loops=1)                             
        Group Key: collection_item.item_id                                                                                  
        ->  Seq Scan on collection_item  (cost=0.00..1.58 rows=4 width=4) (actual time=0.042..0.047 rows=7 loops=1)         
              Filter: ((collection_id = 2) AND ((item_type)::text = 'event'::text))                                         
              Rows Removed by Filter: 33                                                                                    
  ->  Index Scan using idx_event_id on event  (cost=0.43..8.45 rows=1 width=1870) (actual time=0.012..0.012 rows=1 loops=7) 
        Index Cond: (id = collection_item.item_id)                                                                          
Planning time: 0.388 ms                                                                                                     
Execution time: 0.220 ms                                                                                                    

0 个答案:

没有答案