kinerja postgres_fdw lambat

12

Permintaan pada orang asing berikut ini membutuhkan waktu sekitar 5 detik untuk dieksekusi pada 3,2 juta baris:

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

Ketika saya menjalankan kueri yang sama pada tabel normal, ia kembali dalam 0,6 detik. Rencana pelaksanaannya sangat berbeda:

Tabel Normal

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

Meja Asing

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

Saya pikir saya membayar harga tinggi untuk GROUP BYklausa, yang tidak diteruskan ke server asing ketika saya EXPLAIN VERBOSE:

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

Ini mengembalikan 700 ribu baris. Apakah ada jalan keluarnya?

Saya menghabiskan banyak waktu membaca halaman dokumentasi ini kemarin, dan berpikir saya telah menemukan jawaban saya dengan pengaturan use_remote_estimatetrue, tetapi itu tidak berpengaruh.

Saya punya akses ke server asing untuk membuat objek jika perlu. Nilai cap waktu dalam WHEREklausa bisa berupa apa saja; itu tidak datang dari daftar nilai yang telah ditentukan.

J-DawG
sumber
3
Ada beberapa peningkatan pushdown di 9.6 yang mungkin menarik: wiki.postgresql.org/wiki/NewIn96#postgres_fdw
Jack mengatakan coba topanswers.xyz
Ketika Anda mengatakan tabel normal vs asing apakah Anda menjalankan tabel yang sama (lokal dan jarak jauh) atau tabel sebenarnya berbeda (berbunyi seolah-olah mereka), jika mereka berbeda periksa pengindeksan pada server jauh pastikan mereka sama karena Anda tampaknya membaca sumber informasi yang sangat berbeda IntterraNearRealTimeUnitReflexes300sForeignvs IntterraNearRealTimeUnitReflexes300sdan idx_incident_date_time_300 saya berasumsi yang 300-an adalah sama, tetapi mungkin ada baiknya memeriksa apakah idx_incident_date_time_300indeks ada di server asing
Ste Bov
2
Dari apa yang saya mengerti, agregat (COUNT) tidak didorong ke server jauh, yang akan menjelaskan waktu permintaan yang lama. Tampaknya fitur ini akan muncul di halaman 10 - depesz.com/2016/10/25/…
Jerome WAGNER
@JeromeWAGNER - Luar Biasa
J-DawG

Jawaban:

7

Jika Anda menggunakan use_remote_estimatepastikan untuk menjalankan ANALYZE tabel asing (saya melihat estimasi cukup dekat dengan yang dikembalikan, Anda mungkin akan melakukannya). Selain itu, peningkatan pushdown tidak tersedia dalam versi <9.5. Saya juga berasumsi bahwa Anda memiliki struktur tabel yang sama di server jauh baik (termasuk indeks). Jika bitmap diperlukan karena kardinalitas rendah, itu tidak akan menggunakan indeks karena keterbatasan pada mekanisme pushdown. Anda mungkin ingin mengurangi jumlah baris yang dikembalikan untuk memaksakan pemindaian indeks BTREE ( rentang cap waktu). Sayangnya, tidak ada cara bersih untuk menghindari SeqScan di server jauh jika filter mengembalikan + 10% dari baris tabel (dapat bervariasi persentase ini jika perencana menganggap pemindaian seluruh tabel lebih murah daripada mencari bacaan). Jika Anda menggunakan SSD, Anda mungkin akan menemukan manfaat untuk melakukan tweak random_page_cost).

Anda dapat menggunakan CTE untuk mengisolasi perilaku 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";
3manuek
sumber
1
Performanya sama dengan menggunakan CTE. Akan mencoba pengaturan random_page_cost. Terima kasih!
J-DawG