Tema ini menjelaskan cara mengoptimalkan kinerja kueri instance AnalyticDB for PostgreSQL dalam berbagai skenario.
Kumpulkan statistik tabel
Pengoptimal kueri AnalyticDB for PostgreSQL mengoptimalkan rencana kueri dan memperkirakan biayanya berdasarkan statistik tabel yang di-query. Jika tidak ada statistik yang dikumpulkan dari tabel yang di-query atau statistik tabel sudah usang, pengoptimal kueri akan menggunakan nilai default atau nilai lama. Akibatnya, pengoptimal kueri tidak dapat menghasilkan rencana kueri yang optimal. Kami menyarankan Anda mengumpulkan statistik pada tabel setelah sejumlah besar data dimuat atau lebih dari 20% data tabel diperbarui.
Pernyataan ANALYZE memungkinkan Anda mengumpulkan statistik pada semua tabel, semua kolom tabel, atau kolom tertentu dari tabel. Dalam kebanyakan kasus, kami menyarankan Anda mengumpulkan statistik pada semua tabel atau semua kolom tabel. Namun, jika Anda ingin memiliki kontrol lebih atas pengumpulan statistik tabel, Anda dapat memilih hanya mengumpulkan statistik pada kolom tempat kunci gabungan, kondisi filter, atau indeks dibuat.
Contoh:
Setelah sejumlah besar data diimpor, jalankan pernyataan berikut untuk mengumpulkan statistik pada semua tabel:
ANALYZE;Setelah sejumlah besar data disisipkan, diperbarui, atau dihapus di tabel t, jalankan pernyataan berikut untuk mengumpulkan statistik pada semua kolom tabel tersebut:
ANALYZE t;Jalankan pernyataan berikut untuk mengumpulkan statistik pada kolom a tabel t:
ANALYZE t(a);
Pilih pengoptimal kueri
AnalyticDB for PostgreSQL menyediakan dua pengoptimal kueri: Legacy dan ORCA. Setiap pengoptimal kueri memiliki kelebihan dan kekurangan masing-masing dalam berbagai skenario.
Pengoptimal Kueri Legacy
Ini adalah pengoptimal kueri default. Pengoptimal kueri Legacy membutuhkan waktu singkat untuk mengoptimalkan pernyataan SQL. Ideal untuk kueri sederhana dengan tingkat konkurensi tinggi yang memerlukan penggabungan tidak lebih dari tiga tabel dan untuk penulisan atau pembaruan data dengan tingkat konkurensi tinggi yang dilakukan menggunakan pernyataan INSERT, UPDATE, atau DELETE.
Pengoptimal Kueri ORCA
Pengoptimal kueri ORCA dirancang untuk mengoptimalkan kueri kompleks. Ini melintasi lebih banyak jalur eksekusi, sehingga membutuhkan waktu lebih lama daripada pengoptimal kueri Legacy untuk menghasilkan rencana optimal untuk setiap kueri. Kami menyarankan Anda memilih pengoptimal kueri ORCA untuk kueri kompleks yang memerlukan penggabungan lebih dari tiga tabel untuk menyelesaikan pekerjaan ETL (ekstraksi, transformasi, pemuatan) dan pelaporan. Selain itu, pengoptimal kueri ORCA menghilangkan kebutuhan untuk menggabungkan tabel dalam subquery dan secara dinamis menyaring partisi. Oleh karena itu, kami menyarankan Anda memilih pengoptimal kueri ORCA untuk mengoptimalkan pernyataan SQL yang memiliki subquery dan digunakan untuk menanyakan data dari tabel terpartisi tempat kondisi filter ditentukan parameter dibuat.
Contoh berikut menunjukkan cara mengonfigurasi kedua pengoptimal Legacy dan ORCA untuk sesi:
-- Aktifkan pengoptimal kueri Legacy.
set optimizer = off;
-- Aktifkan pengoptimal kueri ORCA.
set optimizer = on;Anda dapat menjalankan pernyataan berikut untuk melihat pengoptimal saat ini:
show optimizer;
Nilai on menunjukkan bahwa pengoptimal kueri ORCA digunakan.
Nilai off menunjukkan bahwa pengoptimal Legacy digunakan.Secara default, AnalyticDB for PostgreSQL V4.3 menggunakan pengoptimal Legacy. AnalyticDB for PostgreSQL V6.0 menggunakan pengoptimal ORCA.
Untuk mengonfigurasi pengoptimal Legacy dan ORCA untuk sebuah instance, Anda harus Submit a ticket.
Gunakan indeks untuk mempercepat kueri
Jika kueri berisi kondisi filter yang digunakan untuk mengidentifikasi nilai identik atau nilai dalam rentang tertentu dan hanya sejumlah kecil data yang diperoleh, Anda dapat membuat indeks pada kolom yang digunakan sebagai kriteria filter untuk mempercepat pemindaian data. AnalyticDB for PostgreSQL mendukung tiga jenis indeks berikut:
Indeks B-tree: Jika sebuah kolom memiliki sejumlah besar nilai unik dan digunakan untuk menyaring, menggabungkan, atau mengurutkan data, buat indeks B-tree.
Indeks Bitmap: Jika sebuah kolom memiliki sejumlah kecil nilai unik dan lebih dari satu kondisi filter dibuat padanya, buat indeks bitmap.
Indeks GiST: Jika Anda ingin menanyakan lokasi geografis, rentang, fitur gambar, atau nilai Geometri, buat indeks GiST.
Contoh:
Jika Anda menjalankan pernyataan berikut untuk menanyakan data dari tabel tanpa indeks, sistem memindai semua data tabel dan kemudian menyaring data berdasarkan kondisi filter yang ditentukan dalam kueri:
postgres=# EXPLAIN SELECT * FROM t WHERE b = 1;
QUERY PLAN
-------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16)
-> Table Scan on t (cost=0.00..431.00 rows=1 width=16)
Filter: b = 1
Settings: optimizer=on
Optimizer status: PQO version 1.609
(5 rows)Jalankan pernyataan berikut untuk membuat indeks B-tree pada kolom b tabel t:
postgres=# CREATE INDEX i_t_b ON t USING btree (b);
CREATE INDEXJika Anda menjalankan pernyataan berikut untuk menanyakan data dari tabel dengan indeks, sistem mendapatkan data berdasarkan indeks:
postgres=# EXPLAIN SELECT * FROM t WHERE b = 1;
QUERY PLAN
-----------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..2.00 rows=1 width=16)
-> Index Scan using i_t_b on t (cost=0.00..2.00 rows=1 width=16)
Index Cond: b = 1
Settings: optimizer=on
Optimizer status: PQO version 1.609
(5 rows)Lihat rencana kueri
Rencana kueri adalah serangkaian langkah yang dieksekusi oleh AnalyticDB for PostgreSQL untuk menyelesaikan kueri. Ini setara dengan algoritma. Anda dapat menganalisis proses eksekusi kueri berdasarkan rencana kueri untuk mengetahui mengapa pernyataan SQL dieksekusi lambat. Jika Anda menambahkan kata kunci EXPLAIN ke kueri, sistem hanya menampilkan rencana kueri tetapi tidak mengeksekusi pernyataan SQL yang ditentukan. Jika Anda menambahkan kata kunci EXPLAIN ANALYZE ke kueri, sistem mengeksekusi pernyataan SQL yang ditentukan, mengumpulkan informasi eksekusi kueri, dan kemudian menampilkan informasi tersebut dalam rencana kueri.
Contoh berikut menunjukkan rencana kueri dengan kata kunci EXPLAIN ditambahkan ke kueri:
postgres=# EXPLAIN SELECT a, b FROM t; QUERY PLAN ------------------------------------------------------------------------------ Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..4.00 rows=100 width=8) -> Seq Scan on t (cost=0.00..4.00 rows=34 width=8) Optimizer status: legacy query optimizer (3 rows)Contoh berikut menunjukkan rencana kueri dengan kata kunci EXPLAIN ANALYZE ditambahkan ke kueri:
postgres=# EXPLAIN ANALYZE SELECT a, b FROM t; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..4.00 rows=100 width=8) Rows out: 100 rows at destination with 2.728 ms to first row, 2.838 ms to end, start offset by 0.418 ms. -> Seq Scan on t (cost=0.00..4.00 rows=34 width=8) Rows out: Avg 33.3 rows x 3 workers. Max 37 rows (seg2) with 0.088 ms to first row, 0.107 ms to end, start offset by 2.887 ms. Slice statistics: (slice0) Executor memory: 131K bytes. (slice1) Executor memory: 163K bytes avg x 3 workers, 163K bytes max (seg0). Statement statistics: Memory used: 128000K bytes Optimizer status: legacy query optimizer Total runtime: 3.739 ms (11 rows)
Rencana kueri terdiri dari operator dan mengatur informasi mereka untuk memproses data dalam urutan logis.
AnalyticDB for PostgreSQL mendukung jenis operator berikut:
Operator Pemindaian Data: Seq Scan, Table Scan, Index Scan, dan Bitmap Scan.
Operator Penggabungan: Hash Join, Nested Loop, dan Merge Join.
Operator Agregasi: Hash Aggregate dan Group Aggregate.
Operator Distribusi: Redistribute Motion, Broadcast Motion, dan Gather Motion.
Operator Lainnya: Hash, Sort, Limit, dan Append.
postgres=# EXPLAIN SELECT * FROM t1, t2 WHERE t1.b = t2.b;
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..862.00 rows=1 width=32)
-> Hash Join (cost=0.00..862.00 rows=1 width=32)
Hash Cond: t1.b = t2.b
-> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16)
Hash Key: t1.b
-> Table Scan on t1 (cost=0.00..431.00 rows=1 width=16)
-> Hash (cost=431.00..431.00 rows=1 width=16)
-> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=16)
Hash Key: t2.b
-> Table Scan on t2 (cost=0.00..431.00 rows=1 width=16)
Settings: optimizer=on
Optimizer status: PQO version 1.609
(12 rows)
Rencana kueri sebelumnya dijelaskan sebagai berikut:
Operator Table Scan memindai tabel t1 dan t2.
Operator Redistribute Motion mendistribusikan ulang data tabel t1 dan t2 berdasarkan nilai hash kolom b mereka ke node komputasi.
Operator Hash membuat kunci hash yang digunakan untuk penggabungan pada tabel t2.
Operator Hash Join menggabungkan data tabel t1 dan t2.
Operator Gather Motion mentransmisikan hasil komputasi ke node koordinator. Node koordinator kemudian mentransmisikan hasil komputasi ke klien.
Rencana kueri aktual bervariasi berdasarkan pernyataan SQL yang Anda tentukan.
Hapus operator distribusi untuk meningkatkan kinerja kueri
Saat Anda memanggil operator penggabungan atau agregasi, AnalyticDB for PostgreSQL menambahkan operator distribusi berdasarkan distribusi data untuk mendistribusikan ulang (Redistribute Motion) atau menyiarkan (Broadcast Motion) data. Operator distribusi memakan sejumlah besar sumber daya jaringan. Untuk meningkatkan kinerja kueri, kami menyarankan Anda membuat tabel dan menyesuaikan logika bisnis untuk menghilangkan kebutuhan akan operator distribusi.
Cara Kerjanya
Jika kunci distribusi dari dua tabel yang ingin Anda gabungkan tidak sesuai dengan logika bisnis, Anda dapat mengubah kunci distribusi mereka untuk menghilangkan kebutuhan akan operator distribusi.
Contoh:
SELECT * FROM t1, t2 WHERE t1.a=t2.a;Dalam contoh ini, kunci distribusi tabel t1 adalah kolom a.
Jika kunci distribusi tabel t2 adalah kolom b, AnalyticDB for PostgreSQL mendistribusikan ulang data tabel t2:
postgres=# EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a; QUERY PLAN ------------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..862.00 rows=1 width=32) -> Hash Join (cost=0.00..862.00 rows=1 width=32) Hash Cond: t1.a = t2.a -> Table Scan on t1 (cost=0.00..431.00 rows=1 width=16) -> Hash (cost=431.00..431.00 rows=1 width=16) -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16) Hash Key: t2.a -> Table Scan on t2 (cost=0.00..431.00 rows=1 width=16) Settings: optimizer=on Optimizer status: PQO version 1.609 (10 rows)Jika kunci distribusi tabel t2 juga merupakan kolom a, AnalyticDB for PostgreSQL menggabungkan tabel t1 dan t2 tanpa mendistribusikan ulang data tabel t2:
postgres=# EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a; QUERY PLAN ------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..862.00 rows=1 width=32) -> Hash Join (cost=0.00..862.00 rows=1 width=32) Hash Cond: t1.a = t2.a -> Table Scan on t1 (cost=0.00..431.00 rows=1 width=16) -> Hash (cost=431.00..431.00 rows=1 width=16) -> Table Scan on t2 (cost=0.00..431.00 rows=1 width=16) Settings: optimizer=on Optimizer status: PQO version 1.609 (8 rows)
Optimalkan tipe data kolom yang akan digabungkan
Kolom yang ingin Anda gabungkan harus memiliki tipe data yang sama untuk mencegah konversi tipe data eksplisit atau implisit, karena konversi tipe data menyebabkan redistribusi data.
Konversi Tipe Eksplisit
Dalam pernyataan SQL, tipe data kolom yang ingin Anda gabungkan mungkin dipaksa dikonversi. Ini disebut konversi tipe eksplisit. Misalnya, kolom a tabel t menggunakan tipe data int, tetapi dikonversi ke tipe data numerik oleh penggabungan.
Setelah tipe data kolom dikonversi secara eksplisit, fungsi hash atau nilai data dalam kolom tersebut berubah. Oleh karena itu, kami menyarankan Anda menghindari konversi tipe data pada kolom yang ingin Anda gabungkan.
Sebagaimana ditunjukkan dalam contoh berikut, konversi tipe eksplisit memicu redistribusi data:
-- Jalankan penggabungan tanpa konversi tipe data. postgres=# EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a; QUERY PLAN ------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..862.00 rows=1 width=32) -> Hash Join (cost=0.00..862.00 rows=1 width=32) Hash Cond: t1.a = t2.a -> Table Scan on t1 (cost=0.00..431.00 rows=1 width=16) -> Hash (cost=431.00..431.00 rows=1 width=16) -> Table Scan on t2 (cost=0.00..431.00 rows=1 width=16) Settings: optimizer=on Optimizer status: PQO version 1.609 (8 rows) -- Jalankan penggabungan dengan konversi tipe eksplisit. postgres=# EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a::numeric; QUERY PLAN ------------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..862.00 rows=1 width=32) -> Hash Join (cost=0.00..862.00 rows=1 width=32) Hash Cond: t1.a::numeric = t2.a::numeric -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16) Hash Key: t1.a::numeric -> Table Scan on t1 (cost=0.00..431.00 rows=1 width=16) -> Hash (cost=431.00..431.00 rows=1 width=16) -> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=16) Hash Key: t2.a::numeric -> Table Scan on t2 (cost=0.00..431.00 rows=1 width=16) Settings: optimizer=on Optimizer status: PQO version 1.609 (12 rows)Konversi Tipe Implisit
Jika Anda ingin menggabungkan lebih dari satu kolom dari dua tabel tetapi salah satu kolom menggunakan tipe data yang berbeda di setiap tabel, tipe data dalam kolom tersebut perlu dikonversi. Ini disebut konversi tipe implisit.
Setelah tipe data kolom dikonversi secara implisit, fungsi hash atau nilai dalam tipe data asli mungkin berbeda dari yang ada dalam tipe data baru. Akibatnya, AnalyticDB for PostgreSQL mendistribusikan ulang data pada kolom tersebut. Oleh karena itu, kami menyarankan Anda memilih kolom dengan tipe data yang sama sebagai kunci penggabungan.
Dalam contoh berikut, kolom a tabel t1 menggunakan tipe data "timestamp without time zone" dan kolom a tabel t2 menggunakan tipe data "timestamp with time zone". Ini berarti bahwa dua kolom a menggunakan fungsi hash yang berbeda. Akibatnya, AnalyticDB for PostgreSQL mendistribusikan ulang data mereka sebelum menggabungkannya.
postgres=# CREATE TABLE t1 (a timestamp without time zone); CREATE TABLE postgres=# CREATE TABLE t2 (a timestamp with time zone); CREATE TABLE postgres=# postgres=# EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a; QUERY PLAN ------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice2; segments: 3) (cost=0.04..0.11 rows=4 width=16) -> Nested Loop (cost=0.04..0.11 rows=2 width=16) Join Filter: t1.a = t2.a -> Seq Scan on t1 (cost=0.00..0.00 rows=1 width=8) -> Materialize (cost=0.04..0.07 rows=1 width=8) -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..0.04 rows=1 width=8) -> Seq Scan on t2 (cost=0.00..0.00 rows=1 width=8) (7 rows)
Lokasi kemiringan data
Jika kueri Anda sangat lambat atau penggunaan sumber daya tidak merata, periksa apakah kemiringan data telah terjadi.
Secara khusus, periksa jumlah baris yang didistribusikan ke setiap node komputasi. Jika baris tabel didistribusikan secara tidak merata di antara node komputasi, data tabel tersebut condong.
postgres=# SELECT gp_segment_id, count(1) FROM t1 GROUP BY 1 ORDER BY 2 DESC;
gp_segment_id | count
---------------+-------
0 | 16415
2 | 37
1 | 32
(3 rows)Jika data tabel condong, kami menyarankan Anda menggunakan salah satu metode berikut untuk menentukan kunci distribusi baru untuk tabel tersebut:
Buat ulang tabel dan tentukan kunci distribusi baru.
Jalankan pernyataan
ALTER TABLE t1 SET DISTRIBUTED BY (b);untuk mengubah kunci distribusi.
Lihat pernyataan SQL yang sedang berjalan
Jika sejumlah besar pernyataan SQL dieksekusi secara bersamaan, kueri bersamaan menjadi lambat dan instance AnalyticDB for PostgreSQL Anda mungkin melaporkan kekurangan sumber daya.
Anda dapat memperoleh status instance AnalyticDB for PostgreSQL Anda dari tampilan pg_stat_activity. Tampilan ini mencantumkan semua pernyataan SQL bersamaan. Anda dapat menentukan apakah kueri membutuhkan waktu yang tidak normal berdasarkan bidang query_start dalam tampilan ini.
Contoh:
postgres=# SELECT * FROM pg_stat_activity;
datid | datname | procpid | sess_id | usesysid | usename | current_query | waiting | query_start | backend_start | client_addr | client_port | application_name | xact_start | waiting_reason
-------+----------+---------+---------+----------+------------+---------------------------------+---------+-------------------------------+-------------------------------+-------------+-------------+------------------+-------------------------------+----------------
10902 | postgres | 53666 | 7 | 10 | yineng.cyn | select * from pg_stat_activity; | f | 2019-05-13 20:27:12.058656+08 | 2019-05-13 20:16:14.179612+08 | | -1 | psql | 2019-05-13 20:27:12.058656+08 |
10902 | postgres | 54158 | 9 | 10 | yineng.cyn | select * from t t1, t t2; | f | 2019-05-13 20:26:28.138641+08 | 2019-05-13 20:17:40.368623+08 | | -1 | psql | 2019-05-13 20:26:28.138641+08 |
(2 rows)Berikut ini menjelaskan bidang penting dalam contoh sebelumnya:
procpid: ID proses utama yang mengeksekusi kueri.
usename: nama pengguna dari pengguna yang mengeksekusi kueri.
current_query: teks kueri.
waiting: menunjukkan apakah kueri dalam keadaan menunggu.
query_start: waktu mulai kueri.
backend_start: waktu ketika proses yang digunakan untuk mengeksekusi kueri dimulai.
xact_start: waktu ketika transaksi tempat kueri dimulai.
waiting_reason: alasan mengapa kueri tetap dalam keadaan menunggu.
Selain itu, Anda dapat menambahkan kondisi current_query ! = '<IDLE>' ke bidang current_query untuk melihat pernyataan SQL yang sedang dieksekusi.
SELECT * FROM pg_stat_activity WHERE current_query ! = '<IDLE>';Jalankan pernyataan berikut untuk melihat lima pernyataan SQL teratas yang membutuhkan waktu paling lama untuk dieksekusi:
SELECT current_timestamp - query_start as runtime
, datname
, usename
, current_query
FROM pg_stat_activity
WHERE current_query ! = '<IDLE>'
ORDER BY runtime DESC
LIMIT 5;Periksa status kunci
Jika sebuah objek dalam instance AnalyticDB for PostgreSQL Anda tetap terkunci oleh kueri untuk waktu yang lama, kueri lain yang melibatkan objek tersebut mungkin tetap dalam keadaan menunggu dan tidak dapat dieksekusi dengan benar. Jalankan pernyataan berikut untuk melihat tabel yang terkunci di instance AnalyticDB for PostgreSQL Anda:
SELECT pgl.locktype AS locktype
, pgl.database AS database
, pgc.relname AS relname
, pgl.relation AS relation
, pgl.transaction AS transaction
, pgl.pid AS pid
, pgl.mode AS mode
, pgl.granted AS granted
, pgsa.current_query AS query
FROM pg_locks pgl
JOIN pg_class pgc ON pgl.relation = pgc.oid
JOIN pg_stat_activity pgsa ON pgl.pid = pgsa.procpid
ORDER BY pgc.relname;Jika sebuah kueri tidak merespons karena sedang menunggu kunci pada sebuah tabel dilepaskan, Anda dapat memeriksa kunci pada tabel tersebut. Gunakan salah satu metode berikut untuk menyelesaikan masalah ini jika diperlukan:
Batalkan kueri ini. Jika sesi yang ditunjukkan oleh parameter pid sedang idle, metode ini tidak cocok. Selain itu, Anda harus menghapus data dan membatalkan transaksi tempat kueri tersebut setelah Anda membatalkan kueri.
SELECT pg_cancel_backend(pid);CatatanFungsi
pg_cancel_backendtidak berpengaruh pada sesi tempat nilai parameterpg_stat_activity.current_queryadalah IDLE. Dalam situasi ini, Anda dapat memanggil fungsipg_terminate_backenduntuk menghapus data.Hentikan sesi tempat kueri tersebut termasuk. Setelah sesi dihentikan, transaksi yang belum disimpan di dalamnya dibatalkan.
SELECT pg_terminate_backend(pid);
Gabungkan tabel menggunakan loop bersarang untuk meningkatkan kinerja kueri
Secara default, penggabungan loop bersarang dinonaktifkan di AnalyticDB for PostgreSQL. Jika hanya sejumlah kecil data yang dikembalikan oleh kueri Anda, kinerja kueri mungkin tidak optimal.
Contoh:
SELECT *
FROM t1 join t2 on t1.c1 = t2.c1
WHERE t1.c2 >= '230769548' and t1.c2 < '230769549'
LIMIT 100;Dalam contoh sebelumnya, tabel t1 dan t2 besar. Namun, kondisi filter (t1.c2>= '230769548' and t1.c2 < '23432442') pada tabel t1 menyaring sebagian besar catatan data dan klausa LIMIT lebih lanjut membatasi catatan data yang memenuhi syarat. Akibatnya, hanya sejumlah kecil data yang di-query. Dalam situasi ini, Anda dapat menggunakan loop bersarang untuk menggabungkan kedua tabel.
Untuk menggabungkan tabel menggunakan loop bersarang, Anda harus menjalankan pernyataan SET. Contoh:
show enable_nestloop ;
enable_nestloop
-----------------
off
SET enable_nestloop = on ;
show enable_nestloop ;
enable_nestloop
-----------------
on
explain SELECT * FROM t1 join t2 on t1.c1 = t2.c1 WHERE t1.c2 >= '230769548' and t1.c2 < '23432442' LIMIT 100;
QUERY PLAN
-----------------------------------------------------------------------------------------------
Limit (cost=0.26..16.31 rows=1 width=18608)
-> Nested Loop (cost=0.26..16.31 rows=1 width=18608)
-> Index Scan using t1 on c2 (cost=0.12..8.14 rows=1 width=12026)
Filter: ((c2 >= '230769548'::bpchar) AND (c2 < '230769549'::bpchar))
-> Index Scan using t2 on c1 (cost=0.14..8.15 rows=1 width=6582)
Index Cond: ((c1)::text = (T1.c1)::text)Dalam contoh sebelumnya, tabel t1 dan t2 digabungkan menggunakan loop bersarang untuk mengoptimalkan kinerja kueri.