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

SQL Oracle Discussion :

[10g] IN LIST versus subquery ?


Sujet :

SQL Oracle

  1. #1
    Membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Avril 2004
    Messages
    46
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 46
    Points : 43
    Points
    43
    Par défaut [10g] IN LIST versus subquery ?
    Bonjour
    Nous avons un utilisateur qui veut passer des listes de +500 valeurs dans un IN

    J'ai comme souvenir qu'il est nefaste de mettre dans une query un IN avec une immense liste de valeurs, mais je n'arrive plus a me souvenir pourquoi ni a trouver d'explication dans les docs et les forums (ca me paraissait pourtant simple a denicher...)
    Je pense qu'il vaut mieux utiliser une table et faire une subquery.

    Quelqu'un peut-il confirmer ou infirmer mon souvenir
    et m'expliquer le fonctionnement de l'optimiseur dans les 2 cas (que la colonne soit indexee ou pas) ?

    Merci
    Isa

  2. #2
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Il y a une limite des 1000 valeurs dans la liste.
    La requête qui utilise IN avec la liste des valeurs est transformée pour utiliser des OR.
    Vous pouvez faire un test mais il y a peu des chances que la solution qui implique remplir une table temporaire pour ensuite l’utiliser dans la sous-requête se comporte mieux que la solution qui utilise le IN.

  3. #3
    Membre expérimenté Avatar de ojo77
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Décembre 2010
    Messages
    680
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2010
    Messages : 680
    Points : 1 597
    Points
    1 597
    Par défaut
    Dans tous les cas, l'optimiseur va essayer de réécrire votre requête

    Avec index :
    Dans le cas colonne1 IN ( liste de valeurs )
    La sélectivité de colonne1 sera, s'il n'y a pas d'histogramme, égale à la sélectivité moyenne d'une valeur multiplié par le nombre de valeurs, plus le nombre de valeurs est grand, plus la sélectivité va pousser vers le FTS.

    S'il y a un histogramme, ça se complique un poil ... comme on a potentiellement plus de 254 valeurs il s'agira d'un histogramme recensant les valeurs populaires et non toutes les valeurs possibles. Soit la liste contient des valeurs populaires, soit elle n'en contient pas. Si elle en contient encore une fois on se dirige vers le FTS. Si elle n'en contient pas on se retrouve comme dans la situation où il n'y a pas d'histogramme avec un sélectivité individuelle beaucoup plus faible pour les valeurs non populaires.

    Sans Index
    Pas de choix => FTS

    On s'oriente donc très probablement vers set FTS + FILTER ou au minimum un IFS + table access by rowid + FILTER

    Dans le cas colonne1 IN ( select ... )
    Les mêmes règles s'appliquent a l'exception que la partie FILTER peut être remplacée par un HASH JOIN ou un SORT MERGE JOIN

    Au final je rejoins la conclusion de mnitu, mais il faut tester

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Comment est consituée la liste des valeurs du IN ?
    Si c'est un ensemble de valeurs prises dans une autre table répondant à une certaine conditions, alors il doit être possible de faire une jointure plutôt que le IN. Ça devrait être beaucoup plus rapide.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    ...Ça devrait être beaucoup plus rapide.
    Avez-vous regarde le plan d’exécution pour les deux requêtes : In vers Join ? Regardez-les et vous aurez une belle surprise.

  6. #6
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Avez-vous regarde le plan d’exécution pour les deux requêtes : In vers Join ? Regardez-les et vous aurez une belle surprise.
    Une fois le plan d'exécution fait, je pense aussi que ça doit dépendre des cas, mais qu'en général le IN gagne.
    Par contre, ce qui est sûr, c'est si la condition varie, la requête à base de IN a toutes les chances de devoir être reparsée à chaque fois (même si on passe tout en Bind, une valeur de plus ou de moins = nouvelle requête), ce qui peut être pénalisant du point de vue performance s'il s'agit d'une requête rapide exécutée un grand nombre de fois ! Auquel cas il serait préférable de passer par une jointure pour laquelle on aurait un plan unique.

  7. #7
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par Rei Ichido Voir le message
    Une fois le plan d'exécution fait, je pense aussi que ça doit dépendre des cas, mais qu'en général le IN gagne.
    Par contre, ce qui est sûr, c'est si la condition varie, la requête à base de IN a toutes les chances de devoir être reparsée à chaque fois (même si on passe tout en Bind, une valeur de plus ou de moins = nouvelle requête), ce qui peut être pénalisant du point de vue performance s'il s'agit d'une requête rapide exécutée un grand nombre de fois ! Auquel cas il serait préférable de passer par une jointure pour laquelle on aurait un plan unique.
    J’ai l’impression qu’on se comprend mal. Néanmoins, en supposant que vous avez construis votre requête de la façon suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Select e.first_name
      from hr.employees e
     Where e.employee_id In (:b0, :b1, :b2, ... :b500)
    Rien ne vous oblige à réparser votre requête chaque fois que le nombre des valeurs "utiles" change, passez null pour les variable non "utiles".

  8. #8
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    En effet, c'est une solution toute simple que je n'avais pas envisagée !
    Il faudrait alors aller jusqu'à 1000, pour traiter tous les cas possibles.

  9. #9
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    En pratique ça sera plutôt un compromis entre avoir une seule requête pour tous les cases d'utilisations possible et avoir plusieurs requêtes, chacune adaptée à un cas d’utilisation. Supposons que vous avez dans l’interface utilisateur la possibilité de choisir entre 1 et 50 "articles" différente. Vous pouvez envisager 5 requêtes qui utilisent chacune entre 1 et 10 variables de liaison, entre 1 et 20, entre 1 et 30 etc.

Discussions similaires

  1. Problème avec l'utilisation d'une list versus un vector
    Par homeostasie dans le forum Langage
    Réponses: 4
    Dernier message: 02/11/2011, 11h17
  2. Liste Deroulante dans "Oracle developper suite-10g"
    Par guyfab dans le forum Oracle
    Réponses: 6
    Dernier message: 15/09/2006, 18h32
  3. Réponses: 19
    Dernier message: 17/05/2006, 19h05
  4. Réponses: 4
    Dernier message: 11/05/2006, 11h28
  5. Réponses: 3
    Dernier message: 15/03/2006, 03h19

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