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 :

filtre WHERE sur premier caractère d'une colonne


Sujet :

Requêtes MySQL

  1. #1
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut filtre WHERE sur premier caractère d'une colonne
    Saluton,

    J'hésite entre trois syntaxes pour la clause WHERE d'une requête sur une table MySQL concernant une colonne indexée (pas BINARY donc case non-sensitive) :

    WHERE LEFT(col,1) = 'c'
    WHERE col LIKE 'c%'
    WHERE col BETWEEN 'c ' AND 'd '

    Laquelle vous apparaît préférable et pourquoi ?

    J'ajoute que la 3° solution me pose problème pour la lettre z, j'ai pensé à :

    WHERE col BETWEEN 'z ' AND 'zzzzzz'.

    Merci de m'éclairer de vos lumières et expériences.

    Amike.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  2. #2
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut Re: filtre WHERE sur premier caractère d'une colonne
    Le mieux, c'est surement:

    WHERE col LIKE 'c%'

    ou encore:

    WHERE col REGEXP '^c'

    REGEXP permet de traduire des expressions plus complèxes (avec des OU par exemple), mais dans ton exemple, un LIKE suffit.
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

  3. #3
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Merci de ta contribution à ma réflexion, pcaboche.

    Cependant je doute que REGEXP soit plus performant en termes de vitesse et de consommation de ressources sur le serveur.
    Les expressions régulières, très puissantes et flexibles, pêchent la plupart du temps sur ce point.
    Elles constituent ce que l'on a l'habitude d'appeler "un recours au canon pour écraser une mouche".

    Mon opinion est que tant LEFT que LIKE n'utilisent pas l'index de la colonne au contraire de la syntaxe avec BETWEEN, et que, pour cette raison, cette dernière syntaxe est la plus rapide, mais j'aimerais avoir des certitudes.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  4. #4
    Membre expérimenté
    Avatar de Adjanakis
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    739
    Détails du profil
    Informations personnelles :
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Avril 2004
    Messages : 739
    Points : 1 351
    Points
    1 351
    Par défaut
    Bonjour,

    J'ai fait un petit test en local dont voici le resultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    mysql> select benchmark(1000000000,LEFT('coucou',1)='c');
    +--------------------------------------------+
    | benchmark(1000000000,LEFT('coucou',1)='c') |
    +--------------------------------------------+
    |                                          0 |
    +--------------------------------------------+
    1 row in set (1 min 15.72 sec)
     
    mysql> select benchmark(1000000000,'coucou' like 'c%');
    +------------------------------------------+
    | benchmark(1000000000,'coucou' like 'c%') |
    +------------------------------------------+
    |                                        0 |
    +------------------------------------------+
    1 row in set (50.69 sec)
     
    mysql> select benchmark(1000000000,'coucou' between 'c' and 'd');
    +----------------------------------------------------+
    | benchmark(1000000000,'coucou' between 'c' and 'd') |
    +----------------------------------------------------+
    |                                                  0 |
    +----------------------------------------------------+
    1 row in set (1 min 27.05 sec)
     
    mysql> select benchmark(1000000000,'coucou' REGEXP '^c.*');
    +----------------------------------------------+
    | benchmark(1000000000,'coucou' REGEXP '^c.*') |
    +----------------------------------------------+
    |                                            0 |
    +----------------------------------------------+
    1 row in set (5 min 46.77 sec)
     
    mysql> select benchmark(1000000000,LEFT('coucou',1)='c');
    +--------------------------------------------+
    | benchmark(1000000000,LEFT('coucou',1)='c') |
    +--------------------------------------------+
    |                                          0 |
    +--------------------------------------------+
    1 row in set (1 min 16.28 sec)
    Bien sur, il faudrait encore savoir si ces méthodes tiennes compte des index, mais la j'ai pas le temps de faire le test
    Pensez au tag

  5. #5
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par Maljuna Kris
    Mon opinion est que tant LEFT que LIKE n'utilisent pas l'index de la colonne au contraire de la syntaxe avec BETWEEN, et que, pour cette raison, cette dernière syntaxe est la plus rapide, mais j'aimerais avoir des certitudes.
    Si si, left et LIKE utilsent bien des index (s'ils portent sur la partie gauche de la colonne) :

    A B-tree index can be used for column comparisons in expressions that use the =, >, >=, <, <=, or BETWEEN operators. The index also can be used for LIKE comparisons if the argument to LIKE is a constant string that does not start with a wildcard character.
    Pensez au bouton

  6. #6
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut
    Citation Envoyé par Maljuna Kris
    Cependant je doute que REGEXP soit plus performant en termes de vitesse et de consommation de ressources sur le serveur.
    Ca c'est évident ! Par contre il est souvent judicieux d'avoir un code facile à lire, souple et évolutif (comme dit Knuth: "Premature optimization is the root of all evil")

    Au niveau gain de performances, c'est souvent au niveau des opérations ensemblistes (les jointures) qu'il vaut mieux chercher (et faire en sorte que MySQL fasse des optimisations de lui-même en se basant sur les tailles des tables et l'existance d'index par exemple)

    Maintenant, si c'est des performances pures que tu cherches, essaye avec la fonction BENCHMARK, au moins tu sera fixé !

    Un exemple d'utilisation de BENCHMARK ici: http://www.developpez.net/forums/vie...ight=benchmark

    EDIT:
    Le temps que j'écrive ces lignes, Adjanakis a déjà fait le test. Merci Adjanakis et Maximilian !
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

  7. #7
    Rédacteur
    Avatar de pcaboche
    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    2 785
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Singapour

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 785
    Points : 9 716
    Points
    9 716
    Par défaut
    Résultat des tests d'Adjanakis:

    Sur 1000.000.000 de boucles:

    - tu perds seulement 25 secondes avec un LIKE (comme quoi, on ne perd pas tant que ça à faire des choses flexibles)

    - BETWEEN est moins performant que LIKE

    - REGEXP est dans les choux, mais comme je disais tout à l'heure, il permet d'exprimer plus de choses (donc incontournable si l'expression devient complexe)

    Encore une fois, merci Adjanakis
    "On en a vu poser les armes avant de se tirer une balle dans le pied..."
    -- pydévelop

    Derniers articles:

    (SQL Server) Introduction à la gestion des droits
    (UML) Souplesse et modularité grâce aux Design Patterns
    (UML) Le Pattern Etat
    Autres articles...

  8. #8
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Merci de toutes vos contributions, cela corrobore les tests que j'avais pu faire sur une petite table avec EXPLAIN SELECT sous phpMyAdmin.
    LIKE l'emporte sur toutes les autres solutions.

    Par contre, à ma grande surprise, si j'ajoute à la table une colonne intiale CHAR(1) indexée, et que je remplis cette colonne par UPDATE clients SET initiale=LEFT(nom,1)
    La requête
    SELECT nom FROM client WHERE initiale='c'
    est moins rapide que
    SELECT nom FROM client WHERE nom LIKE='c%', et je trouve cela très surprenant.
    Kie lumo eksistas ankaŭ ombro troviĝas. L.L. Zamenhof
    articles : Comment émuler un tableau croisé [quasi] dynamique
    et : Une énigme mathématique résolue avec MySQL
    recommande l'utilisation de PDO (PHP5 Data Objects)

  9. #9
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Peut-être qu'un ANALYZE TABLE (pour régénérer les informations d'index) arrangerait les choses.

    Sinon un EXPLAIN sur les deux SELECT nous en dirait certainement plus...
    Pensez au bouton

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RegEx] Regex sur les 3 premiers caractères d'une chaine
    Par boo64 dans le forum Langage
    Réponses: 6
    Dernier message: 01/02/2011, 09h10
  2. [XL-2000] test sur le premier caractère d'une cellule
    Par dybmans dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 27/10/2010, 10h47
  3. Requete / filtre sur le MAX d'une colonne
    Par [ced] dans le forum DB2
    Réponses: 1
    Dernier message: 20/10/2010, 20h00
  4. Index sur le contenu d'une colonne XMLTYPE
    Par haugoyard dans le forum Oracle
    Réponses: 7
    Dernier message: 11/04/2005, 11h10
  5. [C#] [WinForms] Evènement sur le tri d'une colonne
    Par beway dans le forum Windows Forms
    Réponses: 2
    Dernier message: 04/03/2005, 16h43

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