"Periksa ulang Cond:" baris dalam rencana kueri dengan pemindaian indeks bitmap

21

Ini adalah spin-off dari komentar ke pertanyaan sebelumnya:

Menggunakan PostgreSQL 9.4, sepertinya selalu ada Recheck Cond:baris setelah scan indeks bitmap dalam output rencana kueri EXPLAIN.

Seperti dalam EXPLAINoutput dari pertanyaan yang dirujuk:

->  Bitmap Heap Scan on table_three  (cost=2446.92..19686.74 rows=8159 width=7)
      Recheck Cond: (("timestamp" > (now() - '30 days'::interval)) AND (client_id > 0))
      ->  BitmapAnd  (cost=2446.92..2446.92 rows=8159 width=0)
            ->  Bitmap Index Scan on table_one_timestamp_idx  (cost=0.00..1040.00 rows=79941 width=0)
                  Index Cond: ("timestamp" > (now() - '30 days'::interval))
            ->  Bitmap Index Scan on fki_table_three_client_id  (cost=0.00..1406.05 rows=107978 width=0)
                  Index Cond: (client_id > 0)

Atau dalam output EXPLAIN ANALYZEuntuk tabel sederhana, besar (dengan sangat sedikit work_mem):

EXPLAIN ANALYZE SELECT * FROM aa WHERE a BETWEEN 100000 AND 200000;
Bitmap Heap Scan on aa  (cost=107.68..4818.05 rows=5000 width=4) (actual time=27.629..213.606 rows=100001 loops=1)
  Recheck Cond: ((a >= 100000) AND (a <= 200000))
  Rows Removed by Index Recheck: 758222
  Heap Blocks: exact=693 lossy=3732
  ->  Bitmap Index Scan on aai  (cost=0.00..106.43 rows=5000 width=0) (actual time=27.265..27.265 rows=100001 loops=1)
        Index Cond: ((a >= 100000) AND (a <= 200000))

Apakah itu berarti kondisi indeks harus diperiksa untuk kedua kalinya setelah pemindaian indeks bitmap?
Apa lagi yang bisa kita pelajari dari EXPLAINoutput?

Erwin Brandstetter
sumber

Jawaban:

17

Ketika @Chris mengomentari dengan benar pertanyaan yang dirujuk :

sedikit investigasi nampaknya mengindikasikan bahwa kondisi periksa ulang selalu dicetak dalam EXPLAIN, tetapi sebenarnya hanya dilakukan ketika work_membitmap cukup kecil sehingga menjadi lossy. Pikiran? http://www.postgresql.org/message-id/[email protected]

Walaupun ini semua benar dan pengembang inti Heikki Linnakangas adalah sumber kelas satu, pos tersebut kembali ke tahun 2007 (Postgres 8.2). Berikut ini adalah posting blog oleh Michael Paquier dengan penjelasan terperinci untuk Postgres 9.4 , di mana hasilnya EXPLAIN ANALYZEtelah ditingkatkan dengan informasi lebih lanjut.

The Recheck Cond:line selalu ada untuk scan indeks bitmap. Output dari basic EXPLAINtidak akan memberi tahu kita lebih banyak. Kami mendapatkan informasi tambahan EXPLAIN ANALYZEseperti yang dapat dilihat pada kutipan kedua dalam pertanyaan:

Heap Blocks: exact=693 lossy=3732

Dari total 4425 halaman data (blok), 693 tuple tersimpan dengan tepat (termasuk tuple pointer), sementara 3732 halaman lainnya hilang (hanya halaman data) dalam bitmap. Itu terjadi ketika work_memtidak cukup besar untuk menyimpan seluruh bitmap yang dibangun dari pemindaian indeks dengan tepat (lossless).

Kondisi indeks harus diperiksa ulang untuk halaman-halaman dari bagian yang hilang, karena bitmap hanya mengingat halaman mana yang akan diambil dan bukan tupel yang tepat pada halaman. Tidak semua tupel pada halaman tentu akan melewati kondisi indeks, itu perlu untuk benar-benar memeriksa ulang kondisi.

Ini adalah utas tentang peretas pgsql tempat penambahan baru dibahas . Penulis Etsuro Fujita memberikan formula bagaimana menghitung minimum work_memuntuk menghindari entri bitmap yang hilang dan memeriksa kembali kondisi selanjutnya. Penghitungan ini tidak dapat diandalkan untuk kasus kompleks dengan pemindaian bitmap ganda, sehingga tidak digunakan untuk mengeluarkan angka aktual EXPLAIN. Itu masih bisa berfungsi sebagai perkiraan untuk kasus-kasus sederhana.

Garis tambahan BUFFERS:

Selain itu, ketika dijalankan dengan BUFFERSopsi: EXPLAIN (ANALYZE, BUFFERS) ...baris lain ditambahkan seperti:

Buffers: shared hit=279 read=79

Ini menunjukkan berapa banyak tabel yang mendasari (dan indeks) dibaca dari cache ( shared hit=279) dan berapa banyak yang harus diambil dari disk ( read=79). Jika Anda mengulangi kueri, bagian "baca" biasanya hilang untuk kueri yang tidak terlalu besar, karena semuanya di-cache sekarang setelah panggilan pertama. Panggilan pertama memberitahu Anda berapa yang sudah di-cache. Panggilan selanjutnya menunjukkan seberapa banyak cache Anda dapat menangani (saat ini).

Ada lebih banyak opsi. Manual tentang BUFFERSopsi:

Secara khusus, termasuk jumlah blok bersama yang terkena, baca, kotor, dan tertulis, jumlah blok lokal yang terkena, baca, kotor, dan tertulis, dan jumlah blok temp yang dibaca dan ditulis.

Baca terus, masih ada lagi.
Berikut adalah daftar opsi keluaran dalam kode sumber .

Erwin Brandstetter
sumber
10

Erwin, karena ini adalah diskusi kami di utas komentar sebelumnya, saya memutuskan untuk menyodok sedikit lebih jauh ...

Saya punya pertanyaan yang sangat sederhana dari tabel berukuran cukup. Saya biasanya memiliki cukup work_mem, tetapi dalam hal ini saya menggunakan perintah

SET work_mem = 64;

untuk mengatur yang sangat kecil work_memdan

SET work_mem = default;

untuk mengatur work_memkembali saya menjadi cukup besar untuk permintaan saya.

JELASKAN & Kondisi Periksa Ulang

Jadi, jalankan kueri saya hanya EXPLAINdengan

EXPLAIN 
SELECT * FROM olap.reading_facts
WHERE meter < 20;

Saya memperoleh hasil untuk rendah & tinggi work_mem:

Rendah work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Tinggi work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Singkatnya, EXPLAINhanya untuk , seperti yang diharapkan, rencana kueri menunjukkan bahwa kondisi Periksa ulang dimungkinkan, tetapi kami tidak dapat mengetahui apakah benar-benar akan dihitung.

ANALISIS JELAS & Periksa Kondisi

Saat kami memasukkan ANALYZEdalam kueri, hasilnya menelpon kami lebih lanjut tentang apa yang perlu kami ketahui.

Rendah work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=3.130..13.946 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Rows Removed by Index Recheck: 86727
  Heap Blocks: exact=598 lossy=836
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=3.066..3.066 rows=51840 loops=1)
        Index Cond: (meter < 20)

Tinggi work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=2.647..7.247 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Heap Blocks: exact=1434
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=2.496..2.496 rows=51840 loops=1)
        Index Cond: (meter < 20)

Sekali lagi, seperti yang diharapkan, penyertaan ANALYZEmengungkapkan kepada kami beberapa informasi yang sangat penting. Dalam work_memkasus rendah , kita melihat bahwa ada baris yang dihapus oleh indeks periksa kembali, dan bahwa kita memiliki lossyblok tumpukan.

Kesimpulan? (atau ketiadaan)

Sayangnya, sepertinya EXPLAINsendiri adalah tidak cukup untuk mengetahui apakah recheck indeks akan benar-benar diperlukan karena beberapa baris id ini sedang jatuh dalam mendukung halaman mempertahankan selama pemindaian bitmap tumpukan.

Penggunaan EXPLAIN ANALYZEtidak masalah untuk mendiagnosis masalah dengan kueri panjang sedang, tetapi dalam hal kueri membutuhkan waktu yang sangat lama untuk diselesaikan, kemudian jalankan EXPLAIN ANALYZEuntuk mengetahui bahwa indeks bitmap Anda dikonversi menjadi lossy karena tidak mencukupi work_memmasih merupakan kendala yang sulit. Saya berharap ada cara untuk EXPLAINmemperkirakan kemungkinan kejadian ini dari tabel statistik.

Chris
sumber