postgres_fdw performansı yavaş


12

Bir yabancıyla ilgili aşağıdaki sorgu 3,2 milyon satırda yürütmek için yaklaşık 5 saniye sürer:

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

Aynı sorguyu normal tabloda yürüttüğümde, .6 saniye içinde döner. Uygulama planları oldukça farklıdır:

Normal Tablo

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

Yabancı Tablo

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

Bence ben GROUP BYyabancı sunucuya geçmeyen fıkra için yüksek bir fiyat ödüyorum EXPLAIN VERBOSE:

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

Bu 700 bin satır döndürür. Bunun etrafında bir yol var mı?

Dün bu dokümantasyon sayfasını okumak için çok zaman harcadım ve cevabımı use_remote_estimatetrue olarak ayarlayarak bulduğumu düşündüm , ancak hiçbir etkisi olmadı.

Gerekirse nesne oluşturmak için yabancı sunucuya erişimim var. Maddedeki zaman damgası değeri WHEREherhangi bir şey olabilir; önceden tanımlanmış değerler listesinden gelmez.



Normal vs yabancı tablo dediğinizde, aynı tablo (yerel ve uzaktan) veya aslında farklı tablolar (bunlar sanki okurlar) üzerinde çalışıyorsunuz, eğer farklılarsa uzak sunucudaki dizinlemenin aynı olduğundan emin olun Eğer tamamen farklı bilgi kaynaklarını okuma gibi görünen olarak IntterraNearRealTimeUnitReflexes300sForeignvs IntterraNearRealTimeUnitReflexes300sve idx_incident_date_time_300 ben 300s olanlar aynıdır, ama tahmin eğer buna değer denetimi olabilir idx_incident_date_time_300endeksi yabancı sunucuda mevcutsa
Ste Bov

2
Anladığım kadarıyla, toplamalar (COUNT) uzak sunucuya gönderilmez, bu da uzun istek süresini açıklar. Görünüşe göre bu özellik pg 10'da görünecek - depesz.com/2016/10/25/…
Jerome WAGNER

@JeromeWAGNER - Harika
J-DawG

Yanıtlar:


7

Eğer yabancı tabloyu ANALYZE kullandığınızdan use_remote_estimateemin olursanız (tahminlerin oldukça yakın olduğunu tahmin ediyorum, muhtemelen yapardınız). Ayrıca, aşağı açılan geliştirmeler <9.5 sürümünde mevcut değildir. Ayrıca uzak sunucuda (dizinler dahil) aynı tablo yapısına sahip olduğunu varsayalım. Düşük kardinalite nedeniyle bir bitmap gerekiyorsa, aşağı itme mekanizmasındaki sınırlamalar nedeniyle dizini kullanmayacaktır. BTREE dizin taramasını zorlamak için döndürülen satırların miktarını azaltmak isteyebilirsiniz ( zaman damgası aralıkları). Ne yazık ki, filtre tablonun satırlarının +% 10'unu döndürürse, uzak sunucuda SeqScan'ı önlemenin temiz bir yolu yoktur (planlayıcı tüm tabloyu taramanın okumaktan daha ucuz olduğunu düşünürse bu yüzdeyi değiştirebilir). SSD kullanıyorsanız, muhtemelen ince ayar yapmak için yararlı bulacaksınız random_page_cost).

CTE'yi GROUP GROUP davranışını yalıtmak için kullanabilirsiniz:

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 ile performans aynıydı. Ancak random_page_cost ayarlarını deneyecek. Teşekkürler!
J-DawG
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.