2

여기에 스타 스키마가 있는데 사실 테이블을 쿼리하고 하나의 매우 작은 차원 테이블에 가입하려고합니다.다음 조인이 쿼리 시간을 크게 늘리는 이유는 무엇입니까?

EXPLAIN ANALYZE SELECT 
    COUNT(impression_id), imp.os_id 
    FROM bi.impressions imp 
    GROUP BY imp.os_id; 

                    QUERY PLAN 
    -------------------------------------------------------------------------------------------------------------------------------------- 
    HashAggregate (cost=868719.08..868719.24 rows=16 width=10) (actual time=12559.462..12559.466 rows=26 loops=1) 
     -> Seq Scan on impressions imp (cost=0.00..690306.72 rows=35682472 width=10) (actual time=0.009..3030.093 rows=35682474 loops=1) 
    Total runtime: 12559.523 ms 
    (3 rows) 

이 소요 ~ 12600ms하지만, 물론 거기에는 데이터를 결합, 그래서 의미가 무엇인가에 imp.os_id를 "해결"할 수없는, 그래서 추가 : 정말 다음을 설명 할 수 없습니다 가입 :

EXPLAIN ANALYZE SELECT 
    COUNT(impression_id), imp.os_id, os.os_desc 
    FROM bi.impressions imp, bi.os_desc os 
    WHERE imp.os_id=os.os_id 
    GROUP BY imp.os_id, os.os_desc; 
                    QUERY PLAN 
    -------------------------------------------------------------------------------------------------------------------------------------------- 
    HashAggregate (cost=1448560.83..1448564.99 rows=416 width=22) (actual time=25565.124..25565.127 rows=26 loops=1) 
     -> Hash Join (cost=1.58..1180942.29 rows=35682472 width=22) (actual time=0.046..15157.684 rows=35682474 loops=1) 
      Hash Cond: (imp.os_id = os.os_id) 
      -> Seq Scan on impressions imp (cost=0.00..690306.72 rows=35682472 width=10) (actual time=0.007..3705.647 rows=35682474 loops=1) 
      -> Hash (cost=1.26..1.26 rows=26 width=14) (actual time=0.028..0.028 rows=26 loops=1) 
        Buckets: 1024 Batches: 1 Memory Usage: 2kB 
        -> Seq Scan on os_desc os (cost=0.00..1.26 rows=26 width=14) (actual time=0.003..0.010 rows=26 loops=1) 
    Total runtime: 25565.199 ms 
    (8 rows) 

이것은 내 쿼리의 실행 시간을 효과적으로 두 배로 만듭니다. 제 질문은, 제가 그림에서 무엇을 떠나지 않았습니까? 이러한 작은 조회가 쿼리 실행 시간에 큰 차이를 일으키지 않는다고 생각합니다.

+0

는 모두'impressions.os_id'와'os.os_id'에 인덱스를해야합니까? – house9

+0

인덱스는 비트 마스크 인덱스 스캔을 생성합니다 (충분한 선택적인 WHERE 절이 없어도 모든 행이 필요합니다. 노출 인덱스가 인덱스에없는 것으로 가정). – wildplasser

+0

예 모두 인덱스 (btree (os_id)) – Istvan

답변

4

(권장) 명시 적 ANSI와 구문 가입 재 작성 : 더 많거나 적은 하나 정확히 이상의 경기가 os_desc에서 발견되는 경우 모든

SELECT COUNT(impression_id), imp.os_id, os.os_desc 
FROM bi.impressions imp 
JOIN bi.os_desc os ON os.os_id = imp.os_id 
GROUP BY imp.os_id, os.os_desc; 

첫 번째, 두 번째 쿼리 , 잘못 될 수도 있습니다 노출의 모든 행 참조 무결성을 보장 장소에 os_id외래 키 제약, 플러스 bi.impressions.os_idNOT NULL 제약이있는 경우
이 배제 될 수있다.

SELECT COUNT(*) AS ct, imp.os_id, os.os_desc 
FROM bi.impressions imp 
JOIN bi.os_desc  os USING (os_id) 
GROUP BY imp.os_id, os.os_desc; 

count(*) 약간 count(column)보다 빠른 : 그렇다면, 첫 번째 단계에서,에 단순화합니다. 개수에 대한 열 별칭을 추가하십시오. 아직
빠른 :

SELECT os_id, os.os_desc, sub.ct 
FROM (
    SELECT os_id, COUNT(*) AS ct 
    FROM bi.impressions 
    GROUP BY 1 
    ) sub 
JOIN bi.os_desc os USING (os_id) 

그룹 첫째, 나중에 가입 할 수 있습니다. 더 자세한 사항은 여기에 :
Aggregate a single column in query with many columns
PostgreSQL - order by an array

+0

감사합니다. Erwin, 나는 당신이 링크 한 문서를 읽는 것 또한 성능에 대한 영향을 이해하기 위해 이것들에 대한 설명 분석을 실행 중입니다. – Istvan

+1

Erwin, 귀하의 쿼리 승리, 감사합니다! 또한 문서를 가져 주셔서 감사합니다. 매우 감사. – Istvan

1
HashAggregate (cost=868719.08..868719.24 rows=16 width=10) 
HashAggregate (cost=1448560.83..1448564.99 rows=416 width=22) 

흠, 10-22의 폭이 두 배입니다. 아마도 전에 그룹화 한 후에 가입해야합니까?

+0

http :// /use-the-indexluke.com/sql/explain-plan/postgresql/operations –

+0

안녕 데이빗, 어떻게해야합니까? – Istvan

1

다음 쿼리는 쿼리 실행 시간을 늘리지 않고 문제를 해결합니다. 여전히 간단한 조인을 추가하면 실행 시간이 현저하게 늘어나는 이유는 여전히 의문이지만, Postgres의 특정 질문 일 수도 있고이 분야에 대한 광범위한 경험을 가진 사람이 궁극적으로 대답 할 수도 있습니다.

WITH 
    OSES AS (SELECT os_id,os_desc from bi.os_desc) 
SELECT 
    COUNT(impression_id) as imp_count, 
    os_desc FROM bi.impressions imp, 
    OSES os 
WHERE 
    os.os_id=imp.os_id 
GROUP BY os_desc 
ORDER BY imp_count; 
+0

작업을 수행하는 데 시간이 필요합니다. 더 많은 작업을 수행하는 데 더 많은 시간이 소요됩니다. 간단한 조인은 여전히 ​​수행해야하는 작업입니다. 하나가 아닌 두 가지로 그룹화하면 더 많은 작업을 수행 할 수 있습니다. BTW, 위 쿼리는 BI.os_desc를 쿼리에 직접 통합하여 WITH를 사용하지 않고 작성할 수 있습니다. 증가 된 속도의 핵심은 with가 아니라 GROUP BY에서 불필요한 컬럼을 제거하는 것입니다. – jjanes