Saya mengerti bagaimana ORDER BY
klausa bekerja dan bagaimana FIELD()
fungsinya bekerja. Yang ingin saya pahami adalah bagaimana keduanya bekerja sama untuk menyortir. Bagaimana baris diambil dan bagaimana urutan sortir diturunkan
+----+---------+
| id | name |
+----+---------+
| 1 | stan |
| 2 | kyle |
| 3 | kenny |
| 4 | cartman |
+----+---------+
SELECT * FROM mytable WHERE id IN (3,2,1,4) ORDER BY FIELD(id,3,2,1,4)
Kueri di atas akan menghasilkan
+----+---------+
| id | name |
+----+---------+
| 3 | kenny |
| 2 | kyle |
| 1 | stan |
| 4 | cartman |
+----+---------+
sesuatu yang mirip dengan mengatakan ORDER OLEH 3, 2, 1, 4
PERTANYAAN
- Bagaimana cara kerjanya secara internal?
- Bagaimana cara MySQL mendapatkan baris, dan menghitung urutan pengurutan?
- Bagaimana MySQL tahu harus mengurutkan berdasarkan kolom id?
SELECT *, FIELD(id,3,2,1,4) AS f FROM mytable WHERE id IN (3,2,1,4);
Kemudian tambahkanORDER BY f
atauORDER BY FIELD(id,3,2,1,4)
dan coba lagi.Jawaban:
Untuk catatan
harus bekerja juga karena Anda tidak perlu memesan daftar di
WHERE
klausaAdapun cara kerjanya,
FIELD () adalah fungsi yang mengembalikan posisi indeks daftar yang dibatasi koma jika nilai yang Anda cari ada.
The
ORDER BY
nilai dievaluasi oleh apa yang LAPANGAN () returnAnda dapat membuat segala macam pesanan mewah
Misalnya, menggunakan IF () function
Ini akan menyebabkan 4 id pertama muncul di bagian atas daftar, Jika tidak, ia muncul di bagian bawah. Mengapa?
Di
ORDER BY
, Anda mendapatkan 0 atau 1.Mari kita balikkan dengan DESC di kolom pertama
Di
ORDER BY
, Anda masih mendapatkan 0 atau 1.PERTANYAAN SEBENARNYA
Jika Anda benar-benar ingin masalah internal ini, baca halaman 189 dan 192 dari Buku
untuk menyelam yang sangat dalam.
Intinya, ada kelas C ++ yang disebut
ORDER *order
(ORDER BY
Pohon ekspresi). InJOIN::prepare
,*order
digunakan dalam fungsi yang disebutsetup_order()
. Kenapa di tengahJOIN
kelas? Setiap kueri, bahkan kueri terhadap satu tabel selalu diproses sebagai GABUNG (Lihat posting saya Apakah ada perbedaan eksekusi antara kondisi GABUNG dan kondisi DIMANA? )Kode sumber untuk semua ini adalah
sql/sql_select.cc
Jelas,
ORDER BY
pohon itu akan mengadakan evaluasiFIELD(id,3,2,1,4)
. Dengan demikian, angka 0,1,2,3,4 adalah nilai yang sedang disortir sambil membawa referensi ke baris yang terlibat.sumber
N
nilai di keduanyaIN
danFIELD
. Dalam contoh iniN=4
. Apakah saya mengerti benar bahwa permintaan ini akan melakukan setidaknya~N^2
operasi. Karena setiapFIELD
perhitungan membuat~N
perbandingan satu kali untuk setiap baris. Jika demikian, ini cukup lambat untuk besar.N
Mungkin itu bukan pendekatan yang sangat baik?FIELD()
Fungsi ini harusO(1)
operasi karenaFIELD()
memiliki indeks numerikid
. Jadi saya tidak melihat yang lain kecualiO(n)
berdasarkan baris. Saya tidak melihatFIELD()
melakukan operasi berulang seperti yangGREATEST()
perlu dilakukan.FIELD
memilikiN
argumen untuk dibandingkan maka akan menjalankanN
perbandingan. Bagaimana lagi jika membandingkan satu angka denganN
angka lainnya jika tidak dengan melakukanO(N)
? Satu-satunya kemungkinan yang dapat saya pikirkan adalah beberapa jenis optimasi melalui struktur data khusus seperti hash atau pohon argumen. Sebenarnya saya tahu bahwaIN
memang memiliki optimasi seperti itu. Saya tidak tahuFIELD
. Apa yang Anda maksud dengan "indeks numerik"?Mungkin ini akan terlalu jauh dari kode sebenarnya sehingga tidak cukup rendah dari yang Anda inginkan:
Ketika MySQL tidak dapat menggunakan indeks untuk mengambil data dalam urutan terurut, ia membuat tabel / resultset sementara dengan semua kolom yang dipilih dan beberapa data tambahan - salah satunya adalah semacam kolom untuk menyimpan hasil ORDER BY nilai ekspresi untuk setiap baris - kemudian mengirimkan tabel tmp ini ke rutine "filesort" dengan info kolom mana yang akan diurut. Setelah itu, baris-baris tersebut disusun dalam urutan sehingga dapat memilih satu per satu dan mengembalikan kolom yang dipilih.
sumber
FIELD
fungsi dalam dihitung. Saya khawatir itu mungkin berdampak signifikan pada kinerja.