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 :

GROUP BY suivit d'un ORDER BY ne fait pas bon ménage


Sujet :

Requêtes MySQL

  1. #21
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 18
    Points : 39
    Points
    39
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Il y a une petite erreur dans votre requête.
    Dans la sous-requête corrélée, vous avez mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND c.country = 'TG')
    Or il ne faut pas mettre "c.country" mais "ic.country".
    Merci d'avoir relevé la coquille, il s'avère que c'était simplement une erreur de copié/collé.

    Première remarque : à verifier.
    Quand vous faites un where 'c.nbVisits = (SELECT MAX(ic.nbVisits)', vous sélectionnez la ligne contenant la plus haute valeur maximale de la colonne nbVisits.
    Si vous utilisez plusieurs critères qui sont les mêmes dans la sous-requête et la requête, il y a sûrement une simplification à faire.

    La question que je me pose est celle à quoi se rapporte le nombre de visiteurs, puisque nous recherchons la plus haute valeur.
    Autrement dit, pour un même 'name', avons-nous toujours :
    --> online = 1
    --> valid = 1
    --> category_id = 175
    --> country = 'TG'.
    ou bien, il peut y avoir plusieurs valeurs possibles.

    Si la réponse est OUI, c'est-à-dire que les critères sont toujours identiques pour un name alors vous pouvez les supprimer car ils font un double emploi.

    Oui mais Lesquelles seront conservés ?
    Je pense que ce sont ceux de la sous-requête qu'il faut conserver. Et comme je le dis ci-dessus, c'est à vérifier.

    Inversement, si la réponse est NON, il ne faut pas changer votre requête.

    Ce n'est que du détail mais cela permet d'alléger la requête en lisibilité.
    Effectivement le where sur la sous requête est obligatoire, car plusieurs société ayant le même nom peuvent être dans des catégories différentes, et/ou des pays différents, et moi je ne souhaite récupérer le maximum seulement d'un couple (pays, category).

    Deuxième remarque :
    L'index qui se nomme 'IDX_4FBF094F12469DE25373C96662C0E8F9E32BEEA8C0735FF5E237E062D5B' n'a pas été utilisé dans la performance de la requête.
    Je pense que l'index que vous avez créé est inapproprié à votre requête.
    Cet index est utiliser par une autre requête. Je vous est lister tous les index que la table possèdes. Mais c'est vrai que cet index n'est pas utiliser pour cet exemple, mais je ne peux le supprimer, car il est utiliser pour une autre requête.

    Pour l'index, il y a deux points à traiter, soit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND c.country = 'TG')
    et soit:
    Votre index se fait sur les colonnes : category_id, country, isClient, online, valid, name, city.
    Je ne voie nulle part dans votre requête la colonne isClient ?

    Sous toute réserve, je propose de faire l'index suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    alter table company add index `idx_perf` (`name`,`online`,`valid`,`category_id`,`country`, `id`, `nbVisits`);
    Je viens donc d'ajouter cet index "idx_perf" sur la table. Mais cela ne change quasiment rien au perf de la requête.

    En ce que concerne les tests, je ferrai ceci :
    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
    explain SELECT SQL_NO_CACHE id, name, nbVisits
    FROM company c
    WHERE nbVisits = (SELECT MAX(ic.nbVisits)
               FROM company ic
               WHERE ic.name        = c.name
    		   AND   ic.online      = 1
    		   AND   ic.valid       = 1
    		   AND   ic.category_id IN (175)
    		   AND   ic.country     = 'TG')
    AND category_id IN (175) 
    AND online      = 1 
    AND valid       = 1 
    AND country     = 'TG'
    ORDER BY nbVisits DESC 
    LIMIT 5;
     
    set profiling=1;
    SELECT SQL_NO_CACHE SELECT SQL_NO_CACHE id, name, nbVisits
    FROM company c
    WHERE nbVisits = (SELECT MAX(ic.nbVisits)
               FROM company ic
               WHERE ic.name        = c.name
    		   AND   ic.online      = 1
    		   AND   ic.valid       = 1
    		   AND   ic.category_id IN (175)
    		   AND   ic.country     = 'TG')
    AND category_id IN (175) 
    AND online      = 1 
    AND valid       = 1 
    AND country     = 'TG'
    ORDER BY nbVisits DESC 
    LIMIT 5;
     
    SHOW PROFILES;
    SHOW PROFILE CPU FOR QUERY 1;
    set profiling=0;
    En mettant 'sql_no_cache', la requête ne sera pas stockée dans les buffers du serveur MySql.
    Il y a juste un léger problème, le temps d'exécution est juste approximatif.
    Ce qui est bizarre dans son fonctionnement, c'est que vous n'obtenez jamais le même résultat.
    On peut s'en servir comme ordre de grandeur.

    Que ce soit la solution de StringBuilder ou la mienne, les temps d'exécution sont assez semblables. La volumétrie que vous avez, 80574 lignes, n'est pas énorme.
    Les temps d'exécutions sont peu significatives pour départager les deux solutions proposées.

    @+
    Sur phpmyadmin quand on coche "profilage" à l'execution d'une requete il fait a peu près ça. J'ai donc ajouter le SQL_NO_CACHE aux requetes, mais cela ne change pas l'ordre de grandeur du résultats. La requête de StringBuilder est toujours à peu près 9 fois plus rapide.

    Cordialement.

  2. #22
    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 381
    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 381
    Points : 19 066
    Points
    19 066
    Par défaut
    Salut à tous.

    Citation Envoyé par jojolebg
    Effectivement le where sur la sous requête est obligatoire, car plusieurs société ayant le même nom peuvent être dans des catégories différentes, et/ou des pays différents, et moi je ne souhaite récupérer le maximum seulement d'un couple (pays, category).
    Merci pour la précision. Donc on ne peut pas simplifier votre requête.

    Citation Envoyé par jojolebg
    Cet index est utiliser par une autre requête. Je vous est lister tous les index que la table possèdes. Mais c'est vrai que cet index n'est pas utiliser pour cet exemple, mais je ne peux le supprimer, car il est utiliser pour une autre requête.
    Je croyais que cet index avait été créé spécialement pour votre requête.

    Citation Envoyé par jojolebg
    Je viens donc d'ajouter cet index "idx_perf" sur la table. Mais cela ne change quasiment rien au perf de la requête.
    Désolé mais je ne peux rien faire de plus.

    Citation Envoyé par jojolebg
    Sur phpmyadmin quand on coche "profilage" à l'exécution d'une requête il fait a peu près ça.
    Je n'utilise pratiquement pas phpMyAdmin. Je fais tous mes tests en lignes de commandes.

    Pour l'astuce que je vous ai donné, on a ainsi un ordre de grandeur de la performance de la requête.
    Sinon, il y a une autre façon de tester une requête. Sous MySql, il existe un utilitaire qui permet de lancer un nombre de fois votre requête et d'obtenir la moyenne du temps d'exécution.
    Cet utilitaire se nomme 'mysqlslap'. Sur mon mini jeu d'essai, j'ai testé la requête et j'obtiens comme vous, un meilleur résultat pour la solution de StringBuilder.

    Citation Envoyé par jojolebg
    J'ai donc ajouter le SQL_NO_CACHE aux requêtes, mais cela ne change pas l'ordre de grandeur du résultats.
    C'est juste pour dire à MySql de ne pas utiliser les buffers pour stocker le résultat de la requête.

    Citation Envoyé par jojolebg
    La requête de StringBuilder est toujours à peu près 9 fois plus rapide.
    Impressionnant comme résultat.

    J'ai fait une analyse de la comparaison entre la solution de StringBuilder et ma solution.
    En vérifiant le résultat de la variable 'handler_read_next' pour chacune des solutions, je constate que si N est le nombre de lignes dans la table, on obtiens en tant que lecture :
    --> 3 * N lectures pour la solution de StringBuilder.
    --> 5 * N lectures pour ma solution.
    C'est assez déconcertant d'obtenir ce genre de résultat. Quel est l'utilité de faire 3 ou 5 passages sur la table pour produire le résultat attendu ?
    Je trouve que c'est du grand n'importe quoi l'optimisation de MySql.

    Inversement, dans nos deux requêtes, nous faisons un tri. Le nombre de lignes traiter pour le tri est de :
    --> N lignes pour la solution de StringBuilder, c'est-à-dire la totalité de la table.
    --> un nombre beaucoup plus petit pour ma solution. En fait, le nombre que j'obtiens est celui du nombre de lignes à l'affichage des résultats.

    La différence des résultats entre les deux requêtes se fait essentiellement sur 'handler_read_next', c'est-à-dire le nombre de lectures.
    J'espère que votre problème est résolu.

    Citation Envoyé par StringBuilder
    Au final, y'a toujours "36 solutions pour arriver au même résultat en SQL, et y'a pas deux solutions qui ont des performances comparables d'un SGBD à l'autre" (j'aurais presque envie de rajouter "surtout quand on compare MySQL à des SGBD haut de gamme"
    Je suis entièrement de votre avis.

    Je retiendrais qu'une sous-requête corrélée sous MySql est d'une performance très dégradée, à l'inverse des SGBD de haut de gamme.
    Je le savais déjà en ce qui concerne une sous-requête non corrélée, mais je ne m'attendais pas à ce résultat aussi décevant.

    En tout cas, la discussion a été enrichissante car on ne peut rien prévoir à l'avance sur les performance d'une requête.

    Sinon StringBuilder, j'aimerai savoir comment vous testez la performance d'une requête ?
    Désolé si j'ai été un peu trop brusque. Je vous présente mes excuses !

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

  3. #23
    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 381
    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 381
    Points : 19 066
    Points
    19 066
    Par défaut
    Salut jojolebg.

    J'ai bien reçu vos messages et j'ai installé la table 'company_md5'. Il y a 76406 lignes dans votre tables et ce n'est pas énorme.
    Je constate que votre table contient ni 'primary key', ni index. Est-ce un oubli ?

    Du coup, j'ai fait une comparaison entre ma requête et celle de 'StringBuilder' sans les index. Et voici le résultat de ce test :
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    --------------
    describe company_md5
    --------------
     
    +-------------+--------------+------+-----+---------+-------+
    | Field       | Type         | Null | Key | Default | Extra |
    +-------------+--------------+------+-----+---------+-------+
    | id          | int(11)      | NO   |     | NULL    |       |
    | category_id | int(11)      | YES  |     | NULL    |       |
    | parent_id   | int(11)      | YES  |     | NULL    |       |
    | name        | varchar(255) | NO   |     | NULL    |       |
    | isClient    | tinyint(1)   | NO   |     | NULL    |       |
    | country     | varchar(80)  | NO   |     | NULL    |       |
    | online      | tinyint(1)   | NO   |     | NULL    |       |
    | nbVisits    | int(11)      | NO   |     | NULL    |       |
    | valid       | tinyint(1)   | NO   |     | NULL    |       |
    +-------------+--------------+------+-----+---------+-------+
    --------------
    ANALYZE TABLE company_md5
    --------------
     
    +-------------------------+---------+----------+----------+
    | Table                   | Op      | Msg_type | Msg_text |
    +-------------------------+---------+----------+----------+
    | goafrica_sf.company_md5 | analyze | status   | OK       |
    +-------------------------+---------+----------+----------+
    --------------
    SHOW TABLE STATUS LIKE '%company_md5%'
    --------------
     
    +-------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
    | Name        | Engine | Version | Row_format | Rows  | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment |
    +-------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
    | company_md5 | InnoDB |      10 | Compact    | 76164 |             89 |     6832128 |               0 |            0 |  12582912 |           NULL | 2015-09-10 18:59:25 | NULL        | NULL       | utf8_unicode_ci |     NULL |                |         |
    +-------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
    --------------
    show index from company_md5
    --------------
     
    --------------
    explain SELECT SQL_NO_CACHE   id,   name,   nbVisits FROM company_md5 c WHERE nbVisits = (SELECT MAX(ic.nbVisits) FROM company_md5 ic WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG') AND                                  category_id IN (175)
     AND   online = 1 AND   valid = 1 AND   country = 'TG'                   ORDER BY   nbVisits DESC LIMIT 5
    --------------
     
    +----+--------------------+-------+------+---------------+------+---------+------+-------+-----------------------------+
    | id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                       |
    +----+--------------------+-------+------+---------------+------+---------+------+-------+-----------------------------+
    |  1 | PRIMARY            | c     | ALL  | NULL          | NULL | NULL    | NULL | 76164 | Using where; Using filesort |
    |  2 | DEPENDENT SUBQUERY | ic    | ALL  | NULL          | NULL | NULL    | NULL | 76164 | Using where                 |
    +----+--------------------+-------+------+---------------+------+---------+------+-------+-----------------------------+
    --------------
    explain SELECT SQL_NO_CACHE c.id, c.name, c.nbVisits FROM company_md5 c                                LEFT OUTER JOIN company_md5 ic    ON ic.name = c.name and ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG'  AND ic.nbVisits > c.nbVisits WHERE c.category_id IN (175)
     AND c.online = 1 AND c.valid = 1 AND c.country = 'TG' AND ic.id IS NULL ORDER BY c.nbVisits DESC limit 5
    --------------
     
    +----+-------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------------------------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                                                          |
    +----+-------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------------------------+
    |  1 | SIMPLE      | c     | ALL  | NULL          | NULL | NULL    | NULL | 76164 | Using where; Using temporary; Using filesort                   |
    |  1 | SIMPLE      | ic    | ALL  | NULL          | NULL | NULL    | NULL | 76164 | Using where; Not exists; Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------------------------+
    --------------
    RESET QUERY CACHE
    --------------
     
    --------------
    set profiling=1
    --------------
     
    --------------
    SELECT SQL_NO_CACHE   id,   name,   nbVisits FROM company_md5 c WHERE nbVisits = (SELECT MAX(ic.nbVisits) FROM company_md5 ic WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG') AND                                  category_id IN (175) AND   o
    nline = 1 AND   valid = 1 AND   country = 'TG'                   ORDER BY   nbVisits DESC LIMIT 5
    --------------
     
    +------+----------------------------------+----------+
    | id   | name                             | nbVisits |
    +------+----------------------------------+----------+
    | 7810 | 1fb55954013c8267149ea1ddd6c9fab7 |    11876 |
    |   71 | c0ef41c26ea24a4eed4fded037057d78 |    11086 |
    | 1429 | fec2d8acd42fcbdfe05c699878e43886 |     7549 |
    |   29 | 4dbe09cc1623e6d2ff7706c3e397cd23 |     6671 |
    |   28 | 5c7f48ee250da615e03cf102e39676c7 |     6605 |
    +------+----------------------------------+----------+
    --------------
    SELECT SQL_NO_CACHE c.id, c.name, c.nbVisits FROM company_md5 c                                LEFT OUTER JOIN company_md5 ic    ON ic.name = c.name and ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG'  AND ic.nbVisits > c.nbVisits WHERE c.category_id IN (175) AND c.o
    nline = 1 AND c.valid = 1 AND c.country = 'TG' AND ic.id IS NULL ORDER BY c.nbVisits DESC limit 5
    --------------
     
    +------+----------------------------------+----------+
    | id   | name                             | nbVisits |
    +------+----------------------------------+----------+
    | 7810 | 1fb55954013c8267149ea1ddd6c9fab7 |    11876 |
    |   71 | c0ef41c26ea24a4eed4fded037057d78 |    11086 |
    | 1429 | fec2d8acd42fcbdfe05c699878e43886 |     7549 |
    |   29 | 4dbe09cc1623e6d2ff7706c3e397cd23 |     6671 |
    |   28 | 5c7f48ee250da615e03cf102e39676c7 |     6605 |
    +------+----------------------------------+----------+
    --------------
    set profiling=0
    --------------
     
    --------------
    SHOW PROFILES
    --------------
     
    +----------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ----------------------------+
    | Query_ID | Duration    | Query
                                |
    +----------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ----------------------------+
    |        1 | 45.34945525 | SELECT SQL_NO_CACHE   id,   name,   nbVisits FROM company_md5 c WHERE nbVisits = (SELECT MAX(ic.nbVisits) FROM company_md5 ic WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG') AND                                  c
    ategory_id IN (175) AND   o |
    |        2 |  0.96298800 | SELECT SQL_NO_CACHE c.id, c.name, c.nbVisits FROM company_md5 c                                LEFT OUTER JOIN company_md5 ic    ON ic.name = c.name and ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG'  AND ic.nbVisits > c.nbVisits WHERE c.c
    ategory_id IN (175) AND c.o |
    +----------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ----------------------------+
     
    Appuyez sur une touche pour continuer...
    La différence d'exécution est énorme :
    --> ma requête dure : 45,34945525 secondes
    --> la requête de stringbuiler dure : 0,96298800
    Oui, mais voilà, il n'y a ni 'primary key' ni index.

    Je crée une 'primary key' sur la colonne 'id' et un index sur les colonnes 'name','online','valid','category_id','country', 'id', 'nbVisits'.
    Et je refais un nouveau test.
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    --------------
    alter table company_md5 drop primary key
    --------------
     
    ERROR 1091 (42000) at line 3: Ne peut effacer (DROP) 'PRIMARY'. Vérifiez s'il existe
    --------------
    alter table company_md5 add  primary key (`id`)
    --------------
     
    --------------
    alter table company_md5 drop index `idx`
    --------------
     
    ERROR 1091 (42000) at line 6: Ne peut effacer (DROP) 'idx'. Vérifiez s'il existe
    --------------
    alter table company_md5 add  index `idx` (`name`,`online`,`valid`,`category_id`,`country`, `id`, `nbVisits`)
    --------------
     
    --------------
    describe company_md5
    --------------
     
    +-------------+--------------+------+-----+---------+-------+
    | Field       | Type         | Null | Key | Default | Extra |
    +-------------+--------------+------+-----+---------+-------+
    | id          | int(11)      | NO   | PRI | NULL    |       |
    | category_id | int(11)      | YES  |     | NULL    |       |
    | parent_id   | int(11)      | YES  |     | NULL    |       |
    | name        | varchar(255) | NO   | MUL | NULL    |       |
    | isClient    | tinyint(1)   | NO   |     | NULL    |       |
    | country     | varchar(80)  | NO   |     | NULL    |       |
    | online      | tinyint(1)   | NO   |     | NULL    |       |
    | nbVisits    | int(11)      | NO   |     | NULL    |       |
    | valid       | tinyint(1)   | NO   |     | NULL    |       |
    +-------------+--------------+------+-----+---------+-------+
    --------------
    ANALYZE TABLE company_md5
    --------------
     
    +-------------------------+---------+----------+----------+
    | Table                   | Op      | Msg_type | Msg_text |
    +-------------------------+---------+----------+----------+
    | goafrica_sf.company_md5 | analyze | status   | OK       |
    +-------------------------+---------+----------+----------+
    --------------
    SHOW TABLE STATUS LIKE '%company_md5%'
    --------------
     
    +-------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
    | Name        | Engine | Version | Row_format | Rows  | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment |
    +-------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
    | company_md5 | InnoDB |      10 | Compact    | 76218 |             89 |     6832128 |               0 |      4734976 |         0 |           NULL | 2015-09-10 19:15:45 | NULL        | NULL       | utf8_unicode_ci |     NULL |                |         |
    +-------------+--------+---------+------------+-------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
    --------------
    show index from company_md5
    --------------
     
    +-------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | Table       | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
    +-------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    | company_md5 |          0 | PRIMARY  |            1 | id          | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    | company_md5 |          1 | idx      |            1 | name        | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    | company_md5 |          1 | idx      |            2 | online      | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    | company_md5 |          1 | idx      |            3 | valid       | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    | company_md5 |          1 | idx      |            4 | category_id | A         |       76218 |     NULL | NULL   | YES  | BTREE      |         |               |
    | company_md5 |          1 | idx      |            5 | country     | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    | company_md5 |          1 | idx      |            6 | id          | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    | company_md5 |          1 | idx      |            7 | nbVisits    | A         |       76218 |     NULL | NULL   |      | BTREE      |         |               |
    +-------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
    --------------
    explain SELECT SQL_NO_CACHE   id,   name,   nbVisits FROM company_md5 c WHERE nbVisits = (SELECT MAX(ic.nbVisits) FROM company_md5 ic WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG') AND                                  category_id IN (175)
     AND   online = 1 AND   valid = 1 AND   country = 'TG'                   ORDER BY   nbVisits DESC LIMIT 5
    --------------
     
    +----+--------------------+-------+-------+---------------+------+---------+--------------------------------------------+-------+------------------------------------------+
    | id | select_type        | table | type  | possible_keys | key  | key_len | ref                                        | rows  | Extra                                    |
    +----+--------------------+-------+-------+---------------+------+---------+--------------------------------------------+-------+------------------------------------------+
    |  1 | PRIMARY            | c     | index | NULL          | idx  | 1024    | NULL                                       | 76218 | Using where; Using index; Using filesort |
    |  2 | DEPENDENT SUBQUERY | ic    | ref   | idx           | idx  | 1016    | goafrica_sf.c.name,const,const,const,const |     1 | Using where; Using index                 |
    +----+--------------------+-------+-------+---------------+------+---------+--------------------------------------------+-------+------------------------------------------+
    --------------
    explain SELECT SQL_NO_CACHE c.id, c.name, c.nbVisits FROM company_md5 c                                LEFT OUTER JOIN company_md5 ic    ON ic.name = c.name and ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG'  AND ic.nbVisits > c.nbVisits WHERE c.category_id IN (175)
     AND c.online = 1 AND c.valid = 1 AND c.country = 'TG' AND ic.id IS NULL ORDER BY c.nbVisits DESC limit 5
    --------------
     
    +----+-------------+-------+-------+---------------+------+---------+--------------------------------------------+-------+------------------------------------------+
    | id | select_type | table | type  | possible_keys | key  | key_len | ref                                        | rows  | Extra                                    |
    +----+-------------+-------+-------+---------------+------+---------+--------------------------------------------+-------+------------------------------------------+
    |  1 | SIMPLE      | c     | index | NULL          | idx  | 1024    | NULL                                       | 76218 | Using where; Using index; Using filesort |
    |  1 | SIMPLE      | ic    | ref   | idx           | idx  | 1016    | goafrica_sf.c.name,const,const,const,const |     1 | Using where; Not exists; Using index     |
    +----+-------------+-------+-------+---------------+------+---------+--------------------------------------------+-------+------------------------------------------+
    --------------
    RESET QUERY CACHE
    --------------
     
    --------------
    set profiling=1
    --------------
     
    --------------
    SELECT SQL_NO_CACHE   id,   name,   nbVisits FROM company_md5 c WHERE nbVisits = (SELECT MAX(ic.nbVisits) FROM company_md5 ic WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG') AND                                  category_id IN (175) AND   o
    nline = 1 AND   valid = 1 AND   country = 'TG'                   ORDER BY   nbVisits DESC LIMIT 5
    --------------
     
    +------+----------------------------------+----------+
    | id   | name                             | nbVisits |
    +------+----------------------------------+----------+
    | 7810 | 1fb55954013c8267149ea1ddd6c9fab7 |    11876 |
    |   71 | c0ef41c26ea24a4eed4fded037057d78 |    11086 |
    | 1429 | fec2d8acd42fcbdfe05c699878e43886 |     7549 |
    |   29 | 4dbe09cc1623e6d2ff7706c3e397cd23 |     6671 |
    |   28 | 5c7f48ee250da615e03cf102e39676c7 |     6605 |
    +------+----------------------------------+----------+
    --------------
    SELECT SQL_NO_CACHE c.id, c.name, c.nbVisits FROM company_md5 c                                LEFT OUTER JOIN company_md5 ic    ON ic.name = c.name and ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG'  AND ic.nbVisits > c.nbVisits WHERE c.category_id IN (175) AND c.o
    nline = 1 AND c.valid = 1 AND c.country = 'TG' AND ic.id IS NULL ORDER BY c.nbVisits DESC limit 5
    --------------
     
    +------+----------------------------------+----------+
    | id   | name                             | nbVisits |
    +------+----------------------------------+----------+
    | 7810 | 1fb55954013c8267149ea1ddd6c9fab7 |    11876 |
    |   71 | c0ef41c26ea24a4eed4fded037057d78 |    11086 |
    | 1429 | fec2d8acd42fcbdfe05c699878e43886 |     7549 |
    |   29 | 4dbe09cc1623e6d2ff7706c3e397cd23 |     6671 |
    |   28 | 5c7f48ee250da615e03cf102e39676c7 |     6605 |
    +------+----------------------------------+----------+
    --------------
    set profiling=0
    --------------
     
    --------------
    SHOW PROFILES
    --------------
     
    +----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ---------------------------+
    | Query_ID | Duration   | Query
                               |
    +----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ---------------------------+
    |        1 | 0.09293775 | SELECT SQL_NO_CACHE   id,   name,   nbVisits FROM company_md5 c WHERE nbVisits = (SELECT MAX(ic.nbVisits) FROM company_md5 ic WHERE ic.name = c.name AND ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG') AND                                  ca
    tegory_id IN (175) AND   o |
    |        2 | 0.05272950 | SELECT SQL_NO_CACHE c.id, c.name, c.nbVisits FROM company_md5 c                                LEFT OUTER JOIN company_md5 ic    ON ic.name = c.name and ic.online = 1 AND ic.valid = 1 AND ic.category_id IN (175) AND ic.country = 'TG'  AND ic.nbVisits > c.nbVisits WHERE c.ca
    tegory_id IN (175) AND c.o |
    +----------+------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ---------------------------+
     
    Appuyez sur une touche pour continuer...
    Les deux requêtes travaillent sur les mêmes colonnes. Donc l'index que j'ai créé aura une bonne influence sur la performance des deux requêtes.
    --> ma requête dure : 0.09293775 secondes
    --> la requête de stringbuiler dure : 0,05272950
    La plus grosse amélioration reste ma requête avec un rapport de 487,95.
    La requête de stringbuiler produit la meilleur performance, même si l'amélioration donne un rapport de 18,26.

    Le rapport entre les deux performances donne 1,7625 soit presque le double (c'est ma requête qui dure presque deux fois plus longtemps).
    Les deux performances sont faibles, moins de 0,10 seconde. Vu la quantité de lignes, et vu le temps de réponses, c'est presque pareil.
    Mais si la volumétrie augmente grandement, je conseille de choisir la requête de 'StringBuiler'.

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

  4. #24
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 18
    Points : 39
    Points
    39
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Salut jojolebg.
    J'ai bien reçu vos messages et j'ai installé la table 'company_md5'. Il y a 76406 lignes dans votre tables et ce n'est pas énorme.
    Je constate que votre table contient ni 'primary key', ni index. Est-ce un oubli ?
    C'est pas un oublie, c'était fait exprès, pour vous laisser le choix des index à créer.

    Les deux requêtes travaillent sur les mêmes colonnes. Donc l'index que j'ai créé aura une bonne influence sur la performance des deux requêtes.
    --> ma requête dure : 0.09293775 secondes
    --> la requête de stringbuiler dure : 0,05272950
    La plus grosse amélioration reste ma requête avec un rapport de 487,95.
    La requête de stringbuiler produit la meilleur performance, même si l'amélioration donne un rapport de 18,26.

    Le rapport entre les deux performances donne 1,7625 soit presque le double (c'est ma requête qui dure presque deux fois plus longtemps).
    Les deux performances sont faibles, moins de 0,10 seconde. Vu la quantité de lignes, et vu le temps de réponses, c'est presque pareil.
    Mais si la volumétrie augmente grandement, je conseille de choisir la requête de 'StringBuiler'.

    @+
    Sur ma machine et mon vrai jeu de données, j'ai un rapport de 8 à peu près. Mais cela reste, comme dit, une petite performance dans les deux cas.

    Merci en tout cas d'avoir passé du temps à m'aider.

  5. #25
    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 381
    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 381
    Points : 19 066
    Points
    19 066
    Par défaut
    Salut jojolebg.

    Pouvez-vous communiquer le descriptif de votre table company, telle quelle est déclarée en production ?

    Et de même, pouvez-vous me communiquer aussi le fichier 'my.ini" que vous utilisez ?

    Merci.

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

Discussions similaires

  1. group by 2 colonnes et order by une autre colonne
    Par _vivi_ dans le forum Requêtes
    Réponses: 3
    Dernier message: 17/03/2014, 12h31
  2. Réponses: 1
    Dernier message: 16/11/2011, 15h17
  3. Efficacité: GROUP BY plus rapide que ORDER BY ?
    Par Chekov dans le forum Langage SQL
    Réponses: 7
    Dernier message: 19/12/2007, 09h33
  4. [MySQL] Order by qui marche pas, Que faire ?
    Par mulbek dans le forum PHP & Base de données
    Réponses: 25
    Dernier message: 06/01/2006, 14h48
  5. Réponses: 10
    Dernier message: 30/11/2004, 10h12

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