IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Pourquoi cette requête n'utilise pas d'index ?


Sujet :

Requêtes MySQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 113
    Points : 41
    Points
    41
    Par défaut Pourquoi cette requête n'utilise pas d'index ?
    Bonjour à tous,

    Je suis dans un cas qui me surprend avec mysql MyISAM.

    J'ai une table avec id,login,pseudo (enfin pour simplifier) sur laquelle j'ai 3 clés : primaire sur id, unique sur login et pseudo. Quand je fais cette requette :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    explain SELECT id FROM `users` WHERE (login like 'toto' or pseudo like 'titi') AND id<>10
    J'ai :
    1 SIMPLE users ALL PRIMARY,login,pseudo NULL NULL NULL 90775 Using where
    On voit qu'il parcours la totalité de la table (90775 enregistrements). Ce qui biensur n'est pas l'idéal pour l'optimisation.

    si je vire le test du id<>10 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    explain SELECT id FROM `users` WHERE (login like 'toto' or pseudo like 'titi')
    Alors pas de soucis :

    1 SIMPLE users index_merge login,pseudo login,pseudo 18,18 NULL 2 Using union(login,pseudo); Using where
    Je ne comprend pas pourquoi mysql n'utilise plus les index quand j'ajoute ce AND. Ce n'est pas tres grave puisque il me suffit de la faire sans le AND et de tester les resultats derriere.

    Mais je ne saisi pas bien le comportement. Est-ce que quelq'un aurait une explication ?

    Merci à vous.

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Pour commencer, un like sans caractère générique % est équivalent à une égalité.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    LIKE 'toto'
     
    # est équivalent à 
     
    = 'toto'
     
    # Il faudrait plutôt par exemple :
     
    LIKE '%toto'
    Je suppose que l'optimiseur se dit : "puisqu'il y a des LIKE, je vais être obligé de tout parcourir, voyons la dernière condition. C'est une différence sur une valeur de clé primaire donc j'examine toutes les lignes sauf l'id 10 et je traite le LIKE."

    Par contre pourquoi le fait de supprimer l'inégalité le fait changer de raisonnement ?

    Mais peut-être que mon hypothèse de raisonnement de l'optimiseur est totalement fausse !

    Quoi qu'il en soit, si tu sélectionnes des valeurs exactes, utilise le = plutôt que le LIKE.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 113
    Points : 41
    Points
    41
    Par défaut
    Salut,

    Bien vu pour le like, c'est une mauvaise habitude le mettre plutot que le =.

    Du coup j'ai testé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    EXPLAIN SELECT id FROM `users` WHERE (login='toto' OR pseudo='titi') AND id<>10
    Resultat :

    1 SIMPLE users ALL PRIMARY,login,pseudo NULL NULL NULL 90888 Using where
    Pareil... ça ne change rien.

    Je comprend bien l'idée du test different sur une clé primaire. Je comprend qu'il soit obligé de chercher dans toute la table. Mais je comprend pas pourquoi il ne selectionne pas une des deux autres clés ayant une cardinalité totale puisque unique.

    Du coup j'ai fais un autre test sur un autre champ n'ayant pas de clé, juste pour voir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    EXPLAIN SELECT id FROM `users` WHERE (login='toto' OR pseudo='titi') AND grade<>10
    Et là :

    1 SIMPLE users index_merge login,pseudo login,pseudo 18,18 NULL 2 Using union(login,pseudo); Using where
    C'est donc bien l'histoire de la clé primaire qui le gene. Il doit donner priorité à cette clé quelque soit le reste de la requette. C'est domage...

    Par contre un truc interressant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    EXPLAIN SELECT id FROM `users` WHERE (login='toto') AND id<>10
    donne :
    1 SIMPLE users const PRIMARY,login login 18 const 1
    Donc j'en deduit qu'il donne bien priorité à la clé primaire (evidement d'ou son nom) sauf si il trouve plus rapide, mais seulement à condition qu'il n'y ait pas de OR entre 2 autres clés (meme unique). Bon.. à la rigueur ça peut se comprendre, ça manque ptet juste d'un poil de reflexion mais bon, on peut pas lui demander une intelligence artificielle non plus.

    Du coup je me demande si le fait de faire une clé unique au lieu de primaire ne reglerait pas la situation. Faudra que je test..

    Enfin c'est bon à savoir. Merci pour le post qui m'a permet de creuser dans le bon sens

Discussions similaires

  1. Réponses: 2
    Dernier message: 22/06/2013, 07h24
  2. Pourquoi Oracle n'utilise pas mes index ?
    Par yaggi64 dans le forum SQL
    Réponses: 4
    Dernier message: 25/11/2007, 16h03
  3. Pourquoi cette requête SQL ne marche pas toujours
    Par Platon93 dans le forum Requêtes et SQL.
    Réponses: 17
    Dernier message: 14/12/2006, 17h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo