Mysql
 sql >> Base de données >  >> RDS >> Mysql

Lors de la commande par date desc, l'utilisation de requêtes ralentit temporairement

Je pense que la plupart des problèmes ici et dans des questions similaires proviennent d'un malentendu sur la façon dont MySQL (et d'autres bases de données) utilise les index pour le tri. La réponse est la suivante :MySQL n'utilise pas d'index pour le tri, il peut simplement lire les données dans l'ordre d'un index ou dans le sens opposé. S'il vous arrivait de vouloir que les données soient triées dans l'ordre de l'index actuellement utilisé - vous avez de la chance, sinon le résultat sera trié (d'où filesort dans EXPLAIN)

C'est l'ordre de l'ensemble du résultat dépend principalement de la table qui était la première dans la jointure. Et si vous regardez votre EXPLAIN, vous verrez que la jointure commence à partir de la table 'log_codes' (car elle est beaucoup plus petite).

Fondamentalement, ce dont vous avez besoin est un index composite (partner_id, date) sur 'log_entries', un index composite couvrant (log_code, category_overview, log_desc) pour 'log_codes', changez 'INNER JOIN' en 'STRAIGHT_JOIN' pour forcer l'ordre de jointure, et trier par 'date' DESC (cet index couvrira heureusement aussi).

UPD1 :Je suis désolé, j'ai mal tapé l'index de la première table :il devrait être (partner_id, log_code, date) .

MySQL peut soit sortir directement les données tant que vous êtes d'accord avec l'ordre dans lequel il les obtient, soit mettre les données dans une table temporaire, appliquer ensuite le tri et la sortie. Lorsque vous commandez par un champ à partir d'une table qui n'est pas la première dans les jointures, MySQL doit trier les données (pas seulement la sortie dans l'ordre d'un index) et pour trier les données, il a besoin d'une table temporaire.

Pour sortir les lignes 50000,25 MySQL doit de toute façon récupérer les 50000 premiers et les ignorer. Comme j'ai raté une colonne dans l'index, MySQL n'a pas seulement scanné l'index, mais pour chaque élément, il a fait une recherche supplémentaire sur le disque pour log_code évaluer. Avec l'index de couverture, cela devrait être beaucoup plus rapide, puisque toutes les données peuvent être extraites de l'index.

UPD2 :essayez de forcer l'index :

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;