ここでの問題や同様の質問のほとんどは、MySQL(および他のデータベース)がソートにインデックスを使用する方法を誤解していることが原因だと思います。答えは次のとおりです。MySQLは並べ替えにインデックスを使用せず、インデックスの順序または反対方向にデータを読み取ることができます。たまたま現在使用されているインデックスの順序でデータを並べ替えたい場合は、幸運です。そうでない場合、結果は並べ替えられます(したがって、EXPLAINのファイル並べ替え)
つまり、結果全体の順序は、ほとんどの場合、結合の最初のテーブルに依存します。また、EXPLAINを見ると、結合が「log_codes」テーブルから開始されていることがわかります(これははるかに小さいためです)。
基本的に、必要なのは「log_entries」の複合インデックス(partner_id、date)、「log_codes」のカバー複合インデックス(log_code、category_overview、log_desc)です。「INNERJOIN」を「STRAIGHT_JOIN」に変更して、結合順序を強制します。 「日付」DESCで並べ替えます(このインデックスも幸いにもカバーされます)。
UPD1 :申し訳ありませんが、最初のテーブルのインデックスの入力を間違えました。(partner_id, log_code, date)
である必要があります。 。
MySQLは、データを取得する順序に同意する限り、データを直接出力するか、データを一時テーブルに配置して、並べ替えを適用して出力することができます。結合の最初以外のテーブルのフィールドで並べ替える場合、MySQLはデータを並べ替える必要があり(インデックスの順序で出力するだけでなく)、データを並べ替えるには一時テーブルが必要です。
行50000,25を出力するには、とにかくMySQLは最初の50000をフェッチし、それらをスキップする必要があります。インデックスの列を見逃したため、MySQLはインデックスをスキャンしただけでなく、アイテムごとにlog_code
のディスクルックアップを追加しました。 価値。すべてのデータをインデックスからフェッチできるため、カバーするインデックスの方がはるかに高速であるはずです。
UPD2 :インデックスを強制してみてください:
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;