PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#26 11/05/2012 17:19:22

rjuju
Administrateur

Re : bulk collect

Quel est le message d'erreur renvoyé ?
Avez-vous regardé dans la vue pg_stat_activity s'il n'y avait pas des choses étranges ?

Hors ligne

#27 11/05/2012 17:21:23

karthus
Membre

Re : bulk collect

Je n'ai aucun message d'erreur , au bout de 10min j'ai fais un ctrl - C , pour 1 update je pense que sa fait beaucoup. Oui je l'ai fais , rien d'étrange , je peux faire un delete mais pas de drop , ni utiliser mes fonctions , par contre les autres tables oui.

Hors ligne

#28 11/05/2012 17:36:53

rjuju
Administrateur

Re : bulk collect

Il y a forcément une transaction qui bloque.
Vous pouvez redémarrer votre service postgres si personne ne l'utilise pour être certain de couper toutes les connexions.

Hors ligne

#29 11/05/2012 17:46:49

karthus
Membre

Re : bulk collect

Il ne me reste que 15min donc je vais m'occuper d'autre chose , je verrais sa après le week end.

Hors ligne

#30 14/05/2012 10:22:04

karthus
Membre

Re : bulk collect

J'ai trouvé la table qui me bloque, il s'agit de t_ref_ett , en utilisant la table pg_locks j'obtiens:
          relname           |        mode         | granted |  pid
-----------------------------------+--------------------------+---------+-------
pk_t_entcdecli                       | AccessShareLock        | t          |  6320
pg_class_relname_nsp_index | AccessShareLock         | t          | 13590
t_ref_ett                               | AccessExclusiveLock    | f          | 29689
pk_t_ref_ett                          | AccessShareLock         | t          |  6320
pg_locks                               | AccessShareLock         | t         | 13590
ak_cle_2_t_entcde                 | AccessShareLock        | t          |  6320
pg_class                               | AccessShareLock         | t         | 13590
t_ref_ett                               | AccessShareLock         | f         | 11354
tmp_entcdecli                       | AccessShareLock         | t          |  6320
t_ref_ett                               | AccessShareLock         | t         |  6320
ak_cle_unicite_t_ref_et          | AccessShareLock         | t         |  6320
t_ref_ett                               | AccessExclusiveLock    | f         | 22781
t_ref_ett                               | AccessExclusiveLock    | f         |  9346
t_entcdecli                            | AccessShareLock         | t         |  6320
pg_class_oid_index               | AccessShareLock          | t        | 13590

Hors ligne

#31 14/05/2012 10:48:16

karthus
Membre

Re : bulk collect

La table sur laquelle je travaille utilise cette table de référence t_ref_ett , tout bêtement , j'ai donc fait un kill car apparemment il y avait une procédure stockée qui ne s'était pas arrété.

Hors ligne

#32 14/05/2012 15:04:13

karthus
Membre

Re : bulk collect

En essayant une autre méthode j'ai remarqué que mon cursor met 20min au moins les 25 pour se créer , et le lire ligne par ligne puis de faire un update à chaque ligne d'une colonne état qui par la suite servira à savoir s'il faut faire un traitement sur cette ligne. Est-ce normal que ce soit aussi long?

Hors ligne

#33 14/05/2012 15:26:02

Marc Cousin
Membre

Re : bulk collect

Bonjour,

J'ai du mal à comprendre: c'est le select générant le curseur qui met 20 minutes pour se créer ? Que voulez-vous dire par là ?

Sinon, vu qu'on n'a qu'un exemple assez vague de ce que vous faites réellement, le bout de code qui fait les mises à jour de la table ne serait pas dans un sous-bloc begin/end (ou une fonction distincte?) avec un bloc d'exception ?


Marc.

Hors ligne

#34 14/05/2012 15:37:08

karthus
Membre

Re : bulk collect

Voici mon code très barbare , la fonction met 26min pour s'executer , suite à cela dans ma table temporaire les colonnes concerné auront comme etat_int la valeur 3 , je fais donc un copy ... to , puis en copy ... from (3sec au total pour 72000 , les 2 copy au total ) mais le curseur est beaucoup trop long. Si vous avez besoin d'autres infos...Par contre je ne pense pas que je laisserai le code longtemps sur le forum.

/* delete */

Dernière modification par karthus (22/05/2012 09:25:26)

Hors ligne

#35 14/05/2012 15:45:42

Marc Cousin
Membre

Re : bulk collect

