Pertimbangkan tabel nilai dan hash, seperti:
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| val | char(9) | NO | | NULL | |
| val_hashed | char(50) | YES | | NULL | |
+------------+----------+------+-----+---------+----------------+
Permintaan berikut selesai dalam 0,00 detik:
SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;
Namun, kueri ini membutuhkan 3 menit 17 detik:
SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;
Saya melihat bahwa ketika kueri sedang menjalankan daftar proses menunjukkannya sebagai status Sorting result
. Situasi ini sepenuhnya dapat direproduksi. Perhatikan bahwa ada proses lain yang melakukan INSERT
operasi di atas meja secara terus menerus.
Mengapa kueri yang lebih spesifik membutuhkan waktu lebih lama untuk dijalankan daripada *
kueri? Saya selalu percaya bahwa *
pertanyaan harus dihindari secara khusus karena alasan kinerja.
mysql
performance
select
dotancohen
sumber
sumber
id
untuk menemukan baris pertama. Yang kedua perlu mengurutkan hasil lengkap pada kolom (tidak diindeks)val
.ORDER BY NUMBER
sintaks cukup kesalahan rawan.SELECT *
dikombinasikan dengan indeks kolom dalamORDER BY
mengaburkan kolom mana yang sedang disortir - alasan lain untuk menghindari*
...*
tidak eksplisit. Jadi mengatakan "beri saya semua kolom dan urutkan berdasarkan yang ketiga" adalah tentang deterministik seperti mengatakan "pergi ke supermarket dan katakan berapa banyak lampu lalu lintas yang Anda lewati"Jawaban:
Ungkapan tersebut
ORDER BY 1
merujuk pada kolom yang berbeda; di pertama akanid
, di keduaval
. Karenaid
kuncinya akan diindeks danorder by
akan menjadi jumlah pekerjaan yang sepele. Untukorder by val
, bagaimanapun, sistem harus mengambil setiap baris, mengurutkan tabel lengkap denganval
, lalu pilih hanya satu dari baris itu.Ubah kedua kueri
order by id
dan saya pikir waktu eksekusi Anda akan hampir sama.sumber
Perbedaan kinerja dalam permintaan Anda dijelaskan dengan baik oleh MG. Saya akan membahas ini:
select *
tidak membawa hukuman tertentu dengan sendirinya, itu bermasalah ketika disalahgunakan. Dalam kueri tabel tunggal berfungsi dengan baik. sekarang gabung tabel itu ke yang lain dengan 20 kolom, dan kemudian tambahkan bergabung ke 5 tabel lainnya dengan banyak kolom masing-masing. SEKARANG itu masalah. Begitu juga orang-orang yang mengajar bantuan band yang luas "never do X" tanpa menjelaskan alasannya.sumber
SELECT *
mungkin menjadi masalah bahkan untuk kueri tabel tunggal. Misalnya,SELECT * FROM hashes ORDER BY val;
mungkin akan melakukan pemindaian tabel penuh dan kemudian pengurutan sementaraSELECT val FROM hashes ORDER BY val;
hanya akan melakukan pemindaian indeks penuh, dan tidak ada pengurutan (dengan asumsi indeks ada pada val). Jadi, tidak ada salahnya untuk memilih hanya hasil yang kita butuhkan.select(*)
hanya digunakan sebagai sub-pilihan ? Karena ini merupakan pilihan yang disematkan, Bukankah MySQL cukup pintar untuk mengetahui kolom sebenarnya yang perlu dipilih?