J'ai un déclencheur qui exécute une fonction sur l'insertion ou la mise à jour de la table. Cela ressemble à ceci:Différence de Postgres dans la vitesse d'exécution du déclencheur?
CREATE OR REPLACE FUNCTION func_fk_location_area()
RETURNS "trigger" AS $$
BEGIN
IF EXISTS (
-- there was a row valid in area when location started
SELECT * FROM location
WHERE NOT EXISTS (
SELECT * FROM area
WHERE area.key=location.key
AND area.id=location.area_id
AND ( (area.tr_from<=location.tr_from AND area.tr_until>location.tr_from) OR
(area.tr_from=location.tr_from AND area.tr_until=location.tr_from)))
) OR EXISTS (
-- there was a row valid in area when location ended
SELECT * FROM location
WHERE NOT EXISTS (
SELECT * FROM area
WHERE area.key=location.key
AND area.id=location.area_id
AND ( (area.tr_from<location.tr_until AND area.tr_until>=location.tr_until) OR
(area.tr_from=location.tr_until AND area.tr_until=location.tr_until)))
)
THEN
RAISE EXCEPTION 'FK location_area integrity violation.';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_fk_area_location AFTER DELETE OR UPDATE ON area
FOR EACH ROW EXECUTE PROCEDURE func_fk_location_area();
CREATE TRIGGER trigger_fk_location_area AFTER INSERT OR UPDATE ON location
FOR EACH ROW EXECUTE PROCEDURE func_fk_location_area();
Lorsque j'insère une ligne, elle semble fonctionner très lentement. En utilisant l'analyse d'explication, j'ai déterminé que ce déclencheur prenait près de 400 ms à compléter. Cependant, si j'exécute les deux lots de SQL dans la fonction, ils ne prennent chacun que 3 ou 4ms pour s'exécuter!
PREMIERE PARTIE:
mydb=# explain analyze
mydb-# SELECT * FROM location
mydb-# WHERE NOT EXISTS (
mydb(# SELECT * FROM area
mydb(# WHERE area.key=location.key
mydb(# AND area.id=location.area_id
mydb(# AND ( (area.tr_from<location.tr_until AND area.tr_until>=location.tr_until) OR
mydb(# (area.tr_from=location.tr_until AND area.tr_until=location.tr_until)));
Hash Anti Join (cost=14.68..146.84 rows=1754 width=126) (actual time=5.512..5.512 rows=0 loops=1)
Hash Cond: ((location.key = area.key) AND (location.area_id = area.id))
Join Filter: (((area.tr_from < location.tr_until) AND (area.tr_until >= location.tr_until)) OR ((area.tr_from = location.tr_until) AND (area.tr_until = locat
ion.tr_until)))
-> Seq Scan on location (cost=0.00..79.91 rows=2391 width=126) (actual time=0.005..1.016 rows=2393 loops=1)
-> Hash (cost=8.87..8.87 rows=387 width=37) (actual time=0.497..0.497 rows=387 loops=1)
-> Seq Scan on area (cost=0.00..8.87 rows=387 width=37) (actual time=0.004..0.250 rows=387 loops=1)
Total runtime: 5.562 ms
(7 rows)
deuxième partie:
mydb=# explain analyze
mydb-# SELECT * FROM location
mydb-# WHERE NOT EXISTS (
mydb(# SELECT * FROM area
mydb(# WHERE area.key=location.key
mydb(# AND area.id=location.area_id
mydb(# AND ( (area.tr_from<location.tr_until AND area.tr_until>=location.tr_until) OR
mydb(# (area.tr_from=location.tr_until AND area.tr_until=location.tr_until)));
Hash Anti Join (cost=14.68..146.84 rows=1754 width=126) (actual time=5.666..5.666 rows=0 loops=1)
Hash Cond: ((location.key = area.key) AND (location.area_id = area.id))
Join Filter: (((area.tr_from < location.tr_until) AND (area.tr_until >= location.tr_until)) OR ((area.tr_from = location.tr_until) AND (area.tr_until = locat
ion.tr_until)))
-> Seq Scan on location (cost=0.00..79.91 rows=2391 width=126) (actual time=0.005..1.072 rows=2393 loops=1)
-> Hash (cost=8.87..8.87 rows=387 width=37) (actual time=0.509..0.509 rows=387 loops=1)
-> Seq Scan on area (cost=0.00..8.87 rows=387 width=37) (actual time=0.007..0.239 rows=387 loops=1)
Total runtime: 5.725 ms
(7 rows)
Cela fait aucun sens pour moi.
Des pensées?
Merci.
Vous n'utilisez pas de clés étrangères, mais émulez un fk avec un trigger trigger? Si oui, pourquoi? – Kuberchaun
Pour une bonne habitude, changez votre * en quelque chose comme 'X'. Nous marquons tous les * dans les révisions de code et ne laissons pas passer cette révision même si la performance n'est pas affectée. – Kuberchaun
Pouvons-nous voir votre code avec POUR CHAQUE DÉCLARATION et l'expliquer? – Kuberchaun