Saya pikir, sebagian besar masalah di sini dan dalam pertanyaan serupa berasal dari kesalahpahaman bagaimana MySQL (dan database lain) menggunakan indeks untuk menyortir. Jawabannya adalah:MySQL tidak menggunakan indeks untuk pengurutan, hanya dapat membaca data dengan urutan indeks atau sebaliknya. Jika Anda ingin data diurutkan dalam urutan indeks yang saat ini digunakan - Anda beruntung, jika tidak, hasilnya akan diurutkan (maka filesort di EXPLAIN)
Itu adalah urutan seluruh hasil sebagian besar tergantung pada tabel mana yang pertama di gabung. Dan jika Anda melihat EXPLAIN Anda, Anda akan melihat bahwa penggabungan dimulai dari tabel 'log_codes' (karena jauh lebih kecil).
Pada dasarnya, yang Anda butuhkan adalah indeks komposit (partner_id, tanggal) pada 'log_entries', indeks komposit yang mencakup (log_code, category_overview, log_desc) untuk 'log_codes', ubah 'INNER JOIN' menjadi 'STRAIGHT_JOIN' untuk memaksa join order, dan pesan berdasarkan 'tanggal' DESC (untungnya indeks ini juga mencakup).
UPD1 :Maaf, saya salah mengetik indeks untuk tabel pertama:seharusnya (partner_id, log_code, date)
.
MySQL dapat langsung menampilkan data selama Anda setuju dengan urutan yang diperolehnya, atau meletakkan data dalam tabel sementara, menerapkan penyortiran dan keluaran kemudian. Saat Anda memesan berdasarkan bidang dari tabel non-pertama dalam gabungan, MySQL harus mengurutkan data (bukan hanya output dalam urutan indeks) dan untuk mengurutkan data diperlukan tabel sementara.
Untuk menampilkan baris 50000,25 MySQL tetap perlu mengambil 50000 pertama dan melewatinya. Karena saya melewatkan kolom dalam indeks, MySQL tidak hanya memindai indeks tetapi untuk setiap item membuat tambahan pada pencarian disk untuk log_code
nilai. Dengan indeks penutup yang seharusnya lebih cepat, karena semua data dapat diambil dari indeks.
UPD2 :coba paksa indeks:
SELECT log_entries.date, log_codes.log_desc
FROM log_entries FORCE INDEX (IX_partner_code_date)
STRAIGHT_JOIN log_codes
ON log_codes.log_code = log_entries.log_code
WHERE log_entries.partner_id = 1
AND log_codes.category_overview = 1
ORDER BY log_entries.date DESC;