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

 PostgreSQL Discussion :

Utilisation des index composés avec un champ à valeur unique et EXPLAIN [9.1]


Sujet :

PostgreSQL

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2011
    Messages : 64
    Points : 38
    Points
    38
    Par défaut Utilisation des index composés avec un champ à valeur unique et EXPLAIN
    Bonjour, j'aurais une question sur l'optimisation des index

    j'ai une table avec 3 champs

    le premier est la clef primaire
    le deuxième n'a que des 1 dedans
    le troisième à des valeurs diverses

    sur cette table il y a un index unique composé sur le deuxième + troisième champs

    sur cette table je fait des select where champ3 =

    1) comme l'index composé n'a que des 1 dans sont premier champ peut il etre utilisé ?

    2) l'ajout d'un index sur le troisième champs est il intéressant?

    3) Que j'ajoute ou pas le second index, un
    EXPLAIN ANALYZE de ma requête ne donne pas d'"Index Scan using" ni de "Index Cond", comment cela se fait il ?

    Merci d'avance

  2. #2
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Salut
    Les index composés ne sont utilisés que si la condition de recherche contient les colonnes dans l'ordre de création de l'index.
    La création d'un index sur le troisième champs est obligatoire pour votre requête (WHERE ch3=...).
    Sachez par ailleurs que le SGBD n'utilise l'index que s'il le juge nécessaire! Pour le cas de PostgreSQL il faut le lui demander dans ses configurations.
    Pour plus de lecture.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  3. #3
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    bonjour,

    Citation Envoyé par alassanediakite Voir le message
    Les index composés ne sont utilisés que si la condition de recherche contient les colonnes dans l'ordre de création de l'index.
    La création d'un index sur le troisième champs est obligatoire pour votre requête (WHERE ch3=...).
    non et non


    1*/ l'index pourra être utilisé avec plus ou moins d'efficacité :

    si l'index est comme ceci : col2, col3 alors le sgbd sera obligé de faire un full index scan pour pouvoir n'utiliser que la 3eme colonne

    si l'index est comme ceci : col3, col2 alors le SGBD pourra attaquer l'index avec un index probe (plus direct)

    2*/ voir le 1

    Sinon pour les explains :
    Avez-vous fait un analyze de vos objets avant de regarder l'impact de l'index ?

    Si la condition sur la colonne 3 n'est pas assez discriminante le SGBD peut choisir de faire un table à la place de l'utilisation de l'index, ca n'est forcément une mauvaise approche.

  4. #4
    Membre expert
    Avatar de alassanediakite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Mali

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 1 599
    Points : 3 590
    Points
    3 590
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par punkoff Voir le message
    non et non
    En plus de l'article de sqlpro je vous propose ça.
    @+
    Le monde est trop bien programmé pour être l’œuvre du hasard…
    Mon produit pour la gestion d'école: www.logicoles.com

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    http://dba.stackexchange.com/questio...esql/7484#7484


    Perso pour la reproduction j'y suis pas encore arrivé.

  6. #6
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    allez zou, ma table de test n'était pas assez grosse par rapport à l'index je suppose :

    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
     
    drop table tt;
     
    create table tt (id int, fk1 int, val1 char(100));
     
    with tmp as (select generate_series(1, 1000000) as val)
    insert into tt select val, val%10000, val from tmp;
     
     
    create index idx_tt on tt (id, fk1);
     
    analyze;
     
     
    explain analyze
    select *
    from tt where fk1 = 100;

    explain :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    "Index Scan using idx_tt on tt  (cost=0.42..18655.72 rows=98 width=109) (actual time=0.022..22.241 rows=100 loops=1)"
    "  Index Cond: (fk1 = 100)"
    "Total runtime: 22.265 ms"


    En créant un index "propre" sur fk1 on peut voir le temps d’exécution bien inférieur, avec un plan bien différent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    create index idx_tt2 on tt (fk1);
     
    analyze;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    "Bitmap Heap Scan on tt  (cost=5.18..376.24 rows=98 width=109) (actual time=0.041..0.111 rows=100 loops=1)"
    "  Recheck Cond: (fk1 = 100)"
    "  ->  Bitmap Index Scan on idx_tt2  (cost=0.00..5.16 rows=98 width=0) (actual time=0.027..0.027 rows=100 loops=1)"
    "        Index Cond: (fk1 = 100)"
    "Total runtime: 0.128 ms"

    Si on force un table scan, on pourra voir que le temps d'exec est encore plus long quand dans le cas 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    explain analyze
    select *
    from tt
    where fk1 = 100 or val1 = '100';
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    "Seq Scan on tt  (cost=0.00..32242.00 rows=99 width=109) (actual time=0.044..204.252 rows=100 loops=1)"
    "  Filter: ((fk1 = 100) OR (val1 = '100'::bpchar))"
    "  Rows Removed by Filter: 999900"
    "Total runtime: 204.278 ms"

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2011
    Messages : 64
    Points : 38
    Points
    38
    Par défaut index composés et valeurs uniques
    Bonjour merci beaucoup de votre participation,

    mon cas n'était pas tout à fait celui-là mais un peu tordu et difficile à s'imaginer de fait.
    En fait dans le premier champs de l'index je n'ai qu'une valeur, toujours la même, d'où la confusion avec unique

    A la suite des derniers scripts, j'ai donc fait
    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
     
    DROP TABLE tt;
     
    CREATE TABLE tt (id int, fk1 int, val1 char(100));
     
    WITH tmp AS (SELECT generate_series(1, 1000000) AS val)
    INSERT INTO tt SELECT val, 1, val FROM tmp;
     
    analyze;
     
    EXPLAIN analyze
    SELECT *
    FROM tt WHERE val1 = '100';
     
    "Seq Scan on tt  (cost=0.00..29742.00 rows=1 width=109) (actual time=0.144..340.945 rows=1 loops=1)"
    "  Filter: (val1 = '100'::bpchar)"
    "Total runtime: 341.004 ms"
     
    CREATE INDEX idx_tt ON tt (fk1, val1);
     
    analyze;
     
    EXPLAIN analyze
    SELECT *
    FROM tt WHERE val1 = '100';
     
    "Seq Scan on tt  (cost=0.00..29742.00 rows=1 width=109) (actual time=0.170..260.504 rows=1 loops=1)"
    "  Filter: (val1 = '100'::bpchar)"
    "Total runtime: 260.575 ms"
     
     
    DROP INDEX idx_tt;
     
    CREATE INDEX idx_tt ON tt (val1);
     
    analyze;
     
    EXPLAIN analyze
    SELECT *
    FROM tt WHERE val1 = '100';
     
    "Index Scan using idx_tt on tt  (cost=0.00..8.92 rows=1 width=109) (actual time=0.460..0.463 rows=1 loops=1)"
    "  Index Cond: (val1 = '100'::bpchar)"
    "Total runtime: 0.517 ms"
    Donc du coup, seul l'index non composé peut être utilisé pour mon cas.
    Cela semble donc en contradiction avec http://use-the-index-luke.com/fr/sql...dex-concatenes
    voir Figure 2.1. Index concaténé

  8. #8
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Vous pouvez aussi changer votre index unique en inversant les 2 colonnes.

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2011
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2011
    Messages : 64
    Points : 38
    Points
    38
    Par défaut
    Merci pour toutes les infos
    et aussi pour la manière de créer facilement une table remplie à la volée, ce qui me sera bien utile.

    Tout compte fait , il n'y a pas de contradiction avec http://use-the-index-luke.com/fr/sql...dex-concatenes
    c'est juste que le plan d'exécution ne sait pas les valeurs enregistrées sur les tables, donc il ne sait pas qu'il y a un champ avec constamment les mêmes valeurs.

  10. #10
    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 bibouilles Voir le message
    c'est juste que le plan d'exécution ne sait pas les valeurs enregistrées sur les tables, donc il ne sait pas qu'il y a un champ avec constamment les mêmes valeurs.
    si, il le sait !
    Il tient des statistiques sur les colonnes indexées.
    C'est d'ailleurs une des raisons pour laquelle un tel index sera sous utilisé, il n'est pas sélectif.

    Cependant, quel est l’intérêt de cette colonne, si elle contient toujours la même valeur ? et surtout, quel est l’intérêt de l'indexer ?

    Dans tous les cas, vous auriez - comme le dit punkoff - tout intérêt à inverser l'ordre de vos colonnes dans l'index

  11. #11
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    et surtout, quel est l’intérêt de l'indexer ?
    C'est une astuce qu'on utilise avec Oracle pour permettre de chercher des valeurs nulles via un index.
    Par défaut elles ne sont pas indexées, mais en associant une constante le couple devient toujours non-nul et la recherche des nulls peut utiliser l'index.
    http://tkyte.blogspot.fr/2006/01/som...t-nothing.html

    Je n'ai pas testé chez Postgresql.

  12. #12
    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
    Citation Envoyé par Waldar Voir le message
    Par défaut elles ne sont pas indexées.
    Merci pour la précision... et pour l'astuce



    Citation Envoyé par Waldar Voir le message
    Je n'ai pas testé chez Postgresql.
    bah... j'ai pas pu m’empêcher, et il semble que Postgresql index bien les null, donc inutile d'être astucieux

    idem pour SQL Server

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    L'indexation de NULL avec PostgreSQL dépend du type d'index.

    Le type d'index le plus utilisé, btree, indexe les NULL
    hash n'indexe pas les NULL
    GIST indexe les NULL
    GIN indexe les NULL à partir de la version 9.1 seulement

    Il y a également une colonne amsearchnulls dans pg_am qui indique si un type d''index est utilisable pour chercher sur IS NULL/NOT NULL

    En 9.3:

    => select amname,amsearchnulls from pg_am;
    
     amname | amsearchnulls 
    --------+---------------
     btree  | t
     hash   | f
     gist   | t
     gin    | f
     spgist | t
    

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

Discussions similaires

  1. Utilisation des couleurs rgb() avec valeurs > 255
    Par dedeff dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 24/07/2014, 21h50
  2. Requête SELECT : limite d'utilisation des index
    Par DadaWeb dans le forum Requêtes
    Réponses: 7
    Dernier message: 07/12/2005, 22h24
  3. Compteur sur l'utilisation des index
    Par hkhan dans le forum Administration
    Réponses: 11
    Dernier message: 14/10/2004, 17h57
  4. Utilisation des "indexs" ?
    Par vandeyy dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 07/09/2004, 07h49
  5. [CR9] Bug avec les champs à valeur vide ?
    Par Djob dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 15/07/2003, 21h21

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