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 :

Requête avec jointure lente


Sujet :

Requêtes MySQL

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut Requête avec jointure lente
    Bonjour,

    j'ai un problème de vitesse sur une requete, pouvez vous m'aider?

    voici mes tables:
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    CREATE TABLE `site_domaines` (
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id du (sous)domaine',
     `nom` varchar(10) NOT NULL COMMENT 'nom du domaine',
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='Cette table contient la liste des (sous)domaine du site'

    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CREATE TABLE `site_sections` (
     `domaine_id` int(10) unsigned NOT NULL COMMENT 'id du (sous)domaine',
     `section_id` int(10) unsigned NOT NULL COMMENT 'id de la section',
     `nom` varchar(20) NOT NULL COMMENT 'nom de la section',
     PRIMARY KEY (`domaine_id`,`section_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Cette table contient la liste des sections du site'

    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    CREATE TABLE `site_urls` (
     `domaine_id` int(10) unsigned NOT NULL COMMENT 'id du (sous)domaine',
     `section_id` int(10) unsigned NOT NULL COMMENT 'id de la section dans le domaine',
     `item_id` int(10) unsigned NOT NULL COMMENT 'id de l''element dans la section',
     `language_id` int(10) unsigned NOT NULL COMMENT 'id du language de l''url',
     `url` text NOT NULL COMMENT 'url de la page',
     `modified` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'date de mise à jour de l''article',
     PRIMARY KEY (`domaine_id`,`section_id`,`item_id`,`language_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Cette table contient toutes les urls du site'

    item_id sert à lier les urls d'un meme article en plusieurs langues
    la table site_urls contient toutes les urls du site pour les pages en français et les pages en anglais

    ET voici la requete:
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT sufr.url fr, suen.url en, su.modified
    FROM site_urls su
    LEFT JOIN site_urls sufr ON sufr.domaine_id = su.domaine_id AND sufr.section_id = su.section_id AND sufr.item_id = su.item_id AND sufr.language_id = 1 
    LEFT JOIN site_urls suen ON sufr.domaine_id = su.domaine_id AND suen.section_id = su.section_id AND suen.item_id = su.item_id AND suen.language_id = 2 
    WHERE su.domaine_id = 1 AND su.section_id = 2 
    GROUP BY su.item_id
    ORDER BY su.modified DESC



    Je cherche a obtenir la liste des urls d'une section du site avec les colonnes suivantes:

    fr = url de la page en français,
    en = url de la page en anglais,
    modified = date de dernière modification (du couple français anglais).


    La requete fonctionne correctement il me semble mais il me faut 27 secondes pour sortir 5000 lignes, je m'attendais a avoir un resultat en moins de 3 secondes.

    Avez vous une idée du problème?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    Bonjour,
    Le schéma de ta base me laisse perplexe, mais passons.
    Je vois plusieurs problèmes dans ta requête: pour chaque ligne de "su" peut très bien se retrouver dans une des jointures.
    C'est à dire qu'une ligne avec "su.domaine_id = 1 AND su.section_id = 2" peut très bien être jointe avec elle même, vu qu'elle n'est pas filtré dans les jointures.
    Si sa colonne language_id = 1, elle se retrouve dans sufr, si language_id = 2 elle se retrouve dans suen.
    Donc chaque ligne est jointe au moins une fois avec elle-même.

    Enfin ton critère de regroupement n'est pas correct (même si MySql laisse passer), il n'y a aucune fonction d'agrégation, et su.item_id apparaît pas dans la clause Select.

    Bref il y a pas mal de chose à revoir.

    Tatayo.

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par tatayo Voir le message
    Bonjour,
    Le schéma de ta base me laisse perplexe, mais passons.
    Perplexe ???? Tu veut dire merdique ! C'est les bases hiérarchique que l'on faisait avec le cobol dans les années 60. Donc des performances de merde de façon naturelle sans se forcer.....

    Extrait du livre sur SQL que je suis en train d'écrire :
    Nom : Le langage SQL Brouard Soutou Papillon Gaillard.jpg
Affichages : 200
Taille : 324,2 Ko

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    @Tatayo
    Au départ je voulais faire 2 select (français/anglais), les fusionner puis extraire les resultats a l'aide de:
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT ....  
    FROM
    (
    ) UNION (
    )

    et je me suis dis que ça allait ramer et qu'avec des jointures ça fonctionnerai mieux mais apparemment je m'y prends mal.

    Je comprends ta réponse sur le fond mais pas dans le détail.

    Je ne connais pas les fonctions d’agrégation et je ne vois pas nom plus comment changer le critère de regroupement.

    Je pensais plus que c'était un problème d'indexation.


    @SQLpro
    les 2 premières tables ne sont pas utilisées dans la requête et je ne vois pas le problème qu'il pourrait y avoir avec (je les ai mis ici pour vous aider a mieux comprendre la structure).

    Pour la table site_urls, je suis d'accord qu'il y a un problème avec la clé primaire qui ne devrait contenir que 2 colonnes:
    -numéro article du site
    -langage_id

    il me faudrai alors des tables intermediaires ou de liaison pour definir ce numéro d'article unique.
    sachant que une page à 4 numéros pour l'identifier

    -domaine (1 ou 2 pour le moment)
    -section (1 à 10? dans le domaine)
    -article (1 à xxxxx dans la section elle même dans un domaine)
    -langage (1 à 2 pour le moment)


    Cette table sert a répertorier les urls et non pas a définir les urls du site, je ne peux donc pas simplifier en ne donnant qu'un numéro d'article global.
    Je dois partir des 4 colonnes ci dessus pour creer ce numéro de page globale et je dois ensuite pouvoir filtrer parmi cette liste d'url pour selectionner une section d'un domaine.

    Ces tables me servent à generer des fichiers sitemap
    et aussi à trouver/definir l'url de redirection lorsque je change de langage sur le site.

    @tous
    pouvez vous me donner un indice comme par exemple le nombre de tables nécessaires pour organiser ces données de façon a pouvoir les sortir par la suite par section et par langage dans des bonnes conditions?

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    bon j'ai réécrit la requête pour limiter le nombre de données a traiter:
    Code mysql : 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
     
    SELECT sufr.url fr, suen.url en, su.modified
    FROM site_urls su
    LEFT JOIN (
        SELECT domaine_id, section_id, item_id, url 
        FROM site_urls
        WHERE domaine_id = 1 AND section_id = 2 AND language_id = 1
    ) sufr ON sufr.domaine_id = su.domaine_id AND sufr.section_id = su.section_id AND sufr.item_id = su.item_id
    LEFT JOIN (
        SELECT domaine_id, section_id, item_id, url 
        FROM site_urls
        WHERE domaine_id = 1 AND section_id = 2 AND language_id = 2
    ) suen ON suen.domaine_id = su.domaine_id AND suen.section_id = su.section_id AND suen.item_id = su.item_id
    WHERE su.domaine_id = 1 AND su.section_id = 2 
    GROUP BY su.item_id
    ORDER BY su.modified DESC

    j'arrive a un résultat en 0.06s (5000 lignes)

    On peut dire que ça fonctionne.

    Malgré tout, vu les critiques je reste ouvert aux propositions pour m'aider a améliorer mon organisation des données et/ou une correction de la requête.

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sylvercis Voir le message
    bon j'ai réécrit la requête pour limiter le nombre de données a traiter:
    ...
    j'arrive a un résultat en 0.06s (5000 lignes)

    On peut dire que ça fonctionne.

    Malgré tout, vu les critiques je reste ouvert aux propositions pour m'aider a améliorer mon organisation des données et/ou une correction de la requête.
    Pour faire un test censé il faut une certaine volumétrie.... Si la volumétrie est trop faible tout se passe en mémoire et les performances apparaissent correctes.... Personnellement j'estime que les données de la base devrait faire au strict minium 3 fois la taille de la RAM...

    Extrait de mon nouveau livre à paraître sur SQL :
    Nom : Ecueil des développeur n°4 - Le langage SQL.jpg
Affichages : 163
Taille : 249,6 Ko

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    Merci pour l'info, c'est bon a savoir.

    Ma requête fonctionne et c'est tout ce que je lui demande pour le moment.
    Maintenant je n'en suis pas fier car je l'ai bricolé pour qu'elle passe sans être sur d'utiliser la meilleur méthode.

    J'ai essayé d'utiliser la commande EXPLAIN sur mes requetes mais le resultat reçu ne m'aide pas beaucoup.
    Je pense qu'il faudrai un livre remplis d'exemples d'erreurs et leurs solutions pour bien comprendre cette commande, ou bien d'avoir un diagramme en sortie plutot qu'une simple table.

    Le test en surchargeant la RAM est valable pour comparer la vitesse entre plusieurs requêtes mais pas pour indiquer le bon fonctionnement d'une seule requête.
    L'idéal est déjà de bien écrire la requête et bien structurer la BDD au départ, le test ne sert qu'a valider le tout ou bien a aider a choisir entre plusieurs méthodes possibles.

    Donc a mon avis l'étape avant le test est déjà de passer par EXPLAIN, mais bizarrement je ne vois jamais de sujets résolu en utilisant cette commande.

  8. #8
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    EXPLAIN permet d'afficher le plan d'exécution, c'est à dire ce que le SGBD va créer comme programme informatique pour traiter les données afin de vous restituer un résultat. Le code SQL que vous avez écrit n'est pas un code exécuté. Ce n'est pas un code impératif mais plus exactement un code indicatif. Il indique ce que vous voulez obtenir comme résultat et non comment y parvenir....
    En revanche le plan d'exécution fournit pas EXPLAIN, montre comment le SGBD va parvenir à vous fournir un résultat...

    Maintenant il faut savoir lire un plan de requête pour en tirer quelques avantages afin d'optimiser le fonctionnement de la base. Mais dans MySQmerde, les moyens sont plus que limité, là ou dans d'autres SGBDR (par exemple SQL Server) il vous fournit les moyens d'optimiser en vous conseillant les index à poser...

    Exemples :

    Nom : SQL Server - requête et plan d'exécution - diagnostic d'indexation (SSMS).jpg
Affichages : 204
Taille : 113,4 Ko

    Avec SQL Server management Studio

    La même requête avec Sentry Plan Explorer :

    Nom : SQL Server - requête et plan d'exécution - diagnostic d'indexation (SENTRY plan explorer).jpg
Affichages : 178
Taille : 113,4 Ko

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    Effectivement, c'est bien plus complet que le résultat fourni par mysql.
    Malheureusement ce n'est pas accessible sur les hébergements d'entrée de gamme.

  10. #10
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    Si... Vous avez la version Web, dédiée aux sites web, qui est en mode locatif. On trouve des hébergements à partir de 23 € par mois, comme chez OVH :
    https://www.ovh.com/fr/serveurs_dedi...sql_server.xml

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    Ok, j'avais cherché en tout inclus et pas juste un hebergement SGBD.
    C'est juste une licence a ce prix là?
    Faut il en plus payer la location d'un serveur dédié?

    Pour le moment le site ne nous rapporte rien et il tourne correctement avec l'hebergement actuellement utilisé.
    Mais je note quand même le conseil de nous tourner vers une SGBD sur un serveur dédié avec SQL Server lorsque nous aurons le budget et surtout le besoin.

  12. #12
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 768
    Points : 52 565
    Points
    52 565
    Billets dans le blog
    5
    Par défaut
    Non, c'est tout compris :
    serveur virtuel système + SQL Server éditions web.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

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

Discussions similaires

  1. Requête avec jointure
    Par Maglight dans le forum Langage SQL
    Réponses: 4
    Dernier message: 17/11/2005, 09h57
  2. optimisation d'une requête avec jointure
    Par champijulie dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 07/07/2005, 09h45
  3. Requête avec jointures
    Par Corben dans le forum Langage SQL
    Réponses: 4
    Dernier message: 16/11/2004, 12h55
  4. Mise à jour de table impossible après requête avec jointure
    Par sto dans le forum Bases de données
    Réponses: 5
    Dernier message: 17/03/2004, 13h24
  5. problème de requête avec jointures
    Par tinhat dans le forum Requêtes
    Réponses: 7
    Dernier message: 11/08/2003, 10h33

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