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] index non utilisé et using temporary


Sujet :

Requêtes MySQL

  1. #1
    Membre régulier Avatar de jp_rennes
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    72
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Mars 2006
    Messages : 72
    Points : 86
    Points
    86
    Par défaut [Optimisation] index non utilisé et using temporary
    1) Je ne comprends pas que la création de l'index sur la colonne CountryCode ne soit pas utilisé par l'optimiseur de requête
    2) J'ai observé le 'Using temporary'; j'ai passé la variable 'sort_buffer_size' de 1048568 à 3000000 et ça ne change rien. Quelqu'un a une explication ?
    mysql> desc City;
    +-------------+----------+------+-----+---------+----------------+
    | Field | Type | Null | Key | Default | Extra |
    +-------------+----------+------+-----+---------+----------------+
    | ID | int(11) | NO | PRI | NULL | auto_increment |
    | Name | char(35) | NO | | | |
    | CountryCode | char(3) | NO | | | |
    | District | char(20) | NO | | | |
    | Population | int(11) | NO | | 0 | |
    +-------------+----------+------+-----+---------+----------------+
    5 rows in set (0.02 sec)

    mysql> show table status like 'City'\G
    *************************** 1. row ***************************
    Name: City
    Engine: MyISAM
    Version: 10
    Row_format: Fixed
    Rows: 4079
    Avg_row_length: 67
    Data_length: 273293
    Max_data_length: 18858823439613951
    Index_length: 43008
    Data_free: 0
    Auto_increment: 4080
    Create_time: 2006-10-20 14:35:43
    Update_time: 2006-10-20 14:35:43
    Check_time: NULL
    Collation: latin1_swedish_ci
    Checksum: NULL
    Create_options:
    Comment:
    1 row in set (0.01 sec)

    mysql> show index from City;
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    | City | 0 | PRIMARY | 1 | ID | A | 4079 | NULL | NULL | | BTREE | |
    +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
    1 row in set (0.00 sec)
    mysql> explain select CountryCode,avg(Population) from City group by CountryCode;
    +----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
    | 1 | SIMPLE | City | ALL | NULL | NULL | NULL | NULL | 4079 | Using temporary; Using filesort |
    +----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
    1 row in set (0.00 sec)

    mysql> create index codepays on City(CountryCode);
    Query OK, 4079 rows affected (0.06 sec)
    Records: 4079 Duplicates: 0 Warnings: 0

    mysql> explain select CountryCode,avg(Population) from City group by CountryCode;
    +----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
    | 1 | SIMPLE | City | ALL | NULL | NULL | NULL | NULL | 4079 | Using temporary; Using filesort |
    +----+-------------+-------+------+---------------+------+---------+------+------+---------------------------------+
    1 row in set (0.00 sec)

  2. #2
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Bonjour,

    1) L'utilisation d'un index dépend de la sélectivité de celui-ci. Si la colonne country_code contient 50% de valeurs 'fr' et 50% de valeurs 'us' par exemple, un full table scan est plus rentable car l'index n'est pas assez sélectif.

    ANALYZE TABLE peut aussi faire que l'index soit mieux pris en compte.

    2) L'utilisation de GROUP BY implique très souvent la création d'une table temporaire afin de réaliser les calculs d'agrégats. Cf http://dev.mysql.com/doc/refman/5.0/...imization.html


    [ Edit ] en fait c'est plutôt normal qu'aucun index ne soit utilisé, il n'y a pas de clause WHERE dans ta requête et il faut forcément passer en revue toutes les lignes. Le regroupement et les calculs d'agrégats se font ensuite entièrement dans la table temporaire.
    Pensez au bouton

  3. #3
    Membre régulier
    Profil pro
    Administrateur de base de données
    Inscrit en
    Juillet 2003
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juillet 2003
    Messages : 94
    Points : 116
    Points
    116
    Par défaut
    Seule solution, passer par un index couvrant 2 parties
    part1 = CountryCode
    part2 = Population

    l'OPTIMISEUR de MYSQL sur ce type de requête n'a aucun interet à passer par l'index CountryCode seul parce que dans tous les cas il devra aller chercher l'info complémentaire (colonne Population) dans les datas.
    Au final ça entrainera une consommation en E/S plus importante que de faire un scan de table.

    Cordialement

    Selecta

  4. #4
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par selecta
    Seule solution, passer par un index couvrant 2 parties
    part1 = CountryCode
    part2 = Population
    Je ne vois pas en quoi un tel index peut être utilisé ?

    Le but du jeu est de faire la moyenne de la population. Ca nécessite simplement d'additionner toutes les populations et de diviser par leur nombre... Donc aucune recherche sur une population donnée, qui pourrait être accélérée par cet index.
    Pensez au bouton

  5. #5
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    Par défaut
    L'utilité de cet index, à la limite et si on est vraiment désespéré, est que toutes les données utilisées dans la requête (et rien qu'elles, et peut-être groupé comme il le faut) sont dans l'index donc pas besoin de lire la table... en théorie. Vu qu'il n'y a pas de where je ne sais pas si mysql va percuter. Et le gain est discutable même si ça marche.

  6. #6
    Membre régulier
    Profil pro
    Administrateur de base de données
    Inscrit en
    Juillet 2003
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juillet 2003
    Messages : 94
    Points : 116
    Points
    116
    Par défaut
    L'optimiseur de MYSQL percutera sur une telle requête avec l'index couvrant bi-parties.
    Ensuite tout est question de compromis.
    Si la table a 10.000 lignes, le gain sera pas extraordinaire.
    si la table a 100 millions de lignes, ça commence à valoir le cout.

    Il y a pas mal de chose sur le WEB a propos des index couvrants qui ont pour l'avoir pratiqué pas mal d'incidence sur les optimiseurs de Sybase, Oracle, SQL SERVER et bien sur MySQL

    Pour le seuil de 50%, je l'abaisserai plutôt vers les 20 à 30 % pour de nombreux SGBD, y compris MYSQL.

  7. #7
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Autant pour moi, je n'avais pas pensé à cette optimisation...

    Citation Envoyé par selecta
    Pour le seuil de 50%, je l'abaisserai plutôt vers les 20 à 30 % pour de nombreux SGBD, y compris MYSQL.
    Oui, 50 % c'était juste un exemple
    Pensez au bouton

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

Discussions similaires

  1. ASE15-Index non-utilisé qd utilise variables dans WHERE clause
    Par vinceroi dans le forum Adaptive Server Enterprise
    Réponses: 3
    Dernier message: 22/03/2012, 23h05
  2. Index non utilisé dans une jointure
    Par lasyan3 dans le forum SQL
    Réponses: 15
    Dernier message: 12/04/2011, 09h06
  3. Index non utilisé dans une requête
    Par tibal dans le forum Administration
    Réponses: 9
    Dernier message: 10/05/2010, 15h29
  4. [Oracle 11g] Index non utilisé par oracle
    Par eryk71 dans le forum SQL
    Réponses: 12
    Dernier message: 17/02/2009, 10h29
  5. index non utilisé
    Par puck78 dans le forum SQL
    Réponses: 10
    Dernier message: 21/01/2009, 14h36

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