Adakah count(*) dalam MySQL benar-benar lebih pantas daripada count(1)? Artikel berikut akan membandingkan count(*) dan count(1) dalam MySQL untuk melihat perbezaan prestasi mereka. Saya harap ia akan membantu anda!
Seseorang memberitahu saya hari ini bahawa count(1)
lebih pantas daripada count(*)
dalam MySQL Bolehkah saya bertolak ansur dengan ini? Awak kena rehat dengan dia.
Penafian: Perbincangan berikut adalah berdasarkan enjin storan InnoDB Saya akan bercakap tentang MyISAM secara berasingan pada penghujung artikel kerana situasi istimewa. [Cadangan berkaitan: tutorial video mysql]
Izinkan saya bercakap tentang kesimpulan dahulu: Tiada banyak perbezaan dalam prestasi antara kedua-duanya.
Saya menyediakan jadual dengan 1 juta keping data Struktur jadual adalah seperti berikut:
CREATE TABLE `user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Seperti yang anda lihat, terdapat indeks kunci utama.
Mari kita kira bilangan rekod dalam jadual dalam dua cara, seperti berikut:
Seperti yang anda lihat, kecekapan pelaksanaan kedua-dua SQL ialah sebenarnya hampir sama. Kedua-duanya adalah 0.14s.
Mari kita lihat dua lagi statistik:
id ialah kunci utama, nama pengguna dan alamat adalah medan biasa.
Dapat dilihat bahawa menggunakan id untuk statistik mempunyai beberapa kelebihan. Saudara Song, kerana sampel data ujian agak kecil, kesannya tidak jelas Kawan boleh meningkatkan jumlah data ujian, maka perbezaannya akan lebih jelas.
Jadi apakah sebab perbezaan ini? Mari kita analisa secara ringkas seterusnya.
Mari kita gunakan explain untuk melihat pelan pelaksanaan SQL yang berbeza ini:
Anda boleh lihat, pelaksanaannya rancangan tiga kaedah statistik pertama adalah sama, dan dua yang terakhir adalah sama.
Izinkan saya membandingkan item yang berbeza dalam terangkan dengan anda:
Melalui penjelasan, kita sebenarnya boleh melihat secara kasar bahawa kecekapan pelaksanaan tiga kaedah statistik pertama adalah lebih tinggi (kerana penggunaan indeks), manakala kecekapan statistik dua yang terakhir adalah agak rendah. Ia dikatakan lebih rendah (tiada indeks digunakan, imbasan jadual penuh diperlukan).
Analisis di atas sahaja tidak mencukupi, mari kita analisa dari perspektif prinsip.
3.1 Indeks kunci utama dan indeks biasa
Sebelum memulakan analisis prinsip, saya ingin untuk memimpin Mari kita lihat B-tree, yang memainkan peranan penting dalam memahami kandungan seterusnya.
Semua orang tahu bahawa struktur penyimpanan indeks dalam InnoDB ialah pokok-B (untuk apa itu pokok-B dan apakah perbezaan antara pokok-B dan pokok-B, artikel ini tidak akan membincangkan perkara ini. Kedua-duanya boleh digabungkan secara berasingan), storan indeks kunci utama dan indeks biasa adalah berbeza. lihat, dalam indeks kunci utama, nod daun disimpan data untuk setiap baris.
Dalam indeks biasa, nod daun menyimpan nilai kunci utama Apabila kami menggunakan indeks biasa untuk mencari data, kami mula-mula mencari kunci utama dalam nod daun, dan kemudian membawa kunci utama ke. indeks kunci utama mencari data adalah bersamaan dengan melakukan dua carian, yang biasanya kita panggil operasi pulangan jadual
.3.2 Analisis Prinsip
Saya tidak tahu sama ada anda perasan bahawa semasa kami belajar MySQL, fungsi kiraan diklasifikasikan sebagai fungsi agregat Kategori itu ialah purata, jumlah, dsb. Fungsi kiraan dikumpulkan dengan ini, menunjukkan bahawa ia juga merupakan fungsi agregat. Memandangkan ia adalah fungsi agregat, adalah perlu untuk menilai keputusan yang dikembalikan baris demi baris Ini melibatkan soalan, apakah hasil yang dikembalikan? Mari kita lihat secara berasingan:
Untuk pertanyaan, enjin InnoDB akan mencari pokok indeks minimum untuk dilalui (tidak semestinya indeks kunci utama), tetapi ia tidak akan membaca data apabila ia sampai nod daun, ia mengembalikan 1, dan akhirnya hasilnya terkumpul.
Untuk select count(id) from user;
pertanyaan ini, enjin InnoDB akan melintasi keseluruhan indeks kunci utama, kemudian membaca id dan mengembalikannya Walau bagaimanapun, kerana id ialah kunci utama, ia berada pada nod daun pokok B. jadi proses ini tidak melibatkan IO (tidak perlu kembali ke jadual dan operasi lain untuk mendapatkan data dari halaman data), prestasinya juga OK.
Untuk select count(username) from user;
pertanyaan ini, enjin InnoDB akan merentasi seluruh jadual untuk melakukan imbasan jadual penuh, membaca medan nama pengguna setiap baris dan mengembalikannya jika nama pengguna ditetapkan kepada tidak batal semasa definisi, maka statistik akan terus Bilangan nama pengguna jika nama pengguna tidak ditetapkan kepada nol apabila ditakrifkan, mula-mula tentukan sama ada nama pengguna kosong, dan kemudian kira.
Akhirnya, mari kita bercakap tentang select count(*) from user;
Keistimewaan tentang SQL ini ialah ia telah dioptimumkan oleh MySQL Apabila MySQL melihat count(*)
, ia tahu bahawa anda ingin mengira jumlah rekod dan akan mencari minimum Pokok indeks dilalui, dan kemudian bilangan rekod dikira.
Oleh kerana nod daun indeks kunci primer (indeks berkelompok) ialah data, manakala nod daun indeks biasa ialah nilai kunci utama, pokok indeks indeks biasa adalah lebih kecil. Walau bagaimanapun, dalam kes di atas, kami hanya mempunyai indeks kunci utama, jadi indeks kunci utama akhirnya digunakan.
Sekarang, jika saya mengubah suai jadual di atas dan menambah indeks pada medan nama pengguna, maka mari kita lihat rancangan pelaksanaan explain select count(*) from user;
:
Seperti yang anda lihat, indeks yang digunakan pada masa ini ialah indeks nama pengguna, yang konsisten dengan keputusan analisis kami sebelum ini.
Daripada penerangan di atas, kita dapat melihat bahawa pertanyaan pertama mempunyai prestasi tertinggi, yang kedua adalah kedua (kerana ia perlu membaca id dan kembali), dan yang ketiga adalah yang paling teruk (kerana ia memerlukan imbasan jadual penuh ), prestasi pertanyaan yang keempat adalah hampir dengan prestasi yang pertama.
Sesetengah rakan mungkin tahu bahawa operasi select count(*) from user;
dalam enjin MyISAM adalah sangat pantas Itu kerana MyISAM menyimpan baris dalam jadual terus pada cakera dan membacanya terus apabila diperlukan sangat pantas.
Sebab enjin MyISAM melakukan ini adalah terutamanya kerana ia tidak menyokong urus niaga, jadi statistiknya sebenarnya sangat mudah, cuma tambah satu baris rekod.
Tetapi InnoDB kami yang biasa digunakan tidak boleh melakukan ini! kenapa? Kerana InnoDB menyokong transaksi! Untuk menyokong urus niaga, InnoDB memperkenalkan kawalan koncurrency berbilang versi MVCC, jadi mungkin terdapat masalah seperti bacaan kotor, bacaan hantu dan bacaan tidak boleh berulang semasa membaca data
Untuk butiran, sila rujuk: https: //www.bilibili.com/video/BV14L4y1B7mB
Jadi, InnoDB perlu mengeluarkan setiap baris data dan menentukan sama ada baris data kelihatan kepada sesi semasa. Jika ia kelihatan, hitung baris data Jika tidak, ia tidak akan dikira.
Sudah tentu, MVCC dalam MySQL sebenarnya adalah topik yang sangat hebat Brother Song akan memperkenalkan MVCC kepada anda secara terperinci apabila dia mempunyai masa pada masa hadapan.
Baiklah kawan-kawan faham sekarang? Jika anda mempunyai sebarang pertanyaan, sila tinggalkan mesej untuk perbincangan.
Untuk lebih banyak pengetahuan berkaitan pengaturcaraan, sila lawati: Video Pengaturcaraan! !
Atas ialah kandungan terperinci Analisis count(*) dalam MySQL Adakah ia lebih pantas daripada count(1)?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!