Précédent   Forum des professionnels en informatique > Bases de données > Oracle
Oracle Forum Oracle : le serveur, les outils, ... Voir F.A.Q Oracle Tutoriels Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/01/2007, 09h52   #1
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Par défaut commit régulier avec un delete en masse

Bonjour à tous,

Voilà j'ai un gros pb avec oracle 9i

Je voudrais faire un delete complet d'une table très volumineuse et commiter tous les 5000 enregistrements.

Avez vous une idée de comment je pourrais faire ?

Merci
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 09h58   #2
Membre éprouvé
 
Avatar de chrifo
 
Inscription : juillet 2006
Messages : 445
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 445
Points : 418
Points : 418
Salut,
Sol 1 : un bon vieux truncate
Sol 2 : Une boucle PL

A+
chrifo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 10h03   #3
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Oaip le bon vieux truncate serais effectivement bienvenue,

mais le pb c'est que je dois obligatoirement avoir des logs de petites tailles car j'ai 2 bdd couplé avec dataguard et que lorsque je fait un truncate il perd les pédale et lorsque je fais un

dataguard se plante car il ne peux pas traité autant d'info d'un coup.

Je voulais faire une procédure PL, mais je ne sais pas par où commencer ?!
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 14h57   #4
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
CURSOR et BULK COLLECT
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 15h21   #5
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Merci de ta réponse Fred_D

Ma question va surement te paraître idiote mais c'est quoi un bulk collect ?

J'ai essayer de faire ça, mais ce n'est pas très convainquant...
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
declare
  cpt number := 0; 
  max number;
 
begin
	 SELECT count(*) INTO max FROM ma_table;
   WHILE cpt < max
   LOOP
        DELETE  ma_table WHERE ROWNUM < 5000 ;
         cpt := cpt + 5000;
         commit;
    end loop;
    commit;
end;
/
Si tu penses qu'un bulk collect est necessaire pourrais tu m'en dire plus ?
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 16h00   #6
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
utilise la recherche pour trouver des exemples ou lis ce document : http://sheikyerbouti.developpez.com/...=Chap1#L1.2.20
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 16h43   #7
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Je ne vois pas bien en quoi le bulk collect peux m'aider...
J'ai tester celà :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
Declare
   TYPE TYP_TAB_EMP IS TABLE OF ma_table%Rowtype ;
    Tabemp TYP_TAB_EMP ;
  Begin  
   SELECT
        *
      BULK COLLECT
      INTO
         Tabemp
     FROM 
       ma_table;
     FOR i IN Tabemp.first..Tabemp.last Loop
       DELETE FROM ma_table WHERE cle1=Tabemp(i).cle1 AND cle2=Tabemp(i).cle2;
	   commit;
     End loop;
   End ;
   /
Dans ce code je fait un commit tout les enregistrements et Oracle me jette par manque de mémoire...
En plus la clé primaire de ma table est composé ce qui m'oblige à faire la jointure sur 2 champs.

Je suis perdue...

J'ai vu sur internet qu'il existerais quelque chose comme
ma_table.DELETE(val1, val2);
qui permet de supprimer les enregistrements de la ligne val1 à la ligne val2.

En savez vous plus ?
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 16h45   #8
Membre émérite
 
Avatar de Yorglaa
 
Inscription : janvier 2004
Messages : 845
Détails du profil
Informations personnelles :
Âge : 41
Localisation : Suisse

Informations forums :
Inscription : janvier 2004
Messages : 845
Points : 939
Points : 939
regarde à nouveau la doc que t'a donné Fred_D !

la boucle où tu fais le delete ne doit pas être un FOR... mais FORALL (sans End Loop)
__________________
Il est plus facile de voir les signes avant-coureurs après coup que l'inverse !

Yorglaa
Yorglaa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2007, 17h22   #9
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Alors voila je crois que je me suis bien battu et que j'ai finalement gagné !
J'ai laissé tomber le bulk collect pour quelque chose de plus simple :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
declare
  v_pas number; 
  v_count number;
begin
LOOP
   v_pas := 5000;
 
   DELETE FROM ma_table WHERE rownum < v_pas;   
   commit; 
   SELECT count(*) INTO v_count FROM ma_table;
 
IF v_count = 0 then
   exit;
end IF;
 
END LOOP;
end;
Ce n'est peut être pas la meilleure solution, mais au moins elle marche !
Merci à vous de votre aide.
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 09h59   #10
Membre éclairé
 
