Hanya ingin tahu apakah ada di antara Anda yang menggunakan Count(1)
lebih dari Count(*)
dan apakah ada perbedaan yang nyata dalam kinerja atau apakah ini hanya kebiasaan lama yang telah dimajukan sejak masa lalu?
Database spesifiknya adalah SQL Server 2005
.
sql
sql-server
performance
super9
sumber
sumber
COUNT(*)
vsCOUNT(1)
vsCOUNT(pk)
- mana yang lebih baik? . Ada jugaCOUNT(*)
vsCOUNT(column-name)
- mana yang lebih benar? . Mungkin ada duplikat lain.Jawaban:
Tidak ada perbedaan.
Alasan:
"1" adalah ekspresi non-null: jadi itu sama dengan
COUNT(*)
. Pengoptimal mengenalinya apa adanya: sepele.Sama dengan
EXISTS (SELECT * ...
atauEXISTS (SELECT 1 ...
Contoh:
IO yang sama, rencana yang sama, bekerja
Edit, Agustus 2011
Pertanyaan serupa pada DBA.SE .
Edit, Des 2011
COUNT(*)
disebutkan secara khusus dalam ANSI-92 (cari "Scalar expressions 125
")Artinya, standar ANSI mengenalinya sebagai pendarahan jelas apa yang Anda maksud.
COUNT(1)
telah dioptimalkan oleh vendor RDBMS karena takhayul ini. Kalau tidak, akan dievaluasi sesuai ANSIsumber
Di SQL Server, pernyataan ini menghasilkan paket yang sama.
Bertentangan dengan pendapat umum, di Oracle mereka juga melakukannya.
SYS_GUID()
di Oracle adalah fungsi intensif komputasi.Dalam database pengujian saya,
t_even
adalah tabel dengan1,000,000
barisKueri ini:
berjalan selama beberapa
48
detik, karena fungsi perlu mengevaluasi masing-masing yangSYS_GUID()
dikembalikan untuk memastikan itu bukanNULL
.Namun, pertanyaan ini:
berjalan selama beberapa
2
detik, karena ia bahkan tidak mencoba untuk mengevaluasiSYS_GUID()
(meskipun*
ada argumen untukCOUNT(*)
)sumber
SYS_GUID()
setidaknya (maksud saya, tepatnya) sekali untuk sub-query untuk mengembalikan hasil, kan?COUNT(*)
bergantung pada nilai-nilaiSYS_GUID
?COUNT(*)
menjalankan, perlu tabel, jadi sub-kueri harus bertindak seperti satu. Kalau tidak, saya tidak melihat cara untukCOUNT(*)
mengembalikan nilai yang berartimap
metode ini, apakah Anda melihat bagaimana kedua ekspresi ini:t_even.map(() => sys_guid()).length
dant_even.length
akan selalu mengembalikan nilai yang sama? Pengoptimal Oracle cukup pintar untuk melihatnya dan mengoptimalkanmap
bagian luar.length
tidak terlalu tergantung pada apa koleksi terdiri, hanya pada jumlah elemennya. Jika nomor ini disimpan dalam metadata koleksi (ini bukan kasus untuk Oracle atau kebanyakan RDBMS modern lainnya tetapi demikian halnya dengan mesin penyimpanan MySQL lama, MyISAM), makaCOUNT(*)
hanya perlu mengambil nilai dari metadata.Jelas,
COUNT(*)
danCOUNT(1)
akan selalu mengembalikan hasil yang sama. Oleh karena itu, jika salah satu lebih lambat dari yang lain itu akan secara efektif disebabkan oleh bug pengoptimal. Karena kedua formulir ini sangat sering digunakan dalam kueri, tidak masuk akal jika DBMS membiarkan bug semacam itu tetap tidak diperbaiki. Karenanya Anda akan menemukan bahwa kinerja kedua bentuk (mungkin) identik di semua DBMS SQL utama.sumber
Saya bekerja di tim SQL Server dan mudah-mudahan saya bisa mengklarifikasi beberapa poin di utas ini (saya belum pernah melihatnya sebelumnya, jadi saya minta maaf tim teknik belum melakukannya sebelumnya).
Pertama, tidak ada perbedaan semantik antara
select count(1) from table
vsselect count(*) from table
. Mereka mengembalikan hasil yang sama dalam semua kasus (dan itu adalah bug jika tidak). Sebagaimana dicatat dalam jawaban lain,select count(column) from table
secara semantik berbeda dan tidak selalu memberikan hasil yang samacount(*)
.Kedua, berkenaan dengan kinerja, ada dua aspek yang penting dalam SQL Server (dan SQL Azure): kerja waktu kompilasi dan kerja waktu eksekusi. Pekerjaan waktu kompilasi adalah pekerjaan ekstra kecil yang sepele dalam implementasi saat ini. Ada ekspansi * ke semua kolom dalam beberapa kasus diikuti oleh pengurangan kembali ke 1 kolom menjadi output karena bagaimana beberapa operasi internal bekerja dalam pengikatan dan optimalisasi. Saya ragu itu akan muncul dalam tes terukur apa pun, dan kemungkinan akan hilang dalam kebisingan semua hal lain yang terjadi di bawah selimut (seperti statistik otomatis, sesi xevent, overhead kueri toko, pemicu, dll.). Mungkin beberapa ribu instruksi CPU tambahan. Begitu, count (1) melakukan sedikit kerja lebih sedikit selama kompilasi (yang biasanya akan terjadi sekali dan rencana di-cache di beberapa eksekusi berikutnya). Untuk waktu pelaksanaan, dengan asumsi rencana adalah sama, seharusnya tidak ada perbedaan yang terukur. (Salah satu contoh sebelumnya menunjukkan perbedaan - kemungkinan besar karena faktor lain pada mesin jika rencananya sama).
Mengenai bagaimana rencana tersebut berpotensi berbeda. Ini sangat tidak mungkin terjadi, tetapi sangat mungkin dalam arsitektur optimizer saat ini. Pengoptimal SQL Server berfungsi sebagai program pencarian (pikirkan: program komputer bermain catur mencari melalui berbagai alternatif untuk berbagai bagian permintaan dan menghitung alternatif untuk menemukan paket termurah dalam waktu yang wajar). Pencarian ini memiliki beberapa batasan tentang bagaimana ia beroperasi untuk menjaga penyelesaian kompilasi permintaan dalam waktu yang wajar. Untuk kueri di luar yang paling sepele, ada fase pencarian dan mereka berurusan dengan tahapan permintaan berdasarkan seberapa mahal pengoptimal berpikir kueri berpotensi dieksekusi. Ada 3 fase pencarian utama, dan setiap fase dapat menjalankan heuristik yang lebih agresif (mahal) mencoba menemukan rencana yang lebih murah daripada solusi sebelumnya. Pada akhirnya, ada proses pengambilan keputusan di akhir setiap fase yang mencoba menentukan apakah harus mengembalikan rencana yang ditemukan sejauh ini atau harus terus mencari. Proses ini menggunakan total waktu yang diambil sejauh ini vs perkiraan biaya rencana terbaik yang ditemukan sejauh ini. Jadi, pada mesin yang berbeda dengan kecepatan CPU yang berbeda adalah mungkin (walaupun jarang) untuk mendapatkan paket yang berbeda karena penghentian waktu pada fase sebelumnya dengan rencana vs melanjutkan ke fase pencarian berikutnya. Ada juga beberapa skenario serupa yang terkait dengan waktu keluar dari fase terakhir dan berpotensi kehabisan memori pada permintaan yang sangat, sangat mahal yang mengkonsumsi semua memori pada mesin (biasanya tidak masalah pada 64-bit tetapi itu adalah masalah yang lebih besar kembali pada server 32-bit). Pada akhirnya, jika Anda mendapatkan paket yang berbeda, kinerja saat runtime akan berbeda. Saya tidak
Net-net: Silakan gunakan yang mana dari dua yang Anda inginkan karena tidak ada yang penting dalam bentuk praktis. (Ada jauh, faktor-faktor yang jauh lebih besar yang mempengaruhi kinerja dalam SQL di luar topik ini, jujur).
Saya harap ini membantu. Saya memang menulis bab buku tentang cara kerja pengoptimal tapi saya tidak tahu apakah pantas untuk mempostingnya di sini (karena saya mendapatkan sedikit royalti dari itu masih saya percaya). Jadi, alih-alih memposting, saya akan memposting tautan ke ceramah yang saya berikan di SQLBits di Inggris tentang bagaimana pengoptimal bekerja pada level tinggi sehingga Anda dapat melihat berbagai fase utama pencarian dengan sedikit lebih detail jika Anda mau untuk belajar tentang itu. Inilah tautan videonya: https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer
sumber
1
juga mengalami ekspansi yang sama. Saya mendasarkan ini pada tes perf di sini stackoverflow.com/questions/1597442/... juga melihat contoh dalam jawaban permintaan menggunakan1
gagal secara tak terduga ketika izin tingkat kolom sedang dimainkanDalam Standar SQL-92,
COUNT(*)
secara khusus berarti "kardinalitas ekspresi tabel" (bisa berupa tabel dasar, `LIHAT, tabel turunan, CTE, dll).Saya kira idenya
COUNT(*)
mudah diurai. Menggunakan ekspresi lain membutuhkan parser untuk memastikannya tidak mereferensikan kolom apa pun (diCOUNT('a')
manaa
literal dan diCOUNT(a)
manaa
kolom dapat menghasilkan hasil yang berbeda).Dalam nada yang sama,
COUNT(*)
dapat dengan mudah dipilih oleh seorang pengkode manusia yang akrab dengan Standar SQL, keterampilan yang berguna ketika bekerja dengan lebih dari satu penawaran SQL vendor.Juga, dalam kasus khusus
SELECT COUNT(*) FROM MyPersistedTable;
, pemikirannya adalah DBMS cenderung memiliki statistik kardinalitas tabel.Karena itu, karena
COUNT(1)
danCOUNT(*)
secara semantik setara, saya gunakanCOUNT(*)
.sumber
COUNT(*)
danCOUNT(1)
sama dalam hal hasil dan kinerja.sumber
Saya berharap pengoptimal memastikan tidak ada perbedaan nyata di luar kasus tepi aneh.
Seperti apa pun, satu-satunya cara nyata untuk mengetahui adalah dengan mengukur kasus spesifik Anda.
Yang mengatakan, saya selalu digunakan
COUNT(*)
.sumber
Ketika pertanyaan ini muncul berulang-ulang, inilah satu jawaban lagi. Saya berharap dapat menambahkan sesuatu untuk pemula yang bertanya-tanya tentang "praktik terbaik" di sini.
SELECT COUNT(*) FROM something
menghitung catatan yang merupakan tugas yang mudah.SELECT COUNT(1) FROM something
mengambil 1 per catatan dan menghitung 1 yang bukan nol, yang pada dasarnya menghitung catatan, hanya lebih rumit.Setelah mengatakan ini: Pemberitahuan dbms yang baik bahwa pernyataan kedua akan menghasilkan jumlah yang sama dengan pernyataan pertama dan menerjemahkan ulang sesuai dengan itu, karena tidak melakukan pekerjaan yang tidak perlu. Jadi biasanya kedua pernyataan akan menghasilkan rencana eksekusi yang sama dan mengambil jumlah waktu yang sama.
Namun dari sudut keterbacaan Anda harus menggunakan pernyataan pertama. Anda ingin menghitung catatan, jadi hitung catatan, bukan ekspresi. Gunakan COUNT (ekspresi) hanya ketika Anda ingin menghitung kejadian sesuatu yang bukan nol.
sumber
Saya menjalankan tes cepat pada SQL Server 2012 pada kotak hyper-v RAM 8 GB. Anda dapat melihat hasilnya sendiri. Saya tidak menjalankan aplikasi berjendela lain selain dari SQL Server Management Studio saat menjalankan tes ini.
Skema tabel saya:
Total jumlah catatan dalam
Employee
tabel: 178090131 (~ 178 juta baris)Pertanyaan Pertama:
Hasil Kueri Pertama:
Pertanyaan Kedua:
Hasil Kueri Kedua:
Anda dapat melihat ada perbedaan 83 (= 70265 - 70182) milidetik yang dapat dengan mudah dikaitkan dengan kondisi sistem yang tepat pada saat kueri dijalankan. Saya juga menjalankan satu kali, jadi perbedaan ini akan menjadi lebih akurat jika saya melakukan beberapa kali dan rata-rata. Jika untuk kumpulan data yang begitu besar perbedaannya datang kurang dari 100 milidetik, maka kita dapat dengan mudah menyimpulkan bahwa dua kueri tidak memiliki perbedaan kinerja yang ditunjukkan oleh SQL Server Engine.
Catatan : RAM mencapai penggunaan hampir 100% di kedua proses. Saya memulai kembali layanan SQL Server sebelum memulai kedua proses.
sumber
Saya telah menjalankan ini ratusan kali, membersihkan cache setiap waktu .. Hasilnya bervariasi dari waktu ke waktu karena beban server bervariasi, tetapi hampir selalu
count(*)
memiliki waktu cpu yang lebih tinggi.sumber
count(*)
dancount(1)
hasil kembali dalam beberapa ms satu sama lain, bahkan ketika menghitung tabel dengan 4,5 juta baris, dalam contoh SQL 2008 saya.Ada sebuah artikel yang menunjukkan bahwa
COUNT(1)
pada Oracle adalah hanya sebuah alias untukCOUNT(*)
, dengan bukti tentang itu.Saya akan mengutip beberapa bagian:
Dengan pengguna dengan
ALTER SESSION
hak istimewa, Anda dapat menempatkan sebuahtracefile_identifier
, memungkinkan tracing optimizer dan menjalankanCOUNT(1)
pilih, seperti:SELECT /* test-1 */ COUNT(1) FROM employees;
.Setelah itu, Anda perlu melokalkan file jejak, apa yang bisa dilakukan
SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Diag Trace';
. Kemudian pada file, Anda akan menemukan:Seperti yang Anda lihat, itu hanya alias untuk
COUNT(*)
.Komentar penting lainnya: Oracle
COUNT(*)
benar-benar lebih cepat dua dekade yang lalu , sebelum Oracle 7.3:Untuk database lain sebagai Sql Server, itu harus diteliti secara individual untuk masing-masing.
Saya tahu bahwa pertanyaan ini khusus untuk Sql Server, tetapi pertanyaan lain pada SO tentang subjek yang sama, tanpa menyebutkan database, ditutup dan ditandai sebagai duplikat dari jawaban ini.
sumber
Dalam semua RDBMS, dua cara penghitungan adalah setara dalam hal hasil apa yang mereka hasilkan. Mengenai kinerja, saya belum mengamati perbedaan kinerja dalam SQL Server, tetapi mungkin perlu menunjukkan bahwa beberapa RDBMS, misalnya PostgreSQL 11, memiliki implementasi yang kurang optimal karena
COUNT(1)
mereka memeriksa nullability ekspresi argumen seperti yang dapat dilihat pada posting ini .Saya telah menemukan perbedaan kinerja 10% untuk baris 1M saat menjalankan:
sumber
COUNT (1) tidak jauh berbeda dari COUNT (*), jika sama sekali. Mengenai pertanyaan MENGHITUNG KOLOM NULLable, ini bisa langsung untuk mendemonstrasikan perbedaan antara COUNT (*) dan COUNT (<beberapa col>) -
sumber