Vous n'êtes pas identifié(e).
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 ?
Julien.
https://rjuju.github.io/
Hors ligne
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
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.
Julien.
https://rjuju.github.io/
Hors ligne
Il ne me reste que 15min donc je vais m'occuper d'autre chose , je verrais sa après le week end.
Hors ligne
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
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
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
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
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
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
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
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
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)
Julien.
https://rjuju.github.io/
Hors ligne
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.
Dernière modification par karthus (14/05/2012 16:47:00)
Hors ligne
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
É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
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
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
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
Dernière modification par karthus (14/05/2012 17:24:48)
Hors ligne
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