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 :

Optimisation d'une requête


Sujet :

MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé Avatar de lodan
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 064
    Par défaut Optimisation d'une requête
    Bonjour,

    Sur un formulaire, je saisi le début d'un nom et avec ajax j'alimente une liste de sélection.

    Je me pose des questions sur la meilleur façon d'optimiser mes tables pour être le plus performant possible dans la lecture de mes tables.

    J'ai 2 tables : clients et clients_adresses.

    L'identifiant commun au 2 tables est "id_client".

    Dans ma table clients j'ai 3 champs sur lesquels je souhaite faire ma recherche de nom :
    - client_raison_sociale
    - client_nom
    - client_prenom

    Je concataine les 3 champs pour pouvoir faire une recherche sur "dupont philippe"

    Ma table clients a un index constitué des champs client_raison_sociale, client_nom, client_prenom

    Voici ma requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT clients.id_client, client_raison_sociale, client_service, client_nom, client_prenom, client_code_postal, client_ville
    FROM clients
    LEFT OUTER JOIN clients_adresses
    USING ( id_client )
    WHERE CONCAT(client_raison_sociale, ' ', client_nom, ' ', client_prenom) LIKE '%dupont philippe%'
    AND (
    CURDATE( ) <= client_adr_date_fin
    OR client_adr_date_debut <= CURDATE( )
    AND client_adr_date_fin = '0000-00-00'
    )
    ORDER BY client_raison_sociale, client_nom, client_prenom
    limit 0, 10
    Ma base fait 400 000 enregistrements et lorsque je fais une requête le temps de réponses est de plus de 1" voir 2".

    Comment optimiser ma requête ?

    Merci d'avance.

  2. #2
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 059
    Par défaut
    Bonjour,

    2 petites pistes vite fait :
    1. CURDATE( ) BETWEEN client_adr_date_debut AND client_adr_date_fin
    2. client_adr_date_fin IS NULL


    Ensuite, la concaténation augmente sûrement le temps de traitement et il faudrait peut-être la remplacer par une recherche un peu plus "décomposée".

    ced
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  3. #3
    Invité de passage

    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    3 995
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 995
    Par défaut
    Plusieurs choses :

    • Le fait que tu utilises une fonction (concat) va faire que MySQL ne va pas utiliser d'index. Pas idéal, niveau performance. Tu n'en as pas vraiment besoin puisque tu concatènes avec des espaces, et que tu mets un espace au milieu de ta chaine. Tu pourrais alors ajouter un index sur ces 3 champs.
    • Si tu as toujours une adresse pour chaque client, tu peux enlever le "OUTER"
    • MySQL n'aime pas les OR. Si tu as un moyen de t'en passer, ça vaut mieux. Sinon, il risque de ne pas appliquer d'index aux clauses concernées.


    L'objectif, en matière d'optimisation de requête SQL, ce n'est pas seulement de restreindre le nombre de lignes à traiter, mais aussi le plus possible les faire traiter à travers d'index.

  4. #4
    Membre éprouvé Avatar de lodan
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 064
    Par défaut
    J'ai fait les modifs préconisées dans la requête.

    Un index avec les 3 champs existe déjà (voir mon 1er post).
    Un index sur client_adr_date_debut existe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT clients.id_client, client_raison_sociale, client_service, client_nom, client_prenom, client_code_postal, client_ville
    FROM clients
    LEFT JOIN clients_adresses
    USING ( id_client )
    WHERE CONCAT( client_raison_sociale, ' ', client_nom, ' ', client_prenom ) LIKE '%dupont philippe%'
    AND (
    CURDATE( )
    BETWEEN client_adr_date_debut
    AND client_adr_date_fin
    AND client_adr_date_fin IS NOT NULL
    )
    ORDER BY client_raison_sociale, client_nom, client_prenom 
    LIMIT 0,10
    La requête dure 1.6400 sec pour un résultat de 6 enregistrement

    J'ai fait un explain dont voici le résultat
    [IMG]http://www.developpez.net/forums
    /attachment.php?attachmentid=63200&stc=1&d=1275462221[/IMG]

    Le modifs n'ont donc pas apportées le résultat que j'escomptais.

    Une autre piste ?
    Images attachées Images attachées  

  5. #5
    Membre éprouvé Avatar de lodan
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 064
    Par défaut
    Y aurait-il un intérêt à créer un champ dans la table concaténant sans espace la raison sociale, le nom et le prénom et de faire une recherche dessus avec une expression sans espace ?

  6. #6
    Membre chevronné
    Avatar de argoet
    Inscrit en
    Mai 2002
    Messages
    582
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 582
    Par défaut
    Quelques Remarques en passant :

    Pourquoi faire une rechecrche sur 3 champs concatene si vous rechercher "dupont" et "philippe"
    n'est il pas possible d'associer dupont au nom et philippe au prenom ?


    Ma table clients a un index constitué des champs client_raison_sociale, client_nom, client_prenom
    Raison sociale n'etant absolument pas discriminant vous avez tout interet à créer votre index sur 1:le nom 2:le Prenom et(ou pas) eventuelement la raison sociale

    le fait de faire un "like %XXX%" va forcement réaliser un "access full" sur la table donc au final votre index ne sert à rien dans la présente requete

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

Discussions similaires

  1. Optimisation d'une requête
    Par Louis-Guillaume Morand dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 20/12/2005, 18h21
  2. Optimisation d'une requête d'insertion
    Par fdraven dans le forum Oracle
    Réponses: 15
    Dernier message: 01/12/2005, 14h00
  3. Optimisation d'une requête patchwork
    Par ARRG dans le forum Langage SQL
    Réponses: 1
    Dernier message: 11/09/2005, 15h23
  4. optimisation d'une requête avec jointure
    Par champijulie dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 07/07/2005, 09h45
  5. [DB2] Optimisation d'une requête
    Par ahoyeau dans le forum DB2
    Réponses: 7
    Dernier message: 11/03/2005, 17h54

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