Saya telah menemukan artikel yang menyatakan bahwa SELECT COUNT(*) FROM TABLE_NAME
akan lambat ketika tabel memiliki banyak baris dan banyak kolom.
Saya memiliki tabel yang mungkin berisi miliaran baris [memiliki sekitar 15 kolom]. Apakah ada cara yang lebih baik untuk mendapatkan hitungan EXACT dari jumlah baris tabel?
Harap pertimbangkan yang berikut sebelum jawaban Anda:
Saya mencari solusi independen vendor database. Tidak apa-apa jika mencakup MySQL , Oracle , MS SQL Server . Tetapi jika benar - benar tidak ada solusi vendor database independen maka saya akan puas dengan solusi yang berbeda untuk vendor database yang berbeda.
Saya tidak bisa menggunakan alat eksternal lain untuk melakukan ini. Saya terutama mencari solusi berbasis SQL.
Saya tidak bisa menormalkan desain database saya lebih jauh. Itu sudah dalam 3NF dan terlebih lagi banyak kode telah ditulis di sekitarnya.
Jawaban:
Jawaban sederhana:
COUNT(*)
Catatan:
COUNT (1) = COUNT (*) = COUNT (PrimaryKey) untuk berjaga-jaga
Edit:
Contoh SQL Server (1,4 miliar baris, 12 kolom)
1 lari, 5:46 menit, hitung = 1.401.659.700
2 run, keduanya di bawah 1 detik, hitung = 1.401.659.670
Yang kedua memiliki lebih sedikit baris = salah. Akan sama atau lebih tergantung pada penulisan (penghapusan dilakukan di luar jam di sini)
sumber
COUNT(*) = COUNT(key)
. Ini salah. Jika tidak adaNOT NULL
kendala - maka mereka tidak bisa sama (dalam hasil maupun dalam rencana eksekusi).index_id < 2
?Cara tercepat sejauh ini di MySQL adalah:
Anda akan langsung mendapatkan semua tabel Anda dengan jumlah baris (yang merupakan total) bersama dengan banyak informasi tambahan jika Anda mau.
sumber
Itu tergantung pada database. Beberapa mempercepat menghitung, misalnya dengan melacak apakah baris hidup atau mati dalam indeks, memungkinkan untuk hanya memindai indeks untuk mengekstrak jumlah baris. Yang lain tidak, dan akibatnya perlu mengunjungi seluruh meja dan menghitung baris langsung satu per satu. Entah akan lambat untuk meja besar.
Perhatikan bahwa Anda biasanya dapat mengekstraksi estimasi yang baik dengan menggunakan alat optimisasi kueri, statistik tabel, dll. Dalam kasus PostgreSQL, misalnya, Anda dapat mengurai output
explain count(*) from yourtable
dan mendapatkan estimasi jumlah baris yang cukup baik. Yang membawa saya ke pertanyaan kedua Anda.Serius? :-) Maksud Anda hitungan yang tepat dari tabel dengan miliaran baris? Apakah kamu benar-benar yakin? :-)
Jika Anda benar - benar melakukannya, Anda bisa menyimpan jejak total penggunaan trigger, tetapi perhatikan konkurensi dan deadlock jika Anda melakukannya.
sumber
Untuk menjawab pertanyaan Anda secara sederhana, Tidak .
Jika Anda memerlukan cara independen DBMS untuk melakukan ini, cara tercepat akan selalu:
Beberapa vendor DBMS mungkin memiliki cara yang lebih cepat yang hanya akan berfungsi untuk sistem mereka. Beberapa opsi ini sudah diposting dalam jawaban lain.
COUNT(*)
harus dioptimalkan oleh DBMS (setidaknya DB layak PROD), jadi jangan mencoba untuk memotong optimasi mereka.Di samping catatan:
Saya yakin banyak pertanyaan Anda yang lain juga membutuhkan waktu lama untuk diselesaikan karena ukuran meja Anda. Setiap masalah kinerja mungkin harus diatasi dengan memikirkan desain skema Anda dengan cepat. Saya menyadari Anda mengatakan bahwa itu bukan opsi untuk berubah, tetapi mungkin ternyata bahwa kueri 10+ menit juga bukan opsi. 3 NF tidak selalu pendekatan yang terbaik ketika Anda membutuhkan kecepatan, dan kadang-kadang data dapat dipartisi dalam beberapa tabel jika catatan tidak memiliki disimpan bersama-sama. Sesuatu untuk dipikirkan...
sumber
Saya mendapatkan skrip ini dari pertanyaan / jawaban StackOverflow lain:
Meja saya memiliki 500 juta catatan dan pengembalian di atas dalam waktu kurang dari 1 ms. Sementara itu,
membutuhkan 39 menit penuh, 52 detik!
Mereka menghasilkan jumlah baris yang sama persis (dalam kasus saya, tepatnya 519326012).
Saya tidak tahu apakah itu akan selalu terjadi.
sumber
Anda dapat mencoba sp_spaceused ini (Transact-SQL)
sumber
Jika edisi SQL Server 2005/2008, Anda bisa menggunakan DMV untuk menghitung jumlah baris dalam tabel:
Untuk mesin database SQL Server 2000, sysindex akan berfungsi, tetapi sangat disarankan untuk tidak menggunakannya dalam edisi SQL Server mendatang karena dapat dihapus dalam waktu dekat.
Contoh kode diambil dari: Cara Mendapatkan Hitungan Baris Tabel Dengan Cepat Dan Tanpa Rasa Sakit
sumber
saya menggunakan
sumber
Saya sama sekali tidak ahli seperti orang lain yang telah menjawab tetapi saya memiliki masalah dengan prosedur yang saya gunakan untuk memilih baris acak dari tabel (tidak terlalu relevan) tetapi saya perlu mengetahui jumlah baris dalam tabel referensi saya untuk menghitung indeks acak. Menggunakan Hitungan tradisional (*) atau Hitungan (1) berfungsi tetapi saya kadang-kadang mendapatkan hingga 2 detik untuk menjalankan kueri. Jadi sebagai gantinya (untuk meja saya bernama 'tbl_HighOrder') saya menggunakan:
Ini berfungsi dengan baik dan waktu kueri di Management Studio adalah nol.
sumber
Nah, terlambat 5 tahun dan tidak yakin apakah itu membantu:
Saya mencoba menghitung tidak. baris dalam tabel SQL Server menggunakan MS SQL Server Management Studio dan mengalami beberapa kesalahan overflow, maka saya menggunakan di bawah ini:
pilih count_big (1) DARI [dbname]. [dbo]. [FactSampleValue];
Hasil :
24296650578 baris
sumber
Saya menemukan baik artikel ini SQL Server-CARA-TO: cepat mengambil jumlah baris akurat untuk meja dari
martijnh1
yang memberikan rekap yang baik untuk setiap skenario.Saya perlu ini diperluas di mana saya perlu memberikan hitungan berdasarkan kondisi tertentu dan ketika saya mencari bagian ini, saya akan memperbarui jawaban ini lebih lanjut.
Sementara itu, berikut detail dari artikel:
Metode 1:
Pertanyaan:
Komentar:
Melakukan pemindaian tabel penuh. Lambat di meja besar.
Metode 2:
Pertanyaan:
Komentar:
Cara cepat untuk mengambil jumlah baris. Tergantung pada statistik dan tidak akurat.
Jalankan DBCC UPDATEUSAGE (Database) DENGAN COUNT_ROWS, yang bisa memakan waktu cukup lama untuk tabel besar.
Metode 3:
Pertanyaan:
Komentar:
Cara studio manajemen SQL menghitung baris (lihat properti tabel, penyimpanan, jumlah baris). Sangat cepat, tetapi masih merupakan perkiraan jumlah baris.
Metode 4:
Pertanyaan:
Komentar:
Operasi cepat (walaupun tidak secepat metode 2) dan sama pentingnya, andal.
sumber
Saya tidak berpikir ada solusi umum yang selalu tercepat: beberapa RDBMS / versi memiliki optimasi khusus untuk
SELECT COUNT(*)
itu menggunakan opsi lebih cepat sementara yang lain hanya pemindaian tabel. Anda harus pergi ke situs dokumentasi / dukungan untuk set kedua, yang mungkin akan membutuhkan beberapa permintaan khusus untuk ditulis, biasanya yang menyentuh indeks dengan beberapa cara.EDIT:
Berikut ini pemikiran yang mungkin berhasil, tergantung pada skema dan distribusi data Anda: apakah Anda memiliki kolom yang diindeks yang mereferensikan nilai yang meningkat, ID peningkatan numerik, katakanlah, atau bahkan cap waktu atau tanggal? Kemudian, dengan anggapan penghapusan tidak terjadi, seharusnya dimungkinkan untuk menyimpan penghitungan hingga beberapa nilai terkini (tanggal kemarin, nilai ID tertinggi di beberapa titik sampel terbaru) dan menambahkan penghitungan di luar itu, yang seharusnya diselesaikan dengan sangat cepat dalam indeks . Sangat tergantung pada nilai dan indeks, tentu saja, tetapi berlaku untuk hampir semua versi DBMS apa pun.
sumber
SELECT COUNT(*)
. Bahkan MySQL ternyata melakukannya ....Saya terlambat untuk pertanyaan ini, tetapi di sini adalah apa yang dapat Anda lakukan dengan MySQL (karena saya menggunakan MySQL). Saya membagikan pengamatan saya di sini:
Hasil
Baris Hitung: 508534
Output konsol: Baris yang terpengaruh: 0 Baris yang ditemukan: 1 Peringatan: 0 Durasi untuk 1 permintaan: 0,125 dtk.
Butuh beberapa saat untuk tabel dengan jumlah baris yang besar, tetapi jumlah baris sangat tepat.
Hasil
Jumlah baris: 511235
Output konsol: Baris yang terpengaruh: 0 Baris yang ditemukan: 1 Peringatan: 0 Durasi untuk 1 permintaan: 0,250 dt Ringkasan: Jumlah baris tidak tepat.
Hasil
Jumlah baris: 507806
Output konsol: Baris yang terpengaruh: 0 Baris yang ditemukan: 48 Peringatan: 0 Durasi untuk 1 permintaan: 1,701 dtk.
Hitungan baris tidak tepat.
Saya bukan ahli MySQL atau basis data, tetapi saya telah menemukan bahwa untuk tabel yang sangat besar, Anda dapat menggunakan opsi 2 atau 3 dan mendapatkan 'ide yang adil' tentang berapa banyak baris yang ada.
Saya perlu mendapatkan jumlah baris ini untuk menampilkan beberapa statistik di UI. Dengan pertanyaan di atas, saya tahu bahwa total baris lebih dari 500.000, jadi saya menghasilkan statistik seperti "Lebih dari 500.000 baris" tanpa menunjukkan jumlah baris yang tepat.
Mungkin saya belum benar-benar menjawab pertanyaan OP, tetapi saya membagikan apa yang saya lakukan dalam situasi di mana statistik seperti itu diperlukan. Dalam kasus saya, menampilkan baris perkiraan dapat diterima dan hal di atas berfungsi untuk saya.
sumber
Bukan solusi DBMS-agnostik, tetapi setidaknya kode klien Anda tidak akan melihat perbedaannya ...
Buat tabel T lain dengan hanya satu baris dan satu bidang bilangan bulat N 1 , dan buat INSERT TRIGGER yang baru saja dijalankan:
Juga buat DELETE TRIGGER yang mengeksekusi:
DBMS yang bernilai garam akan menjamin atomicity operasi di atas 2 , dan N akan berisi jumlah baris yang akurat setiap saat, yang kemudian super cepat didapat hanya dengan:
Meskipun pemicu adalah spesifik DBMS, memilih dari T tidak dan kode klien Anda tidak perlu berubah untuk setiap DBMS yang didukung.
Namun, ini dapat memiliki beberapa masalah skalabilitas jika tabel INSERT atau DELETE-intensif, terutama jika Anda tidak KOMIT segera setelah INSERT / HAPUS.
1 Nama-nama ini hanya placeholder - gunakan sesuatu yang lebih bermakna dalam produksi.
2 Yaitu N tidak dapat diubah dengan transaksi bersamaan antara membaca dan menulis ke N, selama membaca dan menulis dilakukan dalam pernyataan SQL tunggal.
sumber
Jawaban yang benar-benar gila, tetapi jika Anda memiliki semacam pengaturan sistem replikasi (untuk sistem dengan satu miliar baris, saya harap Anda melakukannya), Anda dapat menggunakan estimator kasar (seperti
MAX(pk)
), bagi nilai itu dengan jumlah budak Anda punya, jalankan beberapa kueri secara paralel.Untuk sebagian besar, Anda akan mempartisi kueri di seluruh budak berdasarkan kunci terbaik (atau kunci utama saya kira), sedemikian rupa (kita akan menggunakan 250000000 sebagai Baris / Budak kami):
Tetapi Anda hanya perlu SQL. Benar-benar payah. Ok, jadi anggaplah Anda seorang sadomasochist. Pada master (atau slave terdekat) Anda kemungkinan besar perlu membuat tabel untuk ini:
Jadi, alih-alih hanya menjalankan seleksi di slave Anda, Anda harus melakukan insert, seperti ini:
Anda mungkin mengalami masalah dengan budak yang menulis ke meja di master. Anda mungkin perlu mendapatkan lebih banyak sadis- Maksudku, kreatif:
Anda pada akhirnya harus memiliki budak yang ada di jalur terakhir yang dilalui oleh grafik replikasi, relatif terhadap budak pertama. Budak itu sekarang harus memiliki semua nilai counter lainnya, dan harus memiliki nilai sendiri. Tetapi pada saat Anda selesai, mungkin ada baris yang ditambahkan, jadi Anda harus memasukkan satu lagi untuk mengkompensasi pk max yang tercatat di counter_table Anda dan pk maks saat ini.
Pada titik itu, Anda harus melakukan fungsi agregat untuk mencari tahu apa total barisnya, tetapi itu lebih mudah karena Anda akan menjalankannya paling banyak pada "jumlah budak yang Anda miliki dan ubah" baris.
Jika Anda berada dalam situasi di mana Anda memiliki tabel terpisah di slave, Anda bisa
UNION
mendapatkan semua baris yang Anda butuhkan.Atau Anda tahu, menjadi sedikit lebih tidak waras dan memigrasikan data Anda ke sistem pemrosesan terdistribusi, atau mungkin menggunakan solusi Data Warehousing (yang akan memberi Anda data yang luar biasa juga di masa depan).
Perhatikan, ini tergantung pada seberapa baik replikasi Anda diatur. Karena bottleneck utama kemungkinan besar adalah penyimpanan yang persisten, jika Anda memiliki penyimpanan yang kasar atau penyimpanan data yang terpisah dengan kebisingan tetangga yang tinggi, ini mungkin akan membuat Anda lebih lambat daripada hanya menunggu satu pun.
SELECT COUNT(*) ...
Tetapi jika Anda memiliki replikasi yang baik, maka peningkatan kecepatan Anda harus langsung terkait dengan jumlah atau budak. Faktanya, jika hanya perlu 10 menit untuk menjalankan kueri penghitungan, dan Anda memiliki 8 budak, Anda akan memotong waktu Anda menjadi kurang dari beberapa menit. Mungkin satu jam untuk menyelesaikan detail dari solusi ini.
Tentu saja, Anda tidak akan pernah benar-benar mendapatkan jawaban yang luar biasa akurat karena penyelesaian terdistribusi ini memperkenalkan sedikit waktu di mana baris dapat dihapus dan dimasukkan, tetapi Anda dapat mencoba untuk mendapatkan kunci terdistribusi dari baris pada contoh yang sama dan mendapatkan penghitungan yang tepat dari baris dalam tabel untuk saat tertentu dalam waktu.
Sebenarnya, ini sepertinya tidak mungkin, karena pada dasarnya Anda terjebak dengan solusi SQL-only, dan saya tidak berpikir Anda menyediakan mekanisme untuk menjalankan kueri yang beling dan terkunci di banyak budak, secara instan. Mungkin jika Anda memiliki kendali atas file log replikasi ... yang berarti Anda benar-benar akan memutar budak untuk tujuan ini, yang tidak diragukan lagi lebih lambat daripada hanya menjalankan kueri hitungan pada satu mesin saja.
Jadi ada dua sen 2013 saya.
sumber
Jika pemicu sisipan terlalu mahal untuk digunakan, tetapi pemicu penghapusan bisa dilakukan, dan ada peningkatan otomatis
id
, kemudian setelah menghitung seluruh tabel satu kali, dan mengingat hitungan sebagailast-count
danlast-counted-id
,maka setiap hari hanya perlu menghitung untuk
id
>last-counted-id
, menambahkannya kelast-count
, dan menyimpan yang barulast-counted-id
.Pemicu hapus akan mengurangi jumlah-terakhir, jika id dari catatan yang dihapus <= id-terakhir-dihitung.
sumber
Jika Anda memiliki struktur tabel tipikal dengan kolom kunci primer yang bertambah secara otomatis di mana baris tidak pernah dihapus, berikut ini akan menjadi cara tercepat untuk menentukan jumlah rekaman dan harus bekerja dengan cara yang sama di sebagian besar basis data yang sesuai dengan ANSI:
Saya bekerja dengan tabel MS SQL yang berisi miliaran baris yang memerlukan waktu respons sub-detik untuk data, termasuk jumlah rekaman. SELECT COUNT (*) yang serupa akan membutuhkan waktu beberapa menit untuk diproses dengan perbandingan.
sumber
INSERT
transaksi dibatalkan? Nilai kunci primer itu akan tidak ada, sehingga jumlah rekaman aktual akan menjadi kurang dari nilai maksimum.count(*)
, jika vendor database belum cukup dioptimalkancount(*)
: Setiap hari melacak indeks-otomatis terakhir dan jumlah yang sesuai, kemudian meminta hitungan catatan melewati itu. Dapat juga menanganidelete
jika menambahkan pemicu pada delete yang menurunkan total sebelumnya , jika record id dihapus <= indeks otomatis terakhir.Untuk server Sql coba ini
sumber
pilih baris dari sysindexes di mana id = Object_ID ('TableName') dan indid <2
sumber
Letakkan indeks pada beberapa kolom. Itu harus memungkinkan pengoptimal untuk melakukan pemindaian penuh blok indeks, bukan pemindaian penuh tabel. Itu akan mengurangi biaya IO Anda. Lihatlah rencana eksekusi sebelum dan sesudah. Kemudian mengukur waktu jam dinding dua arah.
sumber
Jika Anda menggunakan Oracle, bagaimana dengan ini (dengan asumsi statistik tabel diperbarui):
last_analyzed akan menunjukkan waktu ketika statistik terakhir dikumpulkan.
sumber
Dengan PostgreSQL:
sumber
Di SQL server 2016, saya hanya bisa memeriksa properti tabel dan kemudian pilih tab 'Storage' - ini memberi saya jumlah baris, ruang disk yang digunakan oleh tabel, ruang indeks yang digunakan dll.
sumber
database vendor independent solution
. Juga ini membutuhkan GUI dan tidak bisa otomatis. Juga tidak lebih cepat dari COUNT (*)Mungkin agak terlambat tetapi ini mungkin membantu orang lain untuk MSSQL
sumber