Saya perlu mengetahui jumlah baris dalam tabel untuk menghitung persentase. Jika jumlah total lebih besar dari beberapa konstanta yang telah ditentukan sebelumnya, saya akan menggunakan nilai konstanta. Jika tidak, saya akan menggunakan jumlah baris yang sebenarnya.
Saya bisa menggunakan SELECT count(*) FROM table
. Tetapi jika nilai konstanta saya adalah 500.000 dan saya memiliki 5.000.000.000 baris di tabel saya, menghitung semua baris akan membuang banyak waktu.
Apakah mungkin untuk berhenti menghitung segera setelah nilai konstanta saya terlampaui?
Saya membutuhkan jumlah baris yang tepat hanya selama itu di bawah batas yang diberikan. Sebaliknya, jika hitungannya di atas batas, saya menggunakan nilai batas sebagai gantinya dan menginginkan jawaban secepat mungkin.
Sesuatu seperti ini:
SELECT text,count(*), percentual_calculus()
FROM token
GROUP BY text
ORDER BY count DESC;
sumber
Jawaban:
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):
Anda mendapatkan perkiraan yang mendekati seperti ini ( sangat cepat ):
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
adalahadalah sedikit ceroboh . Ini mengabaikan kemungkinan bahwa ada beberapa tabel dengan nama yang sama dalam satu database - dalam skema yang berbeda. Untuk menjelaskan itu:Atau lebih baik lagi
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:TABLESAMPLE SYSTEM (n)
di Postgres 9.5+Seperti komentar @a_horse , klausa yang baru ditambahkan untuk
SELECT
perintah tersebut mungkin berguna jika statistik dalampg_class
tidak cukup terkini karena alasan tertentu. Sebagai contoh:autovacuum
lari.INSERT
atauDELETE
.TEMPORARY
tabel (yang tidak tercakup olehautovacuum
).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:FILLFACTOR
menempati ruang per blok. Jika didistribusikan secara tidak merata di seluruh tabel, perkiraan mungkin salah.Dalam kebanyakan kasus, perkiraan dari
pg_class
akan lebih cepat dan lebih akurat.Jawaban untuk pertanyaan sebenarnya
Dan apakah itu ...
Iya. Anda dapat menggunakan subkueri dengan
LIMIT
: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
.sumber
tablesample
klausa: misalnyaselect count(*) * 100 as cnt from mytable tablesample system (1);
SELECT count(*) FROM (Select * from (SELECT 1 FROM token) query) LIMIT 500000) limited_query;
(Saya bertanya karena saya mencoba mendapatkan hitungan dari kueri sewenang-wenang yang mungkin sudah memiliki klausa batas di dalamnya)ORDER BY something
saat tidak dapat menggunakan indeks, atau dengan fungsi agregat). Selain itu, hanya sejumlah baris dari subquery yang diproses.Saya melakukan ini sekali di aplikasi postgres dengan menjalankan:
Kemudian memeriksa output dengan regex, atau logika serupa. Untuk SELECT * sederhana, baris pertama keluaran akan terlihat seperti ini:
Anda dapat menggunakan
rows=(\d+)
nilai sebagai perkiraan kasar dari jumlah baris yang akan dikembalikan, kemudian hanya melakukan yang sebenarnyaSELECT COUNT(*)
jika perkiraan tersebut, katakanlah, kurang dari 1,5x ambang Anda (atau angka berapa pun yang Anda anggap masuk akal untuk aplikasi Anda).Bergantung pada kompleksitas kueri Anda, angka ini mungkin menjadi semakin kurang akurat. Faktanya, dalam aplikasi saya, saat kami menambahkan gabungan dan kondisi kompleks, itu menjadi sangat tidak akurat sehingga benar-benar tidak berharga, bahkan untuk mengetahui berapa banyak baris yang akan kami kembalikan dalam kekuatan 100, jadi kami harus meninggalkan strategi itu.
Tetapi jika kueri Anda cukup sederhana sehingga Pg dapat memprediksi dalam batas kesalahan yang wajar berapa banyak baris yang akan dikembalikan, ini mungkin berhasil untuk Anda.
sumber
Referensi diambil dari Blog ini.
Anda dapat menggunakan di bawah ini untuk membuat kueri untuk menemukan jumlah baris.
Menggunakan pg_class:
Menggunakan pg_stat_user_tables:
sumber
Di Oracle, Anda dapat menggunakan
rownum
untuk membatasi jumlah baris yang dikembalikan. Saya menebak konstruksi serupa ada di SQL lain juga. Jadi, untuk contoh yang Anda berikan, Anda dapat membatasi jumlah baris yang dikembalikan menjadi 500001 dan menerapkancount(*)
kemudian:sumber
count(*)
dengan rownum, 1 dtk tanpa menggunakan rownum). Ya,SELECT count(*) cnt FROM table
selalu akan mengembalikan 1 baris, tetapi dengan kondisi LIMIT, itu akan mengembalikan "500001" ketika ukuran tabel lebih dari 500000 dan <size> ketika ukuran tabel <= 500000.Seberapa lebar kolom teks?
Dengan GROUP BY, tidak banyak yang dapat Anda lakukan untuk menghindari pemindaian data (setidaknya pemindaian indeks).
Saya akan merekomendasikan:
Jika memungkinkan, ubah skema untuk menghapus duplikasi data teks. Dengan cara ini penghitungan akan terjadi pada bidang kunci asing yang sempit di tabel 'banyak'.
Alternatifnya, membuat kolom yang dihasilkan dengan HASH teks, lalu GROUP BY kolom hash. Sekali lagi, ini untuk mengurangi beban kerja (memindai melalui indeks kolom sempit)
Edit:
Pertanyaan asli Anda tidak cocok dengan hasil edit Anda. Saya tidak yakin apakah Anda mengetahui bahwa JUMLAH, ketika digunakan dengan GROUP BY, akan mengembalikan jumlah item per grup dan bukan jumlah item di seluruh tabel.
sumber
Anda bisa mendapatkan hitungan dengan kueri di bawah ini (tanpa * atau nama kolom apa pun).
sumber
count(*)
.Untuk SQL Server (2005 atau lebih tinggi), metode cepat dan andal adalah:
Detail tentang sys.dm_db_partition_stats dijelaskan di MSDN
Kueri menambahkan baris dari semua bagian tabel (mungkin) yang dipartisi.
index_id = 0 adalah tabel tidak berurutan (Heap) dan index_id = 1 adalah tabel terurut (clustered index)
Metode yang bahkan lebih cepat (tetapi tidak dapat diandalkan) dijelaskan di sini.
sumber