Avatar de Wurlitzer
 
Inscription : avril 2006
Messages : 465
Détails du profil
Informations forums :
Inscription : avril 2006
Messages : 465
Points : 368
Points : 368
Le bulk collect pourrait t'aider si tu avais besoin de faire un select pour trouver les enregistrements à supprimer. Dans ton cas la condition est directement dans le delete. C'est donc plus simple.

Ta solution est correcte. Je te propose l'optimisation suivante qui évite de faire un count et donc potentiellement un FULL SCAN a chaque itération de boucle. Ce qui peut change beaucoup de chose du point de vue des perfs


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
declare
  v_pas number; 
  p_nb_delete number;
begin
LOOP
   v_pas := 5000;
 
   DELETE FROM ma_table WHERE rownum <= v_pas;   
   p_nb_delete := SQL%ROWCOUNT;   
   commit; 
    
IF p_nb_delete < v_pas then
   exit;
end IF;
 
END LOOP;
end;
Wurlitzer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 10h36   #11
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
et pourquoi pas un WHILE ROWCOUNT>0 ?
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 11h34   #12
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Merci pour ces précieux conseils.
Effectivement Wurlitzer, ta solution est beaucoup moins gourmandes que la mienne.
Quand à ton optimisation Fred_D, juste par curiosité qu'est ce que cela m'apporte ? La structure loop exit est-elle plus gourmande que while loop ?
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 11h46   #13
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
c'est juste moins compliqué
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 14h16   #14
Membre éclairé
 
Avatar de Wurlitzer
 
Inscription : avril 2006
Messages : 465
Détails du profil
Informations forums :
Inscription : avril 2006
Messages : 465
Points : 368
Points : 368
Je vois deux raisons pour ne pas utiliser le WHILE ROWCOUNT>0 :
  • La première (assez mauvaise ), j'y avais pas pensé.....
  • La seconde, est que plus loin dans mon code j'additionne les p_nb_delete pour afficher le nombre de lignes totales supprimées

Sinon, je suis d'accord que c'est plus élégant
Wurlitzer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/01/2007, 14h33   #15
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
pour la seconde SQLROWCOUNT + ((nb_boucle - 1) * v_pas)
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/01/2007, 08h52   #16
Membre éclairé
 
Avatar de Wurlitzer
 
Inscription : avril 2006
Messages : 465
Détails du profil
Informations forums :
Inscription : avril 2006
Messages : 465
Points : 368
Points : 368
La nuit portant conseil et juste pour le plaisir de chipoter un peu
  • Si on doit compter le nombre de boucles on peut compter les lignes directement
  • Avec WHILE ROWCOUNT>0 tu es moins optimisé que car tu fais presque toujours un DELETE de trop (puisque que le dernier DELETE est presque toujours un nombre de ligne inferieur a w_pas mais > 0). Il faudrait ecrire WHILE ROWCOUNT = v_pas pour eviter ca
Wurlitzer est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/01/2007, 09h46   #17
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Pour l'optimisation, vous êtes efficaces dans votre genre !

Wurlitzer, ta dernière solution me laisse perplexe.
Parce que si je fait un while rowcount=v_pas alors justement je ne passe pas dans la boucle pour le dernier delete et donc lorsque je sort de ma boucle il me reste encore des enregistrements dans ma table, non ?

Je vais rester sur la solution de Fred_D.
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/01/2007, 10h56   #18
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
si c'est bon, l'avant dernière boucle fera un rowcount = v_pas, du coup tu passes le WHILE pour faire ce qui sera la dernière boucle

Bravo Wurlitzer
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/01/2007, 11h17   #19
Responsable Business Intelligence
 
Avatar de kalyparker
 
Femme
Consultant en Business Intelligence
Inscription : janvier 2007
Messages : 1 192
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : France

Informations professionnelles :
Activité : Consultant en Business Intelligence

Informations forums :
Inscription : janvier 2007
Messages : 1 192
Points : 2 564
Points : 2 564
Oh la la, honte sur moi

effectivement, vous avez raison, je n'avais pas bien saisi le but de la manoeuvre et pis c'etait le matin alors...
Non, je sais que je n'ai pas d'excuse alors je m'arrete...

A nouveau merci à vous et

++
kalyparker est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 01h02.


 
 
 
 
Partenaires

Hébergement Web