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).

#1 Re : Général » Meilleure implémentation d'une CTE récursive en while loop » 04/12/2023 13:01:03

Merci pour la réponse. Il y a des instances où la première prend autour 20s et la deuxième autour de 100s. La raison d'utiliser plpgsql est que c'est plus expressif que les CTE récursifs où on ne peut pas mettre la variable récursive dans une sous requête.

#2 Général » Meilleure implémentation d'une CTE récursive en while loop » 01/12/2023 20:29:25

postgresqlforumuser
Réponses : 2

Bonjour,

J'ai deux requêtes qui calculent une cloture transitive sur un graphe. La première utilise une CTE recursive et la deuxième utilise une boucle WHILE. La première est beaucoup plus rapide que la deuxième. Je voudrais savoir s'il est possible d'améliorer la boucle WHILE pour avoir les mêmes performances.

Voici la première requête:

CREATE TEMPORARY VIEW const_subquery2 AS
  (SELECT src AS x, trg AS col1 FROM graph AS t WHERE predicate = '<p>');
CREATE TEMPORARY RECURSIVE VIEW fixpoint_relation1_X3 (x) AS
    SELECT src AS x FROM graph WHERE trg = '<T>' AND predicate = '<p>'
  UNION 
    SELECT x FROM (SELECT x AS col1 FROM fixpoint_relation1_X3) AS t NATURAL JOIN const_subquery2;
SELECT COUNT(*) FROM (SELECT DISTINCT * FROM (SELECT * FROM fixpoint_relation1_X3) AS t) as t3;

Voici la deuxième requête:

CREATE TEMPORARY VIEW const_subquery2 AS
  (SELECT src AS x, trg AS col1 FROM graph WHERE predicate = '<p>');
DO $$BEGIN
CREATE TEMPORARY TABLE fixpoint_tmp AS
  (SELECT src AS x FROM graph WHERE trg = '<T>' AND predicate = '<p>');
CREATE TEMPORARY TABLE fixpoint_relation1_X3 AS (SELECT * FROM fixpoint_tmp);
WHILE EXISTS (SELECT 1 FROM fixpoint_relation1_X3) LOOP
  CREATE TEMPORARY TABLE nouvelles AS
    (SELECT x FROM (SELECT x AS col1 FROM fixpoint_relation1_X3) AS t NATURAL JOIN const_subquery2 EXCEPT SELECT * FROM fixpoint_tmp);
  INSERT INTO fixpoint_tmp (SELECT * FROM nouvelles);
  DROP TABLE fixpoint_relation1_X3;
  ALTER TABLE nouvelles RENAME TO fixpoint_relation1_X3;
END LOOP;
DROP TABLE fixpoint_relation1_X3;
ALTER TABLE fixpoint_tmp RENAME TO fixpoint_relation1_X3;
END;$$;
SELECT COUNT(*) FROM (SELECT DISTINCT * FROM (SELECT * FROM fixpoint_relation1_X3) AS t) as t3;

Pied de page des forums

Propulsé par FluxBB