PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Cara cepat untuk menemukan jumlah baris tabel di PostgreSQL

Menghitung baris dalam tabel besar diketahui lambat di PostgreSQL. Model MVCC membutuhkan hitungan penuh baris hidup untuk jumlah yang tepat. Ada solusi untuk mempercepat ini secara dramatis jika hitungannya tidak harus tepat sepertinya ada dalam kasus Anda.

(Ingat bahwa bahkan hitungan "tepat" berpotensi mati pada saat kedatangan!)

Jumlah yang tepat

Lambat untuk tabel besar.
Dengan operasi penulisan bersamaan, mungkin sudah usang saat Anda mendapatkannya.

SELECT count(*) AS exact_count FROM myschema.mytable;
Perkiraan

Sangat cepat :

SELECT reltuples AS estimate FROM pg_class where relname = 'mytable';

Biasanya, perkiraannya sangat dekat. Seberapa dekat, tergantung pada apakah ANALYZE atau VACUUM dijalankan cukup - di mana "cukup" ditentukan oleh tingkat aktivitas tulis ke tabel Anda.

Perkiraan lebih aman

Di atas mengabaikan kemungkinan beberapa tabel dengan nama yang sama dalam satu database - dalam skema yang berbeda. Untuk memperhitungkan 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';

Pemeran ke bigint memformat real angka dengan baik, terutama untuk jumlah besar.

Perkiraan lebih baik

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 Pengidentifikasi Objek.

Ganti 'myschema.mytable'::regclass dengan to_regclass('myschema.mytable') di Postgres 9.4+ untuk tidak mendapatkan apa pun selain pengecualian untuk nama tabel yang tidak valid. Lihat:

  • Cara memeriksa apakah ada tabel dalam skema tertentu

Perkiraan yang lebih baik lagi (dengan biaya tambahan yang sangat kecil)

Kita dapat melakukan apa yang dilakukan perencana Postgres. Mengutip Contoh Estimasi Baris dalam manual:

Angka-angka ini berlaku pada VACUUM terakhir atau ANALYZE di atas meja. Perencana kemudian mengambil jumlah halaman aktual saat ini dalam tabel (ini adalah operasi yang murah, tidak memerlukan pemindaian tabel). Jika itu berbeda dari relpages lalu reltuples diskalakan sesuai dengan perkiraan jumlah baris saat ini.

Postgres menggunakan estimate_rel_size didefinisikan dalam src/backend/utils/adt/plancat.c , yang juga mencakup kasus sudut tidak ada data di pg_class karena hubungan itu tidak pernah vakum. Kita dapat melakukan hal serupa di SQL:

Bentuk minimal

SELECT (reltuples / relpages * (pg_relation_size(oid) / 8192))::bigint
FROM   pg_class
WHERE  oid = 'mytable'::regclass;  -- your table here

Aman dan eksplisit

SELECT (CASE WHEN c.reltuples < 0 THEN NULL       -- never vacuumed
             WHEN c.relpages = 0 THEN float8 '0'  -- empty table
             ELSE c.reltuples / c.relpages END
      * (pg_relation_size(c.oid) / pg_catalog.current_setting('block_size')::int)
       )::bigint
FROM   pg_class c
WHERE  c.oid = 'myschema.mytable'::regclass;      -- schema-qualified table here

Tidak pecah dengan tabel kosong dan tabel yang belum pernah melihat VACUUM atau ANALYZE . Panduan tentang pg_class :

Jika tabel belum pernah divakum atau dianalisis, reltuples berisi -1 menunjukkan bahwa jumlah baris tidak diketahui.

Jika kueri ini mengembalikan NULL , jalankan ANALYZE atau VACUUM untuk meja dan ulangi. (Atau, Anda bisa memperkirakan lebar baris berdasarkan jenis kolom seperti Postgres, tapi itu membosankan dan rawan kesalahan.)

Jika kueri ini mengembalikan 0 , meja tampaknya kosong. Tapi saya akan ANALYZE untuk memastikan. (Dan mungkin periksa autovacuum your Anda pengaturan.)

Biasanya, block_size adalah 8192. current_setting('block_size')::int mencakup pengecualian langka.

Kualifikasi tabel dan skema membuatnya kebal terhadap search_path any dan ruang lingkup.

Either way, kueri secara konsisten membutuhkan <0,1 md untuk saya.

Sumber daya Web lainnya:

  • FAQ Wiki Postgres
  • Halaman wiki Postgres untuk menghitung perkiraan dan menghitung(*) kinerja

TABLESAMPLE SYSTEM (n) di Postgres 9.5+

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

Seperti komentar @a_horse, klausa tambahan untuk SELECT perintah dapat berguna jika statistik di pg_class tidak cukup saat ini untuk beberapa alasan. Misalnya:

  • Tidak ada autovacuum berlari.
  • Segera setelah INSERT besar / UPDATE / DELETE .
  • TEMPORARY tabel (yang tidak dicakup oleh autovacuum ).

Ini hanya terlihat secara acak n % (1 dalam contoh) pemilihan 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 memiliki baris yang lebih lebar dari biasanya, hitungannya lebih rendah dari biasanya, dll.
  • Tuple mati atau FILLFACTOR menempati ruang per blok. Jika terdistribusi tidak merata di seluruh tabel, perkiraannya mungkin salah.
  • Kesalahan pembulatan umum.

Biasanya, perkiraan dari pg_class akan lebih cepat dan 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,

Dan apakah itu ...

... mungkin pada saat hitungan melewati nilai konstan saya, itu akan menghentikan penghitungan (dan tidak menunggu untuk menyelesaikan penghitungan untuk menginformasikan bahwa jumlah baris lebih besar).

Ya. Anda dapat menggunakan subkueri dengan LIMIT :

SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;

Postgres benar-benar berhenti menghitung melampaui batas yang diberikan, Anda mendapatkan tepat dan terkini hitung hingga n baris (500.000 dalam contoh), dan n sebaliknya. Tidak secepat perkiraan di pg_class , meskipun.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Mendekode Log Kesalahan PostgreSQL

  2. Izin ditolak untuk hubungan

  3. Amazon RDS untuk Alternatif PostgreSQL - ClusterControl untuk PostgreSQL

  4. Bagaimana cara menggunakan skema di Django?

  5. Apakah desain yang buruk untuk menggunakan array dalam database?