Con quale frequenza verrà eseguito un trigger FOR EACH STATEMENT se l'operazione è causata da un vincolo FK con UPDATE CASCADE?


11

Comprendo che un trigger sulla tabella t definito con FOR EACH STATEMENTverrà eseguito una volta quando eseguo un UPDATE t ....

Ora, quando tviene definito con FOREIGN KEY ... REFERENCES a ... ON UPDATE CASCADEe aggiorno N righe in a, ciò causerà la chiamata del trigger una volta o N volte?

In altre parole, le modifiche a una tabella messe in cascata da un vincolo FK sono più simili a una singola UPDATEo più a una serie di UPDATEs?


4
È possibile creare un caso di prova! Inserisci in un'altra tabella nel corpo del trigger e vedi quante righe ottieni. Quindi scrivilo nella tua risposta a questa domanda (è permesso, anche incoraggiato)!
Colin 't Hart,

2
La frase principale che menziona FOR EACH STATEMENTè ortogonale al resto della domanda. I vincoli FK sono implementati con trigger speciali FOR EACH ROW.
Erwin Brandstetter,

1
@Erwin "FOR EACH ROW of a" o "FOR EACH ROW of t"?
ypercubeᵀᴹ

@ypercube: ho aggiunto una risposta con i dettagli.
Erwin Brandstetter,

Risposte:


6

I vincoli di chiave esterna sono attualmente implementati con speciali trigger interni. Sono tutti in esecuzione FOR EACH ROW.

Nota che questi sono dettagli di implementazione che possono cambiare, quindi non fare affidamento su di esso. Ma le basi non sono cambiate rispetto alle ultime due versioni principali, quindi è improbabile che si verifichino cambiamenti importanti.

Ho eseguito un test rapido con un semplice vincolo FK da tbla tbltype. Un semplice FK è implementato con quattro semplici trigger interni FOR EACH ROWnel mio test a pag 9.4.
Ecco una breve rassegna su come indagare:

SELECT oid  -- 74791
FROM   pg_constraint
WHERE  conrelid = 'tbl'::regclass
AND    contype = 'f';

SELECT objid, classid::regclass  -- 74792,74793,74794,74795 / 'pg_trigger'
FROM   pg_depend
WHERE  refobjid = 74791
AND   deptype = 'i'

SELECT tgrelid::regclass, tgname, tgfoid, tgtype FROM pg_trigger
WHERE  oid IN (74792,74793,74794,74795) ORDER BY tgfoid;

'tbl'    ;'RI_ConstraintTrigger_c_74794';1644;5
'tbl'    ;'RI_ConstraintTrigger_c_74795';1645;17
'tbltype';'RI_ConstraintTrigger_a_74792';1654;9
'tbltype';'RI_ConstraintTrigger_a_74793';1655;17

SELECT oid, proname FROM pg_proc
WHERE oid IN (1654,1655,1644,1645);

1644;'RI_FKey_check_ins'
1645;'RI_FKey_check_upd'
1654;'RI_FKey_noaction_del'
1655;'RI_FKey_noaction_upd'

Si attivano due "noazioni" interne tbltype.
Si attivano due "controlli" interni tbl.
Vengono eseguiti tutti FOR EACH ROW, come indicato dai numeri dispari in tgtype.

I 2 byte di Postgres tgtype smallintrappresentano un int16codice sorgente in C in cui codifica il bit meno significativo TRIGGER_TYPE_ROW. Spiegazione dettagliata qui:

Puoi facilmente testarlo con una coppia di trigger identici in cui cambi solo FOR ROW/ STATEMENT...


5

Esegue N volte e il modo più semplice per vederlo è eseguire l'istruzione con un EXPLAIN ANALYZEanteposto, ovvero

EXPLAIN ANALYZE UPDATE a SET col = 1 WHERE othercol = 'foo';

Questo ti darà informazioni simili a questa:

Trigger for constraint t_col_fk on a: time=1.300 calls=9

(testato con 9.2)


1
Questo è in qualche modo sorprendente per me. Testato su 9.4 con gli stessi risultati.
dezso,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.