postgres_fdw 성능이 느립니다


12

외국인에 대한 다음 쿼리는 320 만 행에서 실행하는 데 약 5 초가 걸립니다.

SELECT x."IncidentTypeCode", COUNT(x."IncidentTypeCode") 
FROM "IntterraNearRealTimeUnitReflexes300sForeign" x 
WHERE x."IncidentDateTime" >= '05/01/2016' 
GROUP BY x."IncidentTypeCode" 
ORDER BY 1;

일반 테이블에서 동일한 쿼리를 실행하면 0.6 초로 반환됩니다. 실행 계획은 상당히 다릅니다.

일반 테이블

Sort  (cost=226861.20..226861.21 rows=4 width=4) (actual time=646.447..646.448 rows=7 loops=1) 
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB 
  -> HashAggregate (cost=226861.12..226861.16 rows=4 width=4) (actual  time=646.433..646.434 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Bitmap Heap Scan on "IntterraNearRealTimeUnitReflexes300s" x  (cost=10597.63..223318.41 rows=708542 width=4) (actual time=74.593..342.110 rows=709376 loops=1) 
        Recheck Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 
        Rows Removed by Index Recheck: 12259 
        Heap Blocks: exact=27052 lossy=26888
        -> Bitmap Index Scan on idx_incident_date_time_300  (cost=0.00..10420.49 rows=708542 width=0) (actual time=69.722..69.722 rows=709376 loops=1) 
           Index Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 

Planning time: 0.165 ms 
Execution time: 646.512 ms

외국 테이블

Sort  (cost=241132.04..241132.05 rows=4 width=4) (actual time=4782.110..4782.112 rows=7 loops=1)   
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB
  -> HashAggregate  (cost=241131.96..241132.00 rows=4 width=4) (actual time=4782.097..4782.100 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Foreign Scan on "IntterraNearRealTimeUnitReflexes300sForeign" x  (cost=10697.63..237589.25 rows=708542 width=4) (actual time=1.916..4476.946 rows=709376 loops=1) 

Planning time: 1.413 ms 
Execution time: 4782.660 ms

나는이 GROUP BY조항에 대해 높은 가격을 지불하고 있다고 생각하는데, 나는 이 때 외국 서버로 전달되지 않습니다 EXPLAIN VERBOSE.

SELECT
    "IncidentTypeCode"
FROM
    PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
WHERE
    (
        (
            "IncidentDateTime" >= '2016-05-01 00:00:00' :: TIMESTAMP WITHOUT TIME ZONE
        )
    )

700k 행을 반환합니다. 이 주위에 방법이 있습니까?

나는 어제이 문서 페이지를 읽는 데 많은 시간을 보냈고, use_remote_estimatetrue 로 설정 하여 답을 찾았다 고 생각 했지만 아무런 효과가 없습니다.

필요한 경우 외부 서버에 액세스하여 객체를 만들 수 있습니다. WHERE절의 타임 스탬프 값은 무엇이든 가능합니다. 사전 정의 된 값 목록에서 제공되지 않습니다.


3
관심을 가질 수있는 9.6에서 일부 푸시 개선이 있습니다 wiki.postgresql.org/wiki/NewIn96#postgres_fdw
잭은 말한다 topanswers.xyz 시도

일반 테이블과 외부 테이블을 말하면 동일한 테이블 (로컬 및 원격) 또는 실제로 다른 테이블 (있는 것처럼 읽음)에서 실행 중일 때 원격 서버의 색인을 확인하십시오. 당신은 완전히 다른 정보 소스를 읽는 것으로 나타으로 IntterraNearRealTimeUnitReflexes300sForeignIntterraNearRealTimeUnitReflexes300s하고 idx_incident_date_time_300 나는 300S의 사람이 같은 추정하지만, 경우에 그것은 가치가 확인 될 수 idx_incident_date_time_300인덱스가 외국 서버에있는
인트 BOV을

2
내가 이해 한 바에 따르면 집계 (COUNT)는 원격 서버로 푸시되지 않으므로 긴 요청 시간을 설명합니다. 이 기능은 pg 10-depesz.com/2016/10/25/에
Jerome WAGNER

@JeromeWAGNER-최고
J-DawG

답변:


7

당신이 사용하는 경우 use_remote_estimate수 있는지 실행 ANALYZE (당신은 아마 그것을 한 것, 나는 꽤 가까이 반환으로 추정 참조) 외국 테이블을. 또한 푸시 다운 개선 사항은 <9.5 버전에서 사용할 수 없습니다. 또한 원격 서버에 동일한 테이블 구조 (인덱스 포함)가 있다고 가정합니다. 카디널리티가 낮아 비트 맵이 필요한 경우 푸시 다운 메커니즘의 제한으로 인해 인덱스를 사용하지 않습니다. BTREE 인덱스 스캔을 강제 실행하기 위해 리턴되는 행의 양을 줄일 수 있습니다 ( 타임 스탬프 범위)). 불행히도, 필터가 테이블 행의 + 10 %를 리턴 할 경우 원격 서버에서 SeqScan을 피할 수있는 확실한 방법은 없습니다 (계획자가 전체 테이블 스캔이 검색 읽기보다 저렴하다고 생각하면이 백분율이 달라질 수 있음). SSD를 사용하는 경우 아마도 조정하는 것이 좋습니다 random_page_cost).

CTE를 사용하여 GROUP BY 동작을 분리 할 수 ​​있습니다.

WITH atable AS (
    SELECT "IncidentTypeCode"
    FROM PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
    WHERE 
       ("IncidentDateTime" 
              BETWEEN '2016-05-01 00:00:00'::TIMESTAMP WITHOUT TIME ZONE 
                  AND '2016-05-02 00:00:00'::TIMESTAMP WITHOUT TIME ZONE)
)
SELECT atable."IncidentTypeCode", COUNT(atable.IncidentTypeCode) 
FROM atable
GROUP BY atable."IncidentTypeCode" 
ORDER BY atable."IncidentTypeCode";

1
CTE를 사용한 성능은 동일했습니다. 그러나 random_page_cost 설정을 시도합니다. 감사!
J-DawG
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.