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 :

Optimisation requête IN (SELECT GROUP BY) [MySQL-5.1]


Sujet :

Requêtes MySQL

  1. #1
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 303
    Points : 1 380
    Points
    1 380
    Par défaut Optimisation requête IN (SELECT GROUP BY)
    Bonjour,

    la requête suivante prend trop de temps (plus d'une nuit) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT DISTINCT vaa.Employe_CodeEmploye, vaa.AffStruct_NomCourt, vaa.AffStruct_Nom, 
    vaa.AffStruct_Type, vaa.AffStruct_ID, vaa.AFFSTRUCT_BRISDEGLACE, 
    vaa.AffStruct_Debut, vaa.AffStruct_Fin 
    FROM vue_aff_actives as vaa
    WHERE vaa.AffStruct_NomCourt 
    In (SELECT DISTINCT AffStruct_NomCourt 
    FROM vue_aff_actives As Tmp 
    where Tmp.AffStruct_Type = vaa.AffStruct_Type And Tmp.Employe_CodeEmploye = vaa.Employe_CodeEmploye
    GROUP BY Tmp.AffStruct_NomCourt, Tmp.AffStruct_Type, Tmp.Employe_CodeEmploye 
    HAVING Count(*)>1 )
    Son explain plan est :
    id * select_type * table type possible_keys key key_len ref rows Extra *
    1 PRIMARY table_emp ALL IDX_ORE_EMPLOYE_ID,IDX_ORE_EMPLOYE_FIN 43035 Using where; Using temporary
    1 PRIMARY table_aff ref IDX_ORA_AFFSTRUCT_NOMCOURT,IDX_ORA_AFFSTRUCT_FIN,IDX_ORA_EMPLOYE_ID,IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE IDX_ORA_EMPLOYE_ID 23 vichus.table_emp.EMPLOYE_ID 22 Using where
    2 DEPENDENT SUBQUERY table_aff range IDX_ORA_AFFSTRUCT_NOMCOURT,IDX_ORA_AFFSTRUCT_FIN,IDX_ORA_AFFSTRUCT_TYPE,IDX_ORA_EMPLOYE_ID,IDX_ORA_EMPLOYE_CODEEMPLOYE,IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE 103 567484 Using where; Using temporary; Using filesort
    2 DEPENDENT SUBQUERY table_emp ref IDX_ORE_EMPLOYE_ID,IDX_ORE_EMPLOYE_FIN IDX_ORE_EMPLOYE_ID 23 vichus.table_aff.EMPLOYE_ID 1 Using where; Distinct
    La vue est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE OR REPLACE VIEW vue_aff_actives AS 
    SELECT table_aff.*
    FROM table_aff INNER JOIN table_emp ON table_aff.Employe_ID = table_emp.Employe_ID
    WHERE table_aff.AffStruct_NomCourt Is Not Null AND 
    (table_aff.AffStruct_Fin Is Null Or table_aff.AffStruct_Fin > Now()) AND 
    (table_emp.Employe_Fin Is Null Or table_emp.Employe_Fin > Now());
    La sous-requête en précisant les variables prend 42 secondes et donne 9500 résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT DISTINCT AffStruct_NomCourt, AffStruct_Type, Employe_CodeEmploye
    FROM vue_aff_actives As Tmp 
    where Tmp.AffStruct_Type = 'Unité XXX' And Tmp.Employe_CodeEmploye = '1111111'
    GROUP BY Tmp.AffStruct_NomCourt, Tmp.AffStruct_Type, Tmp.Employe_CodeEmploye 
    HAVING Count(*)>1
    Et la requête en précisant les variables dans le WHERE prend 2 minutes 14, ce qui même en ne multipliant que par 1000 (au lieu de 9500) est beaucoup trop.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ... and vaa.AffStruct_Type = 'Unité XXX'
    and vaa.Employe_CodeEmploye = '1111111';
    La table principale est comme ci-dessous :
    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
    create table table_aff(
    	AFFSTRUCT_ID int,
    	AFFSTRUCT_NOMCOURT varchar(100),
    	AFFSTRUCT_NOM varchar(100),
    	AFFSTRUCT_BRISDEGLACE varchar(100),
    	AFFSTRUCT_DEBUT datetime,
    	AFFSTRUCT_FIN datetime,
    	AFFSTRUCT_TYPE varchar(100),
    	EMPLOYE_ID varchar(20),
    	EMPLOYE_CODEEMPLOYE varchar(100),
    	ORA_ID int not null auto_increment,
    	primary key(ORA_ID),
    	KEY IDX_ORA_AFFSTRUCT_ID (AFFSTRUCT_ID),
    	KEY IDX_ORA_AFFSTRUCT_NOMCOURT (AFFSTRUCT_NOMCOURT),
    	KEY IDX_ORA_AFFSTRUCT_FIN (AFFSTRUCT_FIN),
    	KEY IDX_ORA_AFFSTRUCT_TYPE (AFFSTRUCT_TYPE),
    	KEY IDX_ORA_EMPLOYE_ID (EMPLOYE_ID),
    	KEY IDX_ORA_EMPLOYE_CODEEMPLOYE (EMPLOYE_CODEEMPLOYE),
    	KEY IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE (AFFSTRUCT_NOMCOURT, AFFSTRUCT_TYPE, EMPLOYE_CODEEMPLOYE)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    Avez-vous une idée d'amélioration possible ?
    Christophe

    Pensez à mettre quand c'est le cas.

  2. #2
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    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 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut Christophe P.

    Quelques questions pour mieux comprendre ce que vous essayez de faire.

    1) quel est en nombre de lignes, la volumétrie de la table 'table_aff' ?
    Idem pour la table 'table_emp' ? Et autres si j'ai oublié quelques choses.

    2) j'ai l'impression que vous faites un mauvais usage des view.
    Si vous avez voulu simuler un "with CTE as (...)", ce n'est pas ainsi que l'on procède.
    Il faut décomposer chaque traitement, en stockant le résultat intermédiaire dans une table (temporaire) destinée à cet usage.

    3) au lieu de la vue 'vue_aff_actives', avez-vous essayé de passer par une table temporaire ?
    Je rappelle qu'une vue, ce n'est pas une table et de ce fait, vous créez une couche supplémentaire d'où les mauvaises performances de votre requête.

    4) dans la vue, quel est l'utilité de ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    INNER JOIN table_emp
    ON table_aff.Employe_ID = table_emp.Employe_ID
    5) Il semble que vous n'utilisez pas de 'foreign key', pour indiquer que la table 'table_aff' est fils de la table 'table_aff'.
    Est-ce un oubli ou y a-t-il une raison à cela ? Par exemple des NULL dans la colonne 'Employe_ID' !

    Si chaque ligne de la table 'table_aff' est en relation avec la table 'table_emp' par l'intermédiaire de la colonne 'employe_id', celle-ci est normalement toujours renseignée.
    Il faudrait revoir l'usage fonctionnelle de cette colonne.

    6) dans votre vue, vous testez ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (table_emp.Employe_Fin Is Null Or table_emp.Employe_Fin > Now());
    Que signifie 'employe_fin' ? Est-ce la date à laquelle votre employé n'est plus présent dans votre entreprise.

    7) tester la colonne 'employe_fin' a-t-elle une importance cruciale pour votre requête ?

    8) que donne le rapport entre :
    --> table_emp.Employe_Fin Is Null Or table_emp.Employe_Fin > Now()
    et entre :
    --> table_emp.Employe_Fin <= Now()

    C'est ce rapport qui va décider aussi de la pertinence de faire avant ou après la jointure.
    Et cela risque aussi d'influencer la performance de votre requête.

    9) dans votre requête, vous faites ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    WHERE vaa.AffStruct_NomCourt In (SELECT DISTINCT AffStruct_NomCourt 
    FROM vue_aff_actives As Tmp 
    where Tmp.AffStruct_Type      = vaa.AffStruct_Type
    And   Tmp.Employe_CodeEmploye = vaa.Employe_CodeEmploye
    GROUP BY Tmp.AffStruct_NomCourt, Tmp.AffStruct_Type, Tmp.Employe_CodeEmploye 
    HAVING Count(*)>1 )
    Il serait plus performant de tester l'existence de la valeur de la colonne 'vaa.AffStruct_NomCourt'.
    En fait, vous extrayez une liste de valeur, mais vous en recherchez qu'une seule.

    10) Je ne comprends pas très bien l'intérêt de faire un 'group by' sur trois colonnes, pour ensuite faire un distinct sur une seule colonne ?
    Il faudrait revoir votre sous-requête afin de la rendre plus concise !

    11) Avez-vous tester la pertinence de faire un 'having count(*) > 1' ? Il me semble que dans plus de 99% des cas, le test sera vrai.
    Si vous désirez sélectionner plus de 1 ligne, autrement dit 2 lignes, il serait intéressant d'utiliser 'limit 2'.
    Sans plus d'informations, je ne sais pas si cela est une bonne idée. Il faudrait un jeu d'essai pour se rendre compte de son utilité.
    En traitant moins de lignes, vous pourriez améliorer vos performances.

    12) votre explain n'est pas très lisible, mais il semble qu'aucun index n'ait été utilisé.
    Soit vous faites une mise en forme du résultat de votre explain, soit vous mettez une image.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 303
    Points : 1 380
    Points
    1 380
    Par défaut
    Merci pour votre réponse détaillée et très instructive.
    1) table_aff : 1 300 000 lignes (c'est ma plus grosse table, c'est pourquoi la dupliquer ne me semblait pas une bonne idée)
    table_emp : 40 000 lignes

    2) En fait, j'ai voulu simuler une requête Access. Ce qui explique "l'étrangeté" de la requête (que je suis censé convertir en 10 minutes).
    "
    3) Suite à votre remarque, je viens d'essayer de remplacer la vue par une table temporaire. Il a fallu 8 min 25 s pour faire l'insert. La requete est alors passée de 2 min 14 s à 3 s.
    Je vais lancer un test complet comme ça ce soir. C'est l'équivalent d'un traitement batch, peut aller au niveau temps.

    4) Cela permet de ne pas avoir les employés dont la date de fin est null :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (table_emp.Employe_Fin Is Null Or table_emp.Employe_Fin > Now())
    5) Les données ont potentiellement des problèmes et il est possible que des foreign key n'existe pas. De plus, elles sont extraites de compilations d'autres tables où EMPLOYE_ID peut ne pas être la clé complète. C'est pourquoi je n'en ai pas mis (seulement des indexes).

    6) C'est la date à laquelle son compte est désactivé.

    7) Oui, il faut faire le test sur Employe_Fin.

    8) select count(*) from table_emp where table_emp.Employe_Fin Is Null Or table_emp.Employe_Fin > Now(); : 41 341
    select count(*) from table_emp where table_emp.Employe_Fin <= Now(); : 623

    9) En remplaçant pas "WHERE exists (SELECT 1" je n'obtient pas exactement le même résultat. Il y a une ligne de plus dans mon cas de test (avec un AffStruct_NomCourt différent).

    10) Le GROUP BY associé au HAVING permet de sélectionner les lignes en double.

    11) Il y a 928 094 lignes dans la vue. La sous-requête renvoie 9 578 lignes.

    12) Voici le Explain plan plus lisible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    id  select_type          table        type    possible_keys                               key                                    key_len ref                           rows    Extra
    1   PRIMARY              table_emp    ALL     IDX_ORE_EMPLOYE_ID, IDX_ORE_EMPLOYE_FIN                                                                                  43035   Using where; Using temporary
    1   PRIMARY              table_aff    ref     IDX_ORA_AFFSTRUCT_NOMCOURT,                 IDX_ORA_EMPLOYE_ID                     23      vichus.table_emp.EMPLOYE_ID   22      Using where
                                                  IDX_ORA_AFFSTRUCT_FIN,
                                                  IDX_ORA_EMPLOYE_ID,
                                                  IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE
    2   DEPENDENT SUBQUERY   table_aff    range   IDX_ORA_AFFSTRUCT_NOMCOURT,                 IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE      103                                    567484  Using where; Using temporary; Using filesort
                                                  IDX_ORA_AFFSTRUCT_FIN,
                                                  IDX_ORA_AFFSTRUCT_TYPE,
                                                  IDX_ORA_EMPLOYE_ID,
                                                  IDX_ORA_EMPLOYE_CODEEMPLOYE,
                                                  IDX_ORA_NOMCOURT_TYPE_CODEEMPLOYE
    2   DEPENDENT SUBQUERY   table_emp    ref     IDX_ORE_EMPLOYE_ID,IDX_ORE_EMPLOYE_FIN      IDX_ORE_EMPLOYE_ID                     23       vichus.table_aff.EMPLOYE_ID   1       Using where; Distinct
    Christophe

    Pensez à mettre quand c'est le cas.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 303
    Points : 1 380
    Points
    1 380
    Par défaut
    J'ai arrêté ce matin la requête utilisant la table temporaire. Je l'avais lancé hier soir, elle a tourné toute la nuit et n'était toujours pas finie.
    Christophe

    Pensez à mettre quand c'est le cas.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 303
    Points : 1 380
    Points
    1 380
    Par défaut
    J'ai créé deux tables temporaires (une pour la vue et l'autre pour le having count) et cela semble mieux, je teste ça.

    Édition : la requête est passée en 1 min 23.
    Christophe

    Pensez à mettre quand c'est le cas.

  6. #6
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    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 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut Christophe P.

    Merci pour tes réponses.

    La solution consiste à ne pas passer par une view, comme tu le fais actuellement.
    Une vue sert essentiellement pour des questions de sécurités, ou pour extraire des données dans un select simple, sans jointure.

    Soit tu réécris ta requête en passant directement par la table, soit tu décomposes ton traitement en plusieurs étapes.
    Décompose aussi ta sous-requête (le having) en créant une table temporaire.

    Si tu utilises des tables temporaires, assure toi d'avoir les bons index.
    Je voie que tu as utilisé des index à une seule colonne.
    Et je constate que dans la colonne 'extra' du 'explain', je ne voie aucune référence à un index.

    Tu devrais créer un index contenant :
    --> AffStruct_NomCourt
    --> AffStruct_Type
    --> Employe_CodeEmploye

    Faire un 'exists' est bien plus rapide que de passer par une liste de valeurs.
    J'ai pas bien compris le problème que tu as rencontré avec le exists.

    Citation Envoyé par Christophe P
    J'ai créé deux tables temporaires (une pour la vue et l'autre pour le having count) et cela semble mieux, je teste ça.
    N'oublie pas de vérifier l'usage des index. As-tu créer une jointure entre tes deux tables temporaires ?
    Tu veux faire cela dans une view.

    Citation Envoyé par Christophe P
    Édition : la requête est passée en 1 min 23.
    Es-tu certain d'avoir le résultat attendu ?

    Est-ce ton premier résultat car si j'ai bien compris, tu n'avais aucun résultat précédemment car tu tuais ta requête au matin.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  7. #7
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 303
    Points : 1 380
    Points
    1 380
    Par défaut
    Le résultat de mon mini-test (sur une personne) correspond. Je suis en train de vérifier le tout (la requête fait parti d'un ensemble).
    Merci pour les conseils, je vais vérifier les indexes.
    Christophe

    Pensez à mettre quand c'est le cas.

  8. #8
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    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 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut Christophe P.

    C'est très long, un test d'optimisation !
    Il ne s'agit pas juste d'ajouter des index ou de découper une requête en morceaux.
    Il faut faire de multiples essais afin de trouver le juste milieu selon différents paramétrages de la requête.
    Pour un paramétrage, tu peux obtenir un bon temps d'exécution, et pour un autre paramétrage obtenir un temps désastreux.

    La plupart du temps, on se contente d'un temps acceptable.
    Les points cruciaux sont :
    --> l'usage des index par l'explain
    --> l'ordre d'exécution des jointures
    --> les clauses where quand ceux-ci n'utilisent plus les index.
    --> les sous-requêtes qui peuvent être remplacées par des jointures.
    --> de-normaliser la base de données pour obtenir de meilleur performance.
    --> usage des procédure stockée.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  9. #9
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 303
    Points : 1 380
    Points
    1 380
    Par défaut
    Qu'est-ce que "dé-normaliser la base" ?
    Le principale problème de ce projet est que je n'ai que 10 minutes par requête...
    Christophe

    Pensez à mettre quand c'est le cas.

  10. #10
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 346
    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 346
    Points : 18 958
    Points
    18 958
    Par défaut
    Salut Christophe P.

    Citation Envoyé par Christophe P.
    Qu'est-ce que "dé-normaliser la base" ?
    Tu fais un accès à la table "table_emp", uniquement pour tester la colonne "table_emp.Employe".
    Une dé-normalisation consisterait à introduire cette colonne dans la table "table_aff".
    Elle serait gérée par un trigger de façon transparente.
    Quand tu vient modifier cette colonne dans la "table_emp", sa modification serait répercutée automatiquement dans la table "table_aff".
    Cela se justifie que si tu gagnes en performance.

    C'est la sous-requête qui pose un problème de performance. Dans ton cas, ce n'est pas justifié.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

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

Discussions similaires

  1. Requête 3 tables - group by - select multi critères
    Par julienleg dans le forum Requêtes
    Réponses: 3
    Dernier message: 16/06/2010, 12h04
  2. Optimisation requête SELECT - IN clause
    Par L'horla dans le forum Requêtes
    Réponses: 0
    Dernier message: 04/05/2010, 16h54
  3. [Optimisation] Requête SELECT conséquente
    Par hobotalker dans le forum SQL
    Réponses: 2
    Dernier message: 29/10/2009, 12h29
  4. [MySQL] Optimisation requête SELECT
    Par GyZmoO dans le forum Requêtes
    Réponses: 3
    Dernier message: 22/10/2009, 18h24
  5. [MySQL] Optimisation requête avec SELECT COUNT
    Par przvl dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 15/10/2008, 16h27

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