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

MySQL Discussion :

indexer une table correctement


Sujet :

MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 39
    Par défaut indexer une table correctement
    Bonjour,

    J'ai indexé ma table client sur les champs suivants :
    - nom_client => idx_client_nom
    - cp_client => idx_client_cp

    Quand je fais un explain SQL : mon indexation est bien prise en compte

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    EXPLAIN 
    SELECT * FROM client AS c WHERE (client_cp= 38210 and client_nom = 'FDDDDD');

    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <DATA>
     
    	<ROW>
    		<id>1</id>
    		<select_type>SIMPLE</select_type>
    		<table>c</table>
    		<type>ref</type>
    		<possible_keys>idx_client_nom,idx_client_client_nom_client_facture_client_utilisateur,idx_client_cp</possible_keys>
    		<key>idx_client_nom</key>
    		<key_len>66</key_len>
    		<ref>const</ref>
    		<rows>1</rows>
    		<Extra>Using index condition; Using where</Extra>
    	</ROW>
    </DATA>

    Par contre, quand je fais

    Quand je fais un explain SQL : mon indexation n'est pas prise en compte

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    EXPLAIN 
    SELECT * FROM client AS c WHERE (client_cp= 38210 OR client_nom = 'FDDDDD');

    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <DATA>
    	<ROW>
    		<id>1</id>
    		<select_type>SIMPLE</select_type>
    		<table>c</table>
    		<type>ALL</type>
    		<possible_keys>idx_client_nom,idx_client_client_nom_client_facture_client_utilisateur,idx_client_cp</possible_keys>
    		<key>NULL</key>
    		<key_len>NULL</key_len>
    		<ref>NULL</ref>
    		<rows>11815</rows>
    		<Extra>Using where</Extra>
    	</ROW>
    </DATA>

    QUESTION : COMMENT FAIRE POUR QUE MON INDEXATION SOIT UTILISEE QUAND J UTILISE DES 'OR' DANS MES REQUËTES SQL ?

    Merci de votre attention et pour vos éventuels réponses.

    Cordialement,
    Titoff

  2. #2
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    La colonne client_cp est-elle de type entier comme le suggère la requête ou de type CHAR ou VARCHAR comme ça devrait être le cas pour un code postal, si c'est bien un code postal ?

    Combien y a t-il de client_cp différents dans la table ?
    Peut-être que la cardinalité n'est pas assez importante et que MySQL considère que d'utiliser cet index n'est pas pertinent.

    Que se passe t-il si vous inversez les deux conditions ?
    L'index sur client_nom est-il utilisé ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 883
    Par défaut
    Salut titoff002.

    Le '=' sur une zone définie en varchar peut poser des problèmes. La bonne syntaxe est bien 'like'.

    Citation Envoyé par titoff002
    SELECT * FROM client AS c WHERE (client_cp= 38210 OR client_nom = 'FDDDDD');
    As-tu essayé de faire un "UNION ALL" ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT * FROM client WHERE (client_cp= 38210)
    union all
    SELECT * FROM client WHERE (client_nom like 'FDDDDD');
    J'ai pas testé donc je ne sais pas si cela résout ton problème.

    @+

  4. #4
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Le '=' sur une zone définie en varchar peut poser des problèmes. La bonne syntaxe est bien 'like'.
    Euh... ça c'est du grand n'importe quoi !
    LIKE n'a de sens que si on utilise un caractère générique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE la_colonne LIKE '%du texte%'
    Sans caractère générique, il vaut mieux utiliser = qui n'est pas un opérateur utilisable que sur une expression numérique mais de n'importe quel type, dès lors qu'on recherche une égalité et non pas une approximation.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 883
    Par défaut
    Salut Cinephil.

    Citation Envoyé par CinePhil Voir le message
    LIKE n'a de sens que si on utilise un caractère générique
    Non, ce que tu dis n'est pas vrai.

    Le '=' s'utilise en tant qu'opérateur arithmétique. Pour les chaînes de caractères, c'est bien 'LIKE', avec ou sans caractères génériques.
    Justement, le fait de ne pas utiliser 'LIKE' est fréquemment source de problèmes.

    J'ai déjà traité dans un sujet ce genre de problème et toi-même tu disais qu'il existait un bug dans MySql.
    Je t'ai démontré que ce n'était pas vrai, car il faut utiliser 'LIKE' et non '='.

    @+

  6. #6
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    Donne moi le lien de la discussion alors mais voici ce que dit SQLPro dans son cours :
    L'opérateur LIKE permet d'effectuer une comparaison partielle. Il est surtout employé avec les colonnes contenant des données de type alpha. Il utilise les jokers % et _ (‘pour cent' et ‘blanc souligné'). Le joker % remplace n'importe quelle chaîne de caractères, y compris la chaîne vide. Le blanc souligné remplace un et un seul caractère.
    Et dans ce même cours, tous les exemples de code précédent ce chapitre emploient = avec des chaînes de caractères. Et même <= ou BETWEEN !
    Comme quoi ce n'est pas du tout résevé aux valeurs numériques !

    EDIT :
    J'ai retrouvé la discussion à laquelle tu faisais allusion.
    Le cas était bien différent : il s'agissait de l'idée bizarre de vouloir insérer seulement un caractère blanc (un espace) dans une colonne VARCHAR.

    Ici, il s'agit bien de chercher une valeur textuelle non vide - ou non considérée comme vide par MySQL (seulement un espace dans la colonne).

    Bien que SQLPro ait confirmé que ce comportement étrange soit conforme à la norme, cela reste pour moi une anomalie, donc normative ! Un espace, c'est un caractère ayant un code ASCII (de mémoire : 32). Une chaîne vide, c'est zéro caractère !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  7. #7
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 883
    Par défaut
    Salut Cinephil.

    Ce qui m'énerve, c'est de toujours répéter la même chose et de ne pas être compris.
    Le sujet en question est le suivant : http://www.developpez.net/forums/d99...space-d-champ/

    Un membre persiste à dire qu'il y a un bug alors qu'il continue d'utiliser le '=' sur des chaînes de caractères.
    Alors qu'avec le 'LIKE', comme par miracle, le bug disparaît.
    Soit deux chose l'une, ou bien le bug existe (ce que je ne crois pas), ou bien on fait un mauvais usage des opérateurs.
    Personnellement, je pencherais pour la deuxième hypothèse.

    Ce que je ne comprends pas, Cinephil, c'est ton entêtement à croire que l'opérateur '=' est le seul valide pour tester une chaîne de caractères.
    Et l'opérateur 'LIKE' a été inventé pour qui ?

    L'opérateur 'LIKE' est le seul opérateur qui fonctionne correctement pour les chaînes de caractères !
    Et nul besoin de trouver des excuses du genre "LIKE n'a de sens que si on utilise un caractère générique".
    Donc si tu n'as pas de caractères génériques alors tu te refuses de l'utiliser. On se demande bien pourquoi ?

    Et arrête de toujours me prendre à parti en donnant une référence de ton Dieu SQLPRO.
    J'ai surtout l'impression que tu n'es pas capable de te rendre compte par toi même de ce genre de problème.

    @+

  8. #8
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    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 818
    Billets dans le blog
    14
    Par défaut
    On se calme !

    Quel est le but de LIKE ?
    => Faire une comparaison partielle à l'aide de caractères génériques.

    Quel est le but de = ?
    => Faire une comparaison exacte.

    Est-ce que LIKE sans caractère générique fonctionne ?
    => Oui, c'est équivalent à = sauf dans le cas précis - et très bizarre, je persiste - où une des chaînes finit par des blancs ; à plus forte raison pour la comparaison d'une chaîne ' ' avec une chaîne vide, ce qui était le cas de la discussion à laquelle tu faisais référence. (Voir mon EDIT) sur mon précédent message.

    Selon moi, dire au gens d'utiliser systématiquement LIKE en guise de comparaison exacte de chaînes de caractères est aussi stupide que de recommander d'utiliser systématiquement un tournevis plat pour des vis cruciformes ! Ca fonctionne le plus souvent mais ce n'est pas l'outil adéquat.

    Je continuerai donc de recommander, surtout aux débutant, d'être rigoureux en utilisant =, ce qui leur permettra au moins de se poser des questions s'ils tombent par hasard sur la cas saugrenu de la chaîne avec seulement un espace.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 883
    Par défaut
    Salut Cinephil.

    Citation Envoyé par Cinephil
    On se calme !
    Mais c'est toi qui provoque !

    Citation Envoyé par Cinephil
    Quel est le but de LIKE ?
    => Faire une comparaison partielle à l'aide de caractères génériques.
    Oui, entre autre. Mais pourquoi se limiter à utiliser le 'LIKE' uniquement si tu utilises des caractères génériques ?

    Je ne comprends pas pourquoi tu te refuses d'utiliser l'opérateur 'LIKE', sous prétexte de ne pas utiliser les caractères génériques. Bizarre cet entêtement ?

    Citation Envoyé par Cinephil
    Quel est le but de = ?
    => Faire une comparaison exacte.
    Faux !!! Justement avec '=', le test de comparaison exacte ne fonctionne pas, surtout s'il y a des blancs à la fin de la chaîne.

    Citation Envoyé par Cinephil
    Est-ce que LIKE sans caractère générique fonctionne ?
    => Oui, c'est équivalent à =
    Justement, je viens de dire que ce n'était pas équivalent.
    Cela ne fonctionne pas comme un '=', c'est-à-dire un test d'égalité caractères par caractères.

    Citation Envoyé par Cinephil
    sauf dans le cas précis - et très bizarre, je persiste - où une des chaînes finit par des blancs ; à plus forte raison pour la comparaison d'une chaîne ' ' avec une chaîne vide, ce qui était le cas de la discussion à laquelle tu faisais référence. (Voir mon EDIT) sur mon précédent message.
    Justement, si tu le sais, pourquoi continues-tu d'utiliser le '=' alors qu'avec le 'LIKE' le problème est résolu ?

    Voici justement un exemple que je viens de tester pour montrer que je dis vrai.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE TABLE IF NOT EXISTS `chaines`
    (
            `zone1` varchar(10) not null,
            `zone2`    char(10) not null
    )       ENGINE=InnoDB
            ROW_FORMAT=COMPRESSED
            DEFAULT CHARSET=`utf8` COLLATE=`utf8_general_ci`
    --------------
     
    --------------
    insert into `chaines` (`zone1`,`zone2`) value
    ('abcd', ''),
    ('abcd  ', ' ')
    --------------
    Je donne à titre indicatif la base que j'utilise pour le test.

    Ci-après, je fais un vidage du contenu de la table.
    Deux lignes, dont l'une se termine par des blancs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    --------------
    select concat('>>',zone1,'<<') as z1,
           concat('>>',zone2,'<<') as z2
    from chaines
    --------------
     
    +------------+------+
    | z1         | z2   |
    +------------+------+
    | >>abcd<<   | >><< |
    | >>abcd  << | >><< |
    +------------+------+
    Ci-après le test avec '=' qui ne fonctionne pas, puisque j'obtiens deux lignes au lieu d'une seule.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    --------------
    select concat('>>',zone1,'<<') as z1,
           concat('>>',zone2,'<<') as z2
    from chaines
    where zone1 = 'abcd'
    --------------
     
    +------------+------+
    | z1         | z2   |
    +------------+------+
    | >>abcd<<   | >><< |
    | >>abcd  << | >><< |
    +------------+------+
    Et ci-après avec le 'LIKE' qui fonctionne parfaitement.
    Une seule ligne apparait.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    --------------
    select concat('>>',zone1,'<<') as z1,
           concat('>>',zone2,'<<') as z2
    from chaines
    where zone1 like 'abcd'
    --------------
     
    +----------+------+
    | z1       | z2   |
    +----------+------+
    | >>abcd<< | >><< |
    +----------+------+
    Tu raisonnes justement à l'envers de ce qu'il faut faire.
    Si tu compares 'abcd' avec 'abcd ', normalement, il n'y a pas d'égalité car les chaînes n'ont pas la même longueur.
    Et pourtant avec '=', il dit qu'il y a égalité.

    Inversement, avec 'LIKE', l'égalité est confirmé.

    Maintenant fait le test et vérifie par toi-même ce que j'affirme. En procédant ainsi, tu véhicules des mauvaises habitudes aux débutants.

    @+

  10. #10
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Pour en revenir au sujet initial, OR est on sargable, et donc pas d'index possible sur cette portion de requête.

    Si on veut vraiment utiliser un index, on séparera la requête en deux, avec un UNION (avec ou sans ALL) comme l'a suggéré Artemus24.

Discussions similaires

  1. Indexer une table
    Par AbouZaid dans le forum SQL
    Réponses: 14
    Dernier message: 19/05/2011, 11h15
  2. Réponses: 3
    Dernier message: 08/04/2011, 12h26
  3. indexer une table
    Par cam360 dans le forum SAP
    Réponses: 3
    Dernier message: 30/06/2008, 16h47
  4. Conseil pour Indexer une table DBase
    Par alainvh dans le forum Bases de données
    Réponses: 4
    Dernier message: 08/05/2006, 22h27
  5. Indexer une table
    Par localhost dans le forum PostgreSQL
    Réponses: 7
    Dernier message: 27/02/2005, 13h49

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