Menghitung baris dalam tabel besar dikenal lambat di PostgreSQL. Untuk mendapatkan angka yang tepat itu harus melakukan penghitungan penuh baris karena sifat MVCC . Ada cara untuk mempercepat ini secara dramatis jika jumlah tersebut tidak tidak harus tepat seperti itu tampaknya dalam kasus Anda.
Alih-alih mendapatkan hitungan pastinya ( lambat dengan tabel besar):
SELECT count(*) AS exact_count FROM myschema.mytable;
Anda mendapatkan perkiraan yang mendekati seperti ini ( sangat cepat ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
Seberapa dekat perkiraannya tergantung pada apakah Anda ANALYZE
cukup berlari . Biasanya sangat dekat.
Lihat FAQ Wiki PostgreSQL .
Atau halaman wiki khusus untuk kinerja hitungan (*) .
Lebih baik
Artikel di dalam PostgreSQL Wiki adalah adalah sedikit ceroboh . Ini mengabaikan kemungkinan bahwa ada beberapa tabel dengan nama yang sama dalam satu database - dalam skema yang berbeda. Untuk menjelaskan itu:
SELECT c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable'
AND n.nspname = 'myschema'
Atau lebih baik lagi
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
Lebih cepat, lebih sederhana, lebih aman, lebih elegan. Lihat manual tentang Jenis Pengenal Objek .
Gunakan to_regclass('myschema.mytable')
di Postgres 9.4+ untuk menghindari pengecualian untuk nama tabel yang tidak valid:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
Seperti komentar @a_horse , klausa yang baru ditambahkan untuk SELECT
perintah tersebut mungkin berguna jika statistik dalam pg_class
tidak cukup terkini karena alasan tertentu. Sebagai contoh:
- Tidak ada
autovacuum
lari.
- Segera setelah besar
INSERT
atau DELETE
.
TEMPORARY
tabel (yang tidak tercakup oleh autovacuum
).
Ini hanya melihat pemilihan acak n % ( 1
dalam contoh) blok dan menghitung baris di dalamnya. Sampel yang lebih besar meningkatkan biaya dan mengurangi kesalahan, pilihan Anda. Akurasi bergantung pada lebih banyak faktor:
- Distribusi ukuran baris. Jika blok tertentu kebetulan memiliki baris yang lebih lebar dari biasanya, jumlahnya lebih rendah dari biasanya, dll.
- Tupel mati atau
FILLFACTOR
menempati ruang per blok. Jika didistribusikan secara tidak merata di seluruh tabel, perkiraan mungkin salah.
- Kesalahan pembulatan umum.
Dalam kebanyakan kasus, perkiraan dari pg_class
akan lebih cepat dan lebih akurat.
Jawaban untuk pertanyaan sebenarnya
Pertama, saya perlu mengetahui jumlah baris dalam tabel itu, jika jumlah total lebih besar dari beberapa konstanta yang telah ditentukan sebelumnya,
Dan apakah itu ...
... mungkin pada saat hitungan melewati nilai konstanta saya, itu akan menghentikan penghitungan (dan tidak menunggu untuk menyelesaikan penghitungan untuk menginformasikan jumlah baris lebih besar).
Iya. Anda dapat menggunakan subkueri denganLIMIT
:
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres benar-benar berhenti menghitung di luar batas yang diberikan, Anda mendapatkan hitungan tepat dan terkini hingga n baris (500000 dalam contoh), dan n sebaliknya. Tidak secepat perkiraannya pg_class
.