Sur l'update, je vois déjà 2 problèmes possibles «évidents»:
- Les OID ne sont pas indexés par défaut. Votre where oid=rowids fait un seqscan, à moins que vous n'ayez mis un index ? (vu que vous créez un autre index plus haut pour cette table, et qu'elle a tmp_ dans le nom, je préfère poser la question)
- Les OID ne doivent plus être utilisés dans des tables utilisateur (c'est déconseillé).

Sinon, avez vous regardé le temps d'exécution, et le plan, du select utilisé par le curseur ? Si oui, vous pouvez le poster aussi.


Marc.

Hors ligne

#36 14/05/2012 15:57:57

karthus
Membre

Re : bulk collect

Effectivement le problème vient de l'update , j'ai exécuté ma fonction sans , le résultat est de 1 sec.
Le seul index que j'ai est celui de la fonction qui crée au début et supprimé à la fin.
Pour l'oid il y était de base donc je préfère le laisser au moins pour l'instant , s'il faut faire sans je verrai plus tard si je peux l'enlever.
Et pour le explain j'obtiens:
Merge Join  (cost=44791.38..47440.74 rows=119009 width=139)
   Merge Cond: ((t_ref_ett.cod_typett = tmp_entcdecli.num_typett) AND (t_ref_ett.num_bu = tmp_entcdecli.num_bu) AND (t_ref_ett.num_ett = tmp_entcdecli.num_ett))
   ->  Sort  (cost=17.26..17.74 rows=193 width=39)
         Sort Key: t_ref_ett.cod_typett, t_ref_ett.num_bu, t_ref_ett.num_ett
         ->  Seq Scan on t_ref_ett  (cost=0.00..9.93 rows=193 width=39)
   ->  Sort  (cost=44774.13..45138.59 rows=145787 width=160)
         Sort Key: tmp_entcdecli.num_typett, tmp_entcdecli.num_bu, tmp_entcdecli.num_ett
         ->  Seq Scan on tmp_entcdecli  (cost=0.00..8351.34 rows=145787 width=160)
               Filter: (etat_int <> 1::numeric)

Hors ligne

#37 14/05/2012 16:05:56

karthus
Membre

Re : bulk collect

Le problème vient du WHERE OID = ROWIDS; mais comment faire autrement? Je dois bien faire un update ligne par ligne , et sur les bonnes tant qu'à faire.

Hors ligne

#38 14/05/2012 16:37:58

rjuju
Administrateur

Re : bulk collect

Il faudrait utiliser la clé primaire de la table pour effectuer l'update, ou ajouter un index à l'oid.

Dernière modification par rjuju (14/05/2012 16:38:45)

Hors ligne

#39 14/05/2012 16:44:58

karthus
Membre

Re : bulk collect

Justement c'est là où c'est drôle , car il n'y en a pas. Aucune clé primaire , aucune contrainte d'unicité , les tables temporaires sont juste des colonnes qu'on insérera dans la table principale en ajoutant une colonne qui contiendra la clé primaire , donc inutile pour moi à ce stade.
Pour l'index j'ai mis CREATE INDEX I_TMP_ENTCDECLI on TMP_ENTCDECLI(NUM_ETT, NUM_BU, NUM_TYPETT, NUM_CDECLI, DAT_CREPROD,OID).
La fonction vient juste de finir , cela m'a pris 9,5min , sa moins de la moitié du temps initial. big_smile

Dernière modification par karthus (14/05/2012 16:47:00)

Hors ligne

#40 14/05/2012 16:57:25

Marc Cousin
Membre

Re : bulk collect

Vous pouvez essayer encore plus agressif, puisque je présume que vous n'aurez qu'un seul de ces traitements à la fois:

rajoutez TMP_ENTCDECLI.ctid dans votre curseur, et utilisez ce champ pour la mise à jour. C'est l'adresse physique de l'enregistrement. Évidemment, après avoir fait l'update l'adresse de l'enregistrement risque de changer, mais vu l'exemple, ça ne devrait pas poser problème.


Marc.

Hors ligne

#41 14/05/2012 16:58:54

Marc Cousin
Membre

Re : bulk collect

Évidemment, dans ce cas, l'update devient

     UPDATE TMP_ENTCDECLI
        SET   ETAT_INT = 3
        WHERE ctid = mon_ctid_que_j_ai_recupere_dans_mon_fetch

Marc.

Hors ligne

#42 14/05/2012 17:10:01

karthus
Membre

Re : bulk collect

Pourquoi n'y était-il pas de base sur le script oracle alors? Il n'y en a pas besoin?
Désolé mais bon je débute , et même après avoir lu la doc sur l'index j'ai un peu de mal à accrocher.

Hors ligne

#43 14/05/2012 17:17:20

Marc Cousin
Membre

Re : bulk collect

Sur le script oracle, il ne pouvait pas y être, il n'y a pas d'oid. Je ne sais pas comment fonctionnait le script oracle, mais je présume que ça devait être similaire, il devait y avoir une clé quelconque sur la table pour retrouver l'enregistrement.


Marc.

Hors ligne

#44 14/05/2012 17:23:18

karthus
Membre

Re : bulk collect

C'est exactement la même table , et il y a un oid , ou plutôt un rowid , d'où le WHERE OID = ROWIDS; car à la base c'était WHERE ROWID = ROWIDS; enfin bref. Je testerai demain si possible avec le contenu total de la base oracle , soit des millions de lignes et je verrais le résultat. En tout cas merci beaucoup pour votre patiente et votre aide.
PS: 72000 insert en 591445ms ( soit 9,8min ) au lieu de ~27min wink

Dernière modification par karthus (14/05/2012 17:24:48)

Hors ligne

#45 14/05/2012 17:33:48

Marc Cousin
Membre

Re : bulk collect

ben le rowid correspond exactement au ctid dont je parle au dessus. À la différence que sous PostgreSQL un update peut modifier un ctid, alors que le rowid est conservé sous Oracle.


Marc.

Hors ligne

Pied de page des forums