Gestion doublons sqlloader

Gestion doublons sqlloader - SQL/NoSQL - Programmation

Marsh Posté le 04-05-2011 à 09:07:00    

Bonjour à tous,
 
Nous souhaitons intégrer n fichiers csv (minimum 2) dans une table Oracle. Pour cela on utilise SqlLoader de cette manière :  
 
 
Code :Sélectionner tout - Visualiser dans une fenêtre à partsqlldr.exe userid=sj\/sj@serveur control=import.ctl log=import.log direct=trueAucun problème ça fonctionne, mais la table se retrouve avec des doublons et lorsque l'on souhaite ouvrir l'application appelant cette table, on se retrouver avec une erreur "ORA-01502 index or partition of such index is in unusable state".  
La table contient une clé primaire constitué de 3 champs.
 
Nous avons essayé avec SqlLoader en ajoutant les options qui permettent de respecter les contraintes. Ca fonctionne, mais le temps de chargement est long.
 
Existe t'il une requête permettant de nettoyer la base des doublons et reconstruire les index ?
 
Merci pour votre aide.
Cordialement,  

Reply

Marsh Posté le 04-05-2011 à 09:07:00   

Reply

Marsh Posté le 04-05-2011 à 10:35:15    

Charger "à la brute" dans une table temporaire, puis faire un insert des lignes uniques dans la table réelle?

Message cité 1 fois
Message édité par skeye le 04-05-2011 à 10:35:24

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 04-05-2011 à 10:51:44    

skeye a écrit :

Charger "à la brute" dans une table temporaire, puis faire un insert des lignes uniques dans la table réelle?


 
Ca se tente, tu peux me donner la syntaxe ?
 
Merci
 
@+ tard

Reply

Marsh Posté le 04-05-2011 à 11:00:45    

nicomes a écrit :


 
Ca se tente, tu peux me donner la syntaxe ?
 
Merci
 
@+ tard


 
Tu crées une table temporaire à l'image de ta table de prod, tu fais remplir cette nouvelle table au lieu de l'autre dans ton sqlloader, et ensuite c'est un bête insert du style

Code :
  1. INSERT INTO matabledeprod
  2. SELECT DISTINCT *
  3. FROM matabletemporaire


(S'il y a lieu tu fais aussi attention à ne prendre que les lignes de la table temp qui ne sont pas déjà dans l'autre :o)


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 04-05-2011 à 11:08:14    

skeye a écrit :


 
Tu crées une table temporaire à l'image de ta table de prod, tu fais remplir cette nouvelle table au lieu de l'autre dans ton sqlloader, et ensuite c'est un bête insert du style

Code :
  1. INSERT INTO matabledeprod
  2. SELECT DISTINCT *
  3. FROM matabletemporaire


(S'il y a lieu tu fais aussi attention à ne prendre que les lignes de la table temp qui ne sont pas déjà dans l'autre :o)


 
 
Ok, merci bien. Nous allons tenter ça. Je te tiens au courant.
 
@+

Reply

Marsh Posté le 04-05-2011 à 11:17:58    

quand tu mets l'option "direct=true" tu spécifies de ne pas mettre à jour les indexes : ca permet d'insérer plus rapidement
 
du coup après ton chargement, tu dois recontruire tes indexes avec "alter index ... rebuild;"

Reply

Marsh Posté le 04-05-2011 à 11:21:13    

si tu ne souhaites pas passer par une table temporaire, il faut faire une requête de suppression des doublons avant la reconstruction des indexes

Reply

Marsh Posté le 04-05-2011 à 11:27:36    

couak a écrit :

quand tu mets l'option "direct=true" tu spécifies de ne pas mettre à jour les indexes : ca permet d'insérer plus rapidement
 
du coup après ton chargement, tu dois recontruire tes indexes avec "alter index ... rebuild;"


 
On a essayé, mais nous avons eu un message nous indiquant que c'était impossible car la table contenait des des doublons ...

Reply

Marsh Posté le 04-05-2011 à 11:32:58    

couak a écrit :

si tu ne souhaites pas passer par une table temporaire, il faut faire une requête de suppression des doublons avant la reconstruction des indexes


 
Nous avons essayé une requête de suppression mais ce n'est pas très concluant, peut-être qu'on s'y prend mal. Aurais-tu un exemple s'il te plait ?
 
Merci à tous, c'est super sympa !

Reply

Marsh Posté le 04-05-2011 à 13:09:41    

oui, par exemple supprimer les doublons nom/prénom de la table PERSONNE :

Code :
  1. DELETE PERSONNE a
  2. WHERE rowid > (
  3. SELECT min(rowid)
  4. FROM PERSONNE b
  5. WHERE b.nom = a.nom AND
  6. b.prenom = a.prenom
  7. );

