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

Administration Oracle Discussion :

Création d'une table à partir d'une requête


Sujet :

Administration Oracle

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut Création d'une table à partir d'une requête
    Bonjour.

    Je cherche la meilleure méthode pour créer une table à partir d'une requête. La requête en question ramène de très volumineux résultats. La table où seront stoqués les résultats aura son propre tablespace.

    Voici les méthodes que j'ai trouvé:

    1. La méthode la plus connue (Gourmand en utilisation du tablespace temporaire):
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
       
      CREATE TABLE RESULTATS AS SELECT ...
    2. Une autre méthode assez connue (Gourmand en utilisation du tablespace temporaire):
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
       
      -- En admettant que la table a été crée au paravant:
      INSERT INTO RESULTATS SELECT ...
    3. Par curseur interposé (Plus lent que les 2 prmières, mais n'utilise pas le tablespace temporaire):
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
       
      -- On admettra aussi que la table a déjà été crée
      -- On pourra tout aussi bien faire un WHILE en utilisant FETCH pour parcourir le curseur
      FOR C IN (SELECT...) LOOP
          INSERT INTO RESULTATS VALUES (C.COL1, C.COL2, ...);
      END LOOP;


    Bon voilà ce que j'ai trouvé. Evidemment je pourrais déclarer une vue, mais celà ne m'intéresse pas, sauf si il est possible de faire une vue fixe, c'est à dire sans qu'elle ne prenne en compte les modifications futures dans les tables concernées par la requête.

    Y aurait-il d'autres méthodes plus rapides? Le problème est qu'il ne faut pas que le tablespace temporaire soit utilisé, ou qu'il soit très peu utilisé, comme dans la 3ème méthode.

    Merci d'avance.
    @+

  2. #2
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    A mon avis (je me trompe peut etre) c'est plus le select que le "create table machin as" qui est gourmant en tablespace temporaire, si tu as un gros tri, un group-by, une union, un distinct etc... dans ton select, là ça va effectivement consomer du temp...

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par remi4444
    A mon avis (je me trompe peut etre) c'est plus le select que le "create table machin as" qui est gourmant en tablespace temporaire, si tu as un gros tri, un group-by, une union, un distinct etc... dans ton select, là ça va effectivement consomer du temp...
    En fait je ne pense pas que ce soit le create qui bouffe du tablespace temporaire, car quand je crée la table en décrivant les colonne grace à l'ouverture d'un curseur (DBMS_SQL.OPEN_CURSOR, DBMS_SQL.PARSE, DBMS_SQL.DESCRIBE_COLUMNS2), celà prend moins d'une seconde et n'utilise pas de tablespace. Ensuite en replissant cette table ligne à ligne grace à la boucle LOOP de la 3ème méthode, celà met du temps, mais n'utilise pas tout ou presque pas de tablespace temporaire.
    Ce que je pense, c'est que lors de l'utilisation de la syntaxe de la 1ère et 2ème syntaxe, Oracle doit mettre tout le résultat de la requête dans l'espace temporaire avant de le basculer dans la table. Alors qu'en utilisant le parcours ligne à ligne du curseur, il y a tout au plus une seule ligne qui se retrouve dans l'espace temporaire en même temps.

    Bon sinon je suis en train de me renseigner et de faire des test de performances sur l'utilisation des vue matérialisées.
    Dès que j'aurai le temps, je ferais des tests avec mesure du temps sur toutes les méthodes que j'aurai trouvé et publierai un petit tableau comparatif si ça peut servir à quelqu'un.

    @+

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Une vue matérialisée, ce n'est jamais qu'une table qui se rempli avec une requête, c'est à dire l'équivalent de "SELECT * FROM MACHIN INTO BIDULE". Le gros avantage est que, sous certaines conditions, tu peux faire du rafraichissement différentiel mais il faudra forcément en passer au départ par un remplissage complet.

    Sinon, j'ai cru comprendre que d'après oracle c'était le "CREATE TABLE TRUC AS ..." qui était le plus éfficace car il faisait du "DIRECT LOAD" un peu comme SQL*LOADER.

    PS: Qu'est-ce qui te fait dire qu'une méthode prends plus d'espace temporaire qu'une autre, tu as des messages d'erreurs de dépassement de tablespace TEMP ?

  5. #5
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    on peut faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE ... AS SELECT ... WHERE ROWNUM = 0
    Et On peut optimiser le 3 avec les bulk collect aussi

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par remi4444
    PS: Qu'est-ce qui te fait dire qu'une méthode prends plus d'espace temporaire qu'une autre, tu as des messages d'erreurs de dépassement de tablespace TEMP ?
    Je regarde l'utilisation du tablespace en temps réel tout simplement

    @+

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par Fred_D
    on peut faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE ... AS SELECT ... WHERE ROWNUM = 0
    Et On peut optimiser le 3 avec les bulk collect aussi
    Le problème c'est que comme je l'ai dit plus haut, est aussi gourmand en tablespace temporaire que le simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE ... AS SELECT ...
    Sinon pourrais-tu être plus explicite sur les bulk collect (avec un petit exemple), il me semblait que celà obligeait la création d'autant de tableau mémoire qu'il y a de colonne dans la requête. Merci d'avance.

    @+

  8. #8
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    la doc PL/SQL est en ligne http://oracle.developpez.com/guide

  9. #9
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par pedroleouf
    Le problème c'est que comme je l'ai dit plus haut, est aussi gourmand en tablespace temporaire que le simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE ... AS SELECT ...
    Il manque quand meme un truc vachement important pour ne pas parler dans le vide, c'est ce qu'il y a dans ton select...

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par remi4444
    Il manque quand meme un truc vachement important pour ne pas parler dans le vide, c'est ce qu'il y a dans ton select...
    Oui, alors le mieux c'est que je te donne un exemple du genre de requête que j'ai:
    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
     
    SELECT ROWNUM AS ROW_NUM, T.*
          FROM (SELECT TRIM(NUMPOL.NUM_POL) AS POL_NUM,
                       DECODE(VEH_POL.ID_CATR,
                              NULL,
                              POL_GAR.PNET_GARP,
                              GAR_FORMULES.PBAS_GPROD) AS PRIME_NETTE,
                       DECODE(VEH_POL.ID_CATR,
                              NULL,
                              POL_GAR.TTC_GARP,
                              GAR_FORMULES.TTC_GPROD) AS PRIME_TTC
                  FROM POLICE POLICE
                  JOIN NUMPOL NUMPOL ON (NUMPOL.ID_POL = POLICE.ID_POL)
                  JOIN (SELECT MAX(LIENPOL.ID_LPOL) AS ID_LPOL,
                              LIENPOL.ID_POL AS ID_POL,
                              LIENPOL.ID_FPOL AS ID_FPOL
                         FROM LIENPOL
                        WHERE LIENPOL.CD_LIEN = 'FLOTTE'
                        GROUP BY LIENPOL.ID_POL, LIENPOL.ID_FPOL) VEH_LAST_LP ON (VEH_LAST_LP.ID_POL =
                                                                                 POLICE.ID_POL)
                  JOIN LIENPOL VEH_LPOL ON (VEH_LPOL.ID_LPOL = VEH_LAST_LP.ID_LPOL AND
                                           VEH_LPOL.ID_FPOL = VEH_LAST_LP.ID_FPOL AND
                                           VEH_LPOL.ID_POL = VEH_LAST_LP.ID_POL AND
                                           VEH_LPOL.CD_LIEN = 'FLOTTE')
                  JOIN POLICE VEH_POL ON (VEH_POL.ID_POL = VEH_LPOL.ID_LPOL)
                  LEFT OUTER JOIN GARPOL POL_GAR ON (POL_GAR.ID_POL = VEH_POL.ID_POL AND
                                                    POL_GAR.CD_GAR = 'COURTAGE')
                  LEFT OUTER JOIN CATEGRIS CATEGRIS ON (CATEGRIS.ID_CATR =
                                                       VEH_POL.ID_CATR)
                  LEFT OUTER JOIN FORMULES GAR_FORMULES ON (GAR_FORMULES.CD_FORM =
                                                           CATEGRIS.FORM_CATR AND
                                                           GAR_FORMULES.CD_GAR =
                                                           'COURTAGE' AND
                                                           GAR_FORMULES.ID_POL =
                                                           POLICE.ID_POL)
                  JOIN COMPAGNIE POL_CIE ON (POL_CIE.CD_CIE = NUMPOL.CD_CIE)
                 WHERE POL_CIE.ID_PER = 6969) T
    Cela peut ramener jusqu'à 250000 lignes :-)

    Voilà, c'est horrible, mais je n'ai pas le choix, c'est le MPD du client qui est ainsi

    Sinon toutes les requêtes sont de la sorte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT ROWNUM AS ROW_NUM, T.*
          FROM (/* requête */) T
    car par la suite j'utilise la ligne pour faire des calculs, enfin peut importe...

  11. #11
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    De toutes façons ce genre de requête va consomer de l'espace temporaire car il y a des group by, des jointures sur des sous-requête en un calcul de rownum au dessus du tout... ce qui m'étonne c'est que la methode par curseur en consome moins...

    Le fait de faire calculer un rownum dans une requête au dessus ne se justifie que si tu fait un ORDER BY dans ta sous requête. Dans l'exemple que tu as donné, tu peux tout aussi bien ramener le rownum au meme niveau que les 3 autres colonnes, ça économiserais du TEMP.

  12. #12
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    il y a les hints APPEND et PARALLEL aussi... et la requête de SELECT prend combien de temps par rapport à l'INSERT ? T'as fait une trace ?

    Quand je pense qu'on cherche une solution globale depuis le début alors que c'est un problème spécifique

  13. #13
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par Fred_D
    Quand je pense qu'on cherche une solution globale depuis le début alors que c'est un problème spécifique
    c'est la première fois que je vois ça

  14. #14
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    quand je vois :
    JOIN (SELECT MAX(LIENPOL.ID_LPOL) AS ID_LPOL,
    LIENPOL.ID_POL AS ID_POL,
    LIENPOL.ID_FPOL AS ID_FPOL
    FROM LIENPOL
    WHERE LIENPOL.CD_LIEN = 'FLOTTE'
    GROUP BY LIENPOL.ID_POL, LIENPOL.ID_FPOL) VEH_LAST_LP ON (VEH_LAST_LP.ID_POL =
    POLICE.ID_POL)
    JOIN LIENPOL VEH_LPOL ON (VEH_LPOL.ID_LPOL = VEH_LAST_LP.ID_LPOL AND
    VEH_LPOL.ID_FPOL = VEH_LAST_LP.ID_FPOL AND
    VEH_LPOL.ID_POL = VEH_LAST_LP.ID_POL AND
    VEH_LPOL.CD_LIEN = 'FLOTTE')
    je pense immédiatement fonction analytique... malheureusement, n'étant pas familier de l'ANSI j'ai du mal à voir comment le mettre en oeuvre :'(

    rémi c'est sûr

  15. #15
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par remi4444
    Dans l'exemple que tu as donné, tu peux tout aussi bien ramener le rownum au meme niveau que les 3 autres colonnes, ça économiserais du TEMP.
    Non, car il arrivera souvent que j'ai un order by dans la requête, et à ce moment, j'aurai plus le bon ordre dans ma table de destination:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    /*
     * - ROWNUM à l'extérieur:
     * 1   | Alfred
     * 2   | Jean
     * 3   | Robert
     *
     * ROWNUM à l'intérieur (exemple possible):
     * 2   | Alfred
     * 3   | Jean
     * 1   | Robert
     */

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Vous verriez l'état de la base de données du client...
    Après on dit que le client est roi, mais là vu les requêtes de fou que je suis obligé de faire pour récupérer des infos si basiques, le client va être roi mais devra patienter durant l'éxécution des requêtes...


    Le pb avec la requête d'exemple, c'est qu'en gros et brièvement le schéma de la BDD pour cette requête est le suivant:

    Assuré <=> TL <=> Police de la flotte <=> TLB => Police du vehicule <=> TLB <=> Vehicule

    TL: Table de liaison
    TLB: Table de liaison bizare (MAX..)

    Enfin... vous comprenez mon malheur quand on m'a demandé de faire un requêteur simple à utiliser pour un utilisateur lambda (enfin je dirai bêta...) qui devra avoir une durée de compilation de requête limitée à 30 secondes car
    ah non, il ne faut pas toucher au paramètres du serveur ni à ceux de la connection
    selon les instructions du client...

  17. #17
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Monte un DWH avec rapatriement des données à intervalles réguliers...
    Il vaut mieux monopoliser son intelligence sur des bêtises que sa bêtise sur des choses intelligentes.

Discussions similaires

  1. Réponses: 7
    Dernier message: 22/06/2012, 12h12
  2. Réponses: 3
    Dernier message: 27/03/2009, 10h43
  3. [Tables] Update d'une table à partir d'une autre
    Par le_niak dans le forum VBA Access
    Réponses: 2
    Dernier message: 17/01/2008, 09h01
  4. [ASE]SOS Création d'une table à partir d'une requête
    Par bilelle dans le forum Adaptive Server Enterprise
    Réponses: 1
    Dernier message: 26/09/2007, 11h39
  5. copie d'une table Y d'une base A vers une table X d'une base
    Par moneyboss dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 30/08/2005, 21h24

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