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 et sous-requête complexes - limites de MySQL


Sujet :

Requêtes MySQL

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 16
    Points : 17
    Points
    17
    Par défaut Requête et sous-requête complexes - limites de MySQL
    Bonjour à tous,

    Voila j'ai à des requêtes assez lourdes avec des jointures dans tous les sens et lorsque j'essaye de regrouper le resultats de certaines, Mysql est à la traine.

    J'ai essayé en passant par des table temporaire, cela marche mieux mais devient de suite plus fastidieux à gérer.

    exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT DISTINCT tr.idd FROM table_data as tr WHERE tr.idd IN (SELECT DISTINCT tr.idd FROM table_data as tr
    INNER JOIN table_enr as trr ON tr.id_link = trr.id
    INNER JOIN table_data as tz ON tr.idd = tz.idd INNER JOIN table_data as t1 ON tr.idd=t1.idd
    WHERE tz.id_group ='' AND ( ( t1.key_name LIKE 'email%' AND t1.key_name !='' ) ) AND t1.val!=''
    AND trr.profil='1' AND trr.acces='1' AND trr.etat='1' AND trr.id_link='0'
     
    UNION
    SELECT DISTINCT tr.idd FROM table_data as tr
    INNER JOIN table_enr as trr ON tr.id_link = trr.id
    INNER JOIN table_data as tz ON tr.idd = tz.idd INNER JOIN table_data as t1 ON tr.idd=t1.idd
    WHERE tz.id_group !='' AND ( ( t1.key_name LIKE 'mobile%' AND t1.key_name !='' ) ) AND t1.val!=''
    AND trr.profil='1' AND trr.acces='1' AND trr.etat='1' AND trr.id_link='0'
    )
    Peut prendre 1 minute pour me remonter 34000 resultats

    alors que :


    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
    Create temporary table eee 
     
    SELECT DISTINCT (tr.idd) FROM table_data as tr
    INNER JOIN table_enr as trr ON tr.id_link = trr.id
    INNER JOIN table_data as tz ON tr.idd = tz.idd INNER JOIN table_data as t1 ON tr.idd=t1.idd
    WHERE tz.id_group = '' AND ( ( t1.key_name LIKE 'email%' AND t1.key_name !='' ) ) AND t1.val!=''
    AND trr.profil='1' AND trr.acces='1' AND trr.etat='1' AND trr.id_link='0';
     
    Create temporary table ddd 
    SELECT DISTINCT (tr.idd) FROM table_data as tr
    INNER JOIN table_enr as trr ON tr.id_link = trr.id
    INNER JOIN table_data as tz ON tr.idd = tz.idd INNER JOIN table_data as t1 ON tr.idd=t1.idd
    WHERE tz.id_group != '' AND ( ( t1.key_name LIKE 'mobile%' AND t1.key_name !='' ) ) AND t1.val!=''
    AND trr.profil='1' AND trr.acces='1' AND trr.etat='1' AND trr.id_link='0';
     
     
    SELECT idd from eee UNION select idd from ddd;
    Ne va me prendre à peine 2 secondes, avec le même résultat

    Et ça c'est pour le rapprochement de deux sous-requetes, il risque d'en y avoir bien plus...

    Donc avez-vous déjà rencontré ce genre de soucis, pour qu'elle solution avez vous optés ? Changer de SGDB ? passage obligatoire de table temporaire ? Arrêter de travailler

    Merci d'avance pour votre aide,

    FlashPapa

  2. #2
    Modérateur
    Avatar de Bisûnûrs
    Profil pro
    Développeur Web
    Inscrit en
    Janvier 2004
    Messages
    9 868
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Janvier 2004
    Messages : 9 868
    Points : 16 258
    Points
    16 258
    Par défaut
    Tu peux lire ce cours de SQLPro pour apprendre à optimiser tes requêtes :
    http://sqlpro.developpez.com/cours/optimiser/#L9

    De plus, fais un EXPLAIN de ta requête pour avoir plus d'informations (y a-t-il des index ? sont-ils utilisés ? etc.)

    MySQL n'est souvent pas la raison de la lourdeur d'une requête.

  3. #3
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Citation Envoyé par flashguitou Voir le message
    pour qu'elle solution avez vous optés ?
    La première chose à faire est de réécrire proprement la requête :

    Vos DISTINCT sont redondants avec votre UNION, qui dédoublonne pas défaut (à l'inverse de UNION ALL)

    Pour le reste, il faudrait la structure des tables mais à mon avis :

    1/ vous pourriez vous passer de cet UNION en réduisant vos deux requêtes en une seule.
    2/ vous pourriez vous passer des vos multiples (et couteuses) auto-jointure sur la table table_data

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 16
    Points : 17
    Points
    17
    Par défaut
    Merci pour votre aide, j'essaye d'appliquer tous vos conseils.

    Pour être plus précis je vais vous donner plus de détails.

    En fait j'ai 3 tables :
    • table_enr : table qui identifie un contact de manière unique, avec date de creation, modification,...
    • table_data : table qui porte toutes les valeurs des contacts de la table_enr
    • table_liaison_communication : table des règles d'utilisation des canaux de communication de chaque contact


    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
    CREATE TABLE `table_enr` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `id_link` int(11) unsigned NOT NULL DEFAULT '0',
      `profil` int(1) NOT NULL DEFAULT '0',
      `form` int(11) NOT NULL DEFAULT '0',
      `import` int(11) NOT NULL DEFAULT '0',
      `etat` int(1) NOT NULL DEFAULT '0',
      `etat_bdd` int(11) NOT NULL DEFAULT '0',
      `acces` int(1) NOT NULL DEFAULT '0',
      `actived` int(1) NOT NULL DEFAULT '0',
      `date_crea` datetime NOT NULL,
      `date_mod` datetime NOT NULL,
      `erreur` int(1) NOT NULL,
      `doublon` int(11) NOT NULL,
      `match_code` varchar(24) NOT NULL,
      `ref_track` varchar(30) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `etat` (`etat`),
      KEY `erreur` (`erreur`),
      KEY `date_crea` (`date_crea`),
      KEY `date_mod` (`date_mod`),
      KEY `doublon` (`doublon`),
      KEY `profil` (`profil`),
      KEY `form` (`form`),
      KEY `id_link` (`id_link`),
      KEY `acces` (`acces`),
      KEY `etat_bdd` (`etat_bdd`),
      KEY `actived` (`actived`),
      KEY `import` (`import`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=96678 ;
    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
    CREATE TABLE `table_data` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `id_link` int(11) NOT NULL DEFAULT '0',
      `id_group` char(10) NOT NULL,
      `key_name` char(30) NOT NULL,
      `key_genre` int(1) NOT NULL,
      `val` char(150) NOT NULL,
      `type_val` int(1) NOT NULL DEFAULT '0',
      `idd` int(11) unsigned NOT NULL,
      PRIMARY KEY (`id`),
      KEY `id_link` (`id_link`),
      KEY `key_genre` (`key_genre`),
      KEY `type_val` (`type_val`),
      KEY `idd` (`idd`),
      KEY `val` (`val`),
      KEY `key_name` (`key_name`),
      KEY `id_group` (`id_group`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=971810 ;
    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
    CREATE TABLE `table_liaison_communication` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `id_link` int(11) NOT NULL,
      `key_name` char(30) NOT NULL,
      `pro` int(1) NOT NULL,
      `utilisable` int(1) NOT NULL DEFAULT '0',
      `principal` int(1) NOT NULL DEFAULT '0',
      `liste_rouge` int(1) NOT NULL DEFAULT '0',
      `cession` int(1) NOT NULL DEFAULT '0',
      `erreur` int(1) NOT NULL DEFAULT '0',
      `code_erreur` char(20) NOT NULL,
      `utilisable_defaut` int(1) NOT NULL DEFAULT '0',
      `principal_defaut` int(1) NOT NULL DEFAULT '0',
      `liste_rouge_defaut` int(1) NOT NULL DEFAULT '0',
      `cession_defaut` int(1) NOT NULL DEFAULT '0',
      `erreur_defaut` int(1) NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`),
      KEY `principal` (`principal`),
      KEY `liste_rouge` (`liste_rouge`),
      KEY `erreur` (`erreur`),
      KEY `cession` (`cession`),
      KEY `utilisable` (`utilisable`),
      KEY `id_link` (`id_link`),
      KEY `principal_defaut` (`principal_defaut`),
      KEY `utilisable_defaut` (`utilisable_defaut`),
      KEY `liste_rouge_defaut` (`liste_rouge_defaut`),
      KEY `cession_defaut` (`cession_defaut`),
      KEY `erreur_defaut` (`erreur_defaut`),
      KEY `code_erreur` (`code_erreur`),
      KEY `key_name` (`key_name`),
      KEY `pro` (`pro`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=146969 ;

    Pour le contact id = 85626 (dans la table_enr) j'ai les datas suivantes (les données que j'ai sur le contact) dans la table_data:

    Nom : 127.0.0.1---localhost---arc_earc_b1---table_data---phpMyAdmin-3.5.5.png
Affichages : 289
Taille : 437,8 Ko

    Sachant que les nom, prénom, date de naissance sont stockés dans 3 autres tables plus sujettes à des requêtes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE `table_index_nom` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `id_link` int(11) NOT NULL DEFAULT '0',
      `val` varchar(150) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `id_link` (`id_link`),
      KEY `val` (`val`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=80924 ;
    Pour les canaux de communication de cette personne les règles sont stockées dans la table_liaison_communication :

    Nom : 127.0.0.1---localhost---arc_earc_b1---table_liaison_communication---phpMyAdmin-3.5.5.png
Affichages : 208
Taille : 76,2 Ko


    La suite à suivre...

  5. #5
    Membre averti
    Avatar de diablo-dz
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2014
    Messages
    75
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2014
    Messages : 75
    Points : 327
    Points
    327
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,



    Pour le reste, il faudrait la structure des tables mais à mon avis :

    1/ vous pourriez vous passer de cet UNION en réduisant vos deux requêtes en une seule.
    2/ vous pourriez vous passer des vos multiples (et couteuses) auto-jointure sur la table table_data
    En plus de ça tu peux nous dire le résultat que vous désirer d'avoir
    Merci
    A+
    Si une réponse vous a permis d'avancer , n'oublie pas de mettre
    Ne pas oublier

Discussions similaires

  1. Requête et sous requête
    Par 501darts dans le forum Développement
    Réponses: 1
    Dernier message: 21/02/2008, 10h53
  2. intégré une sous requête dans une requête
    Par Smix007 dans le forum SQL
    Réponses: 13
    Dernier message: 25/06/2007, 11h45
  3. inclure une sous requête dans une requête
    Par garsflo dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 08/05/2007, 19h12
  4. Requête et sous requête avec SELECT et UPDATE
    Par Véronique75ca dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 29/06/2006, 21h25
  5. Requêtes et sous requêtes
    Par lau2nyce dans le forum Langage SQL
    Réponses: 3
    Dernier message: 23/03/2004, 15h14

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