Reply

Marsh Posté le 04-05-2011 à 13:09:41   

Reply

Marsh Posté le 04-05-2011 à 13:46:51    

couak a écrit :

oui, par exemple supprimer les doublons nom/prénom de la table PERSONNE :

Code :
  1. DELETE PERSONNE a
  2. WHERE rowid > (
  3. SELECT min(rowid)
  4. FROM PERSONNE b
  5. WHERE b.nom = a.nom AND
  6. b.prenom = a.prenom
  7. );



 
euh, j'ai un doute sur ta requête, là...tu vas supprimer toutes les lignes dont le rowid est supérieur à celui d'un doublon, non?[:dawao]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 04-05-2011 à 14:08:39    

C un win win!
T'as plus de doublons et t'as vachement moins de données a gerer :)
 
Sinon un moyen generique et rapide de se debarasser des doublons est de faire un join de la table avec elle meme et virer tout ce qui a un count > 2.
Ca prends 2 table scan.
 
Si la table est tres grosse il y a moyen de faire la meme chose en petit morceau en construisant une table temporaire avec les ID des doublons et faire un delete top xxx avec un join sur la table temporaire. Faut un index sur l'ID sinon ca prends 2 plombes.

Reply

Marsh Posté le 04-05-2011 à 14:16:44    

skeye a écrit :


 
euh, j'ai un doute sur ta requête, là...tu vas supprimer toutes les lignes dont le rowid est supérieur à celui d'un doublon, non?[:dawao]


non non :o

Reply

Marsh Posté le 04-05-2011 à 14:18:14    


Ben....si...?
Ou alors ya un truc que je rate dans ta syntaxe...


Message édité par skeye le 04-05-2011 à 14:18:56

---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 04-05-2011 à 16:42:41    

tu n'as qu'à tester...
Pour moi il parcourt toute la table, et supprime chaque ligne dont le rowid est supérieur au plus petit rowid correspondant au couple nom/prenom i.e. parcours de la table et suppression de chaque doublon basé sur nom/prénom
 
J'ai toujours fait comme cela et ça marche
Je viens de retester sur une base oracle, j'ai pas de soucis
 

Code :
  1. CREATE TABLE personne (
  2.  nom varchar2(20),
  3.  prenom varchar2(20)
  4. );
  5.  
  6. INSERT INTO personne VALUES ('a', 'a');
  7. INSERT INTO personne VALUES ('a', 'b');
  8. INSERT INTO personne VALUES ('a', 'a');
  9. INSERT INTO personne VALUES ('a', 'b');
  10. INSERT INTO personne VALUES ('a', 'b');
  11. INSERT INTO personne VALUES ('a', 'a');
  12. INSERT INTO personne VALUES ('b', 'a');
  13. INSERT INTO personne VALUES ('b', 'a');
  14. INSERT INTO personne VALUES ('a', 'b');
  15. INSERT INTO personne VALUES ('a', 'a');
  16. INSERT INTO personne VALUES ('a', 'a');
  17. commit;
  18.  
  19. -- affiche les doublons
  20. SELECT a.rowid, a.nom, a.prenom
  21. FROM
  22.  personne a
  23. WHERE
  24.  a.rowid > (SELECT min(rowid) FROM personne b WHERE a.nom=b.nom AND a.prenom=b.prenom)

Message cité 1 fois
Message édité par couak le 04-05-2011 à 16:42:53
Reply

Marsh Posté le 04-05-2011 à 16:57:50    

couak a écrit :

tu n'as qu'à tester...


Je viens de tester, effectivement ça fonctionne...je ne comprends toujours pas la logique de la syntaxe, mais c'est pas grave.[:doc petrus]
Chez moi la version compréhensible pour ça c'est :
 

Code :
  1. DELETE FROM personne
  2. WHERE rowid NOT IN (
  3. SELECT a.rowid
  4. FROM
  5.  personne a
  6. WHERE
  7.  a.rowid = (SELECT min(rowid) FROM personne b WHERE a.nom=b.nom AND a.prenom=b.prenom)
  8. );


 
[:tinostar]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 04-05-2011 à 17:08:05    

ca marche aussi mais tu fais 3 accès complet à la table :) confirmé en regardant le plan d'exécution

Reply

Marsh Posté le 04-05-2011 à 17:09:14    

Ah mais j'ai pas dit que c'était plus rapide, j'ai dit que je comprenais pourquoi ça fonctionne.[:joce]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 05-05-2011 à 07:11:47    

Dans tous les cas, moi ça me convient vos requêtes. Nous allons tester ça aujourd'hui ! Un grand merci. Je vous tiens au courant.


Message édité par nicomes le 05-05-2011 à 07:12:14
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed