저는 오라클 및 MySQL 경험 (DBA 및 dev)을 19 년 이상 받았으며 Postgres를 처음 사용하기 때문에 뭔가 분명하지 않을 수 있습니다. 그러나 나는이 쿼리가 내가 원하는 것을 할 수 없다.왜 Postgres는 인덱스가 데이터의 1 % 미만을 반환하는 순차 스캔을 수행합니까?
NOTE: This query is running on an EngineYard Postgres instance. I am not immediately aware of the parameters it has set up. Also, columns applicable_type and status in the items table are of extension type citext.
다음 쿼리는 행을 반환 60 초를 초과하여 수행 할 수 있습니다
SELECT items.item_id,
CASE when items.sku is null then items.title else concat(item.title, ' (SKU: ', items.sku, ')') END title,
items.listing_status, items.updated_at, items.id,
items.sku, count(details.id) detail_count
FROM "items" LEFT OUTER JOIN details ON details.applicable_id = items.id
and details.applicable_type = 'Item'
and details.status = 'Valid'
LEFT OUTER JOIN products ON products.id = items.product_id
WHERE "items"."user_id" = 3
GROUP BY items.id
ORDER BY title asc
LIMIT 25 OFFSET 0
details
테이블은 650 행이 포함되어 있습니다. LEFT OUTER JOIN
은 applicable_id
에서 순차적 스캔을 수행합니다. 카디널리티 측면에서 볼 때이 열은 6.5M 행에서 120,000 가지의 고유 한 가능성을 제공합니다.
applicable_id
applicable_type
status
하지만 정말, applicable_id
및 applicable_type
낮은 기수가 :
나는 다음과 같은 열 details
에 BTREE 인덱스를 가지고있다. 이 같은
내 explain analyze
외모 :
Limit (cost=247701.59..247701.65 rows=25 width=118) (actual time=28781.090..28781.098 rows=25 loops=1)
-> Sort (cost=247701.59..247703.05 rows=585 width=118) (actual time=28781.087..28781.090 rows=25 loops=1)
Sort Key: (CASE WHEN (items.sku IS NULL) THEN (items.title)::text ELSE pg_catalog.concat(items.title, ' (SKU: ', items.sku, ')') END)
Sort Method: top-N heapsort Memory: 30kB
-> HashAggregate (cost=247677.77..247685.08 rows=585 width=118) (actual time=28779.658..28779.974 rows=664 loops=1)
-> Hash Right Join (cost=2069.47..247645.64 rows=6425 width=118) (actual time=17798.898..28742.395 rows=60047 loops=1)
Hash Cond: (details.applicable_id = items.id)
-> Seq Scan on details (cost=0.00..220591.65 rows=6645404 width=8) (actual time=6.272..27702.717 rows=6646205 loops=1)
Filter: ((applicable_type = 'Listing'::citext) AND (status = 'Valid'::citext))
Rows Removed by Filter: 942
-> Hash (cost=2062.16..2062.16 rows=585 width=118) (actual time=1.286..1.286 rows=664 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 90kB
-> Bitmap Heap Scan on items (cost=16.87..2062.16 rows=585 width=118) (actual time=0.157..0.748 rows=664 loops=1)
Recheck Cond: (user_id = 3)
-> Bitmap Index Scan on index_items_on_user_id (cost=0.00..16.73 rows=585 width=0) (actual time=0.141..0.141 rows=664 loops=1)
Index Cond: (user_id = 3)
총 런타임 : 28781.238 MS
궁금한 점 ... 어떤 종류의 계획을 기대하고 있었습니까? 큰 골재의 톱 앤 타입이 맞을 것 같아, 안 그래? (또한 : 제품에 대한 왼쪽 조인을 보면서 (distinct.id)를 계산해서는 안됩니다.) –
'set enable_hashjoin = false; '로 해시 조인을 일시적으로 비활성화하여 다른 쿼리 계획을보고 비교할 수 있습니다 현재와. –
또한 더 나은 성능을 얻으려면 다른 테이블과 조인 할 하위 쿼리에서'items'에'LIMIT'을 적용 할 수 있습니다. –