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

mysql:très simple SELECT id ORDER BY LIMIT n'utilisera pas INDEX comme prévu (?!)

Les recherches d'index se font par valeur , et non par position . Un index peut rechercher une valeur 2955900, mais vous ne le demandez pas. Vous demandez que la requête commence à un décalage de la 2 955 900e ligne du tableau.

L'optimiseur ne peut pas supposer que toutes les valeurs de clé primaire sont consécutives. Il est donc fort probable que la 2955900e ligne ait une valeur bien supérieure à cela.

Même si les valeurs de clé primaire sont consécutives, vous pouvez avoir une condition WHERE qui ne correspond, par exemple, qu'à 45 % des lignes. Dans ce cas, la valeur de l'identifiant sur la 2955900ème ligne serait way au-delà de la valeur d'identifiant 2955900.

En d'autres termes, une recherche d'index de la valeur d'identifiant 2955900 ne fournira pas la 2955900ème ligne.

MySQL ne peut donc pas utiliser l'index pour le décalage d'une limite. Il doit scannez les lignes pour les compter jusqu'à ce qu'il atteigne décalage + lignes limites.

MySQL a des optimisations liées à LIMIT , mais il s'agit plutôt d'arrêter une analyse de table une fois qu'elle a atteint le nombre de lignes à renvoyer. L'optimiseur peut toujours signaler dans un plan EXPLAIN qu'il s'attend à ce qu'il pourrait avoir à balayer toute la table.

Un malentendu fréquent à propos de FORCE INDEX est qu'il force l'utilisation d'un index. :-)En fait, si la requête ne peut pas utiliser un index (ou si les index disponibles n'ont aucun avantage pour cette requête), FORCE INDEX n'a ​​aucun effet.

Concernant votre commentaire :

La pagination est un fléau fréquent des applications Web axées sur les données. Malgré la fréquence de cette fonctionnalité, il n'est pas facile de l'optimiser. Voici quelques conseils :

  • Pourquoi interrogez-vous avec le décalage 2955900 ? Vous attendez-vous vraiment à ce que les utilisateurs parcourent autant de pages ? La plupart des utilisateurs abandonnent après quelques pages (le nombre exact dépend du type d'application et des données).

  • Réduisez le nombre de requêtes. Votre fonction de pagination peut récupérer les 5 à 10 premières pages, même si elle ne montre que la première page à l'utilisateur. Mettez en cache les autres pages, en supposant que l'utilisateur avancera sur quelques pages. Ce n'est que s'ils dépassent l'ensemble de pages mis en cache que votre application doit effectuer une autre requête. Vous pouvez même mettre en cache les 10 pages en Javascript sur le navigateur du client afin que cliquer sur "Suivant" soit instantané pour eux (au moins pour ces premières pages).

  • Ne placez pas de bouton "Dernier" sur une interface utilisateur, car les gens cliqueront dessus par curiosité. Remarquez que Google a un bouton "Suivant" mais pas un bouton "Dernier". Ainsi, l'interface utilisateur elle-même décourage les utilisateurs d'exécuter des requêtes inefficaces avec des décalages élevés.

  • Si l'utilisateur avance d'une page à la fois, utilisez la valeur d'id la plus élevée renvoyée dans la page précédente dans la clause WHERE de la requête de la page suivante. C'est à dire. ce qui suit fait utiliser l'index, même sans indice FORCE INDEX :

    SELECT * FROM thistable WHERE id > 544 LIMIT 20