Apakah REINDEX berbahaya?


17

Saya sudah mencoba COUNT(*)meja dengan 150.000 baris yang memiliki kunci Primer. Ini alat sekitar 5 menit, jadi saya tahu ini adalah masalah pengindeksan.

Mengutip manual PostgreSQL :

REINDEX mirip dengan setetes dan buat ulang indeks di mana isi indeks dibangun kembali dari awal. Namun, pertimbangan pengunciannya agak berbeda. REINDEX mengunci penulisan tetapi tidak membaca tabel induk indeks. Dibutuhkan juga kunci eksklusif pada indeks spesifik yang sedang diproses, yang akan memblokir bacaan yang mencoba menggunakan indeks itu (...) CREATE INDEX berikutnya mengunci penulisan tetapi tidak membaca; karena indeks tidak ada, tidak ada pembacaan akan mencoba untuk menggunakannya, yang berarti bahwa tidak akan ada pemblokiran tetapi pembacaan mungkin dipaksa menjadi pemindaian berurutan yang mahal.

Dari pengalaman Anda sendiri, dapatkah Anda memberi tahu:

  • adalah REINDEXINGberbahaya? Bisakah itu merusak konsistensi data?
  • Bisakah ini menghabiskan banyak waktu?
  • Apakah ini solusi yang mungkin untuk skenario saya?

Memperbarui:

Solusi yang berhasil bagi kami adalah menciptakan kembali indeks yang sama dengan nama yang berbeda, kemudian menghapus indeks yang lama.

Pembuatan indeks sangat cepat, dan kami telah mengurangi ukuran indeks dari 650 MB menjadi 8 MB. Menggunakan COUNT(*)dengan betweenhanya membutuhkan 3 detik.

Jawaban:


15

Reindexing tidak berbahaya dan tidak dapat merusak konsistensi data. Namun, jika Anda memiliki waktu kritis menulis, Anda dapat kehilangan data jika tabel dikunci dan DML dibatalkan.

Pengindeksan ulang tidak perlu banyak waktu, tetapi biasanya melibatkan membaca seluruh tabel, mengurutkan bidang indeks dan menulis indeks baru. Mengingat waktu untuk COUNT(*)itu kemungkinan akan memakan waktu lima menit atau lebih.

Sepertinya ini bukan masalah pengindeksan. COUNT(*)harus menggunakan pemindaian tabel dalam hal ini tidak ada indeks yang dibaca. Saya berharap Anda memiliki semacam masalah IO.

Coba gunakan COUNT(1)atau COUNT(pk_field)yang dapat menggunakan indeks.

Jika Anda menjalankan pada platform Unix atau Linux Anda mungkin ingin memantau aktivitas disk dengan sar. Anda mungkin juga memiliki disk gagal yang dapat memotong tingkat IO secara dramatis.

Tabel dengan objek besar juga dapat meningkatkan IO secara signifikan untuk membangun catatan untuk COUNT (*).


2
Menurut wiki.postgresql.org, COUNT(*)adalah pilihan terbaik:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80

1

Saya tidak yakin dengan jawaban terbaik untuk Anda. Namun utas ini tampaknya menawarkan beberapa saran bagus: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

Satu catatan adalah bahwa Anda dapat mengimplementasikan TRIGGER untuk mempertahankan jumlah baris dalam tabel terpisah (jika COUNT (*) sering dipanggil oleh aplikasi Anda).

Beberapa tanggapan menyarankan bahwa ini merupakan gejala dari basis data yang belum cukup disedot baru-baru ini (menunjukkan bahwa autovacuum dinonaktifkan pada server Anda atau untuk basis data itu khususnya)?

Saran lain terlihat seperti:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

Dan seseorang yang diidentifikasi sebagai A. Kretschmer mencatat:

Tidak. Implementasi indeks saat ini tidak mengandung informasi tentang visibilitas baris dalam transaksi saat ini. Anda perlu memindai seluruh tabel data untuk mendapatkan jika baris saat ini terlihat dalam transaksi saat ini.

... mendukung komentar saya tentang izin tingkat baris menjadi masalah kinerja.

Pencarian saya juga menemukan WikiVS: MySQL vs. PostgreSQL: COUNT (*) .

Anda dapat membaca dengan teliti hasil-hasil lain yang saya temukan dengan menggunakan Google: kinerja postgresql count (*)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.