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 BY
klausa, 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_estimate
true, tetapi itu tidak berpengaruh.
Saya punya akses ke server asing untuk membuat objek jika perlu. Nilai cap waktu dalam WHERE
klausa bisa berupa apa saja; itu tidak datang dari daftar nilai yang telah ditentukan.
IntterraNearRealTimeUnitReflexes300sForeign
vsIntterraNearRealTimeUnitReflexes300s
danidx_incident_date_time_300
saya berasumsi yang 300-an adalah sama, tetapi mungkin ada baiknya memeriksa apakahidx_incident_date_time_300
indeks ada di server asingJawaban:
Jika Anda menggunakan
use_remote_estimate
pastikan 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 tweakrandom_page_cost
).Anda dapat menggunakan CTE untuk mengisolasi perilaku GROUP BY:
sumber