bonjour

j'ai un requete assez complexe, qui prend pas mal de temps, et pourtant si je le fais en 2 fois via une table temporaire, c'est instantané


dans les 2 cas j'ai le meme with au dessus :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
WITH 
	ListePlanning(Numero, IdPlanning, IdArticle)
	AS (SELECT  ROW_NUMBER() OVER (ORDER BY Planning.IdPlanning, Planning.OrderToUse DESC), Planning.idPlanning, Planning.IdArticle FROM Planning) 
,
 
	ListeArticlesUtilisesPourPlanning (IdPlanning, IdArticle) -- pour chaque planning, l'article du planning et les articles en provenance
	AS (SELECT Planning.IdPlanning, Planning.IdArticle FROM Planning 
		UNION SELECT Planning.IdPlanning, PlanningProv.IdArticle FROM Planning INNER JOIN PlanningProv ON Planning.IdPlanning = PlanningProv.IdPlanning)
,
 
	ListeIncompatibilites (IdArticle, IdArticleInterdit, NbBatch, IdIncompatibilite) -- ne contient que des isarticles (soit direct soit pris dans les regroupements définis)
				-- article à fabriquer, article précédent interdit, nombre entre chaque requis
	AS (SELECT case when vueFab.IdArticle IS NULL then IncompatibiliteDefinition.IdArticle else vueFab.IdArticle end as c1, 
				case when vueInterdit.IdArticle IS NULL then IncompatibiliteInterdite.IdArticle else vueInterdit.IdArticle end as c2,
				IncompatibiliteInterdite.NbBatch, IncompatibiliteDefinition.IdIncompatibilite
			FROM  IncompatibiliteDefinition	
				LEFT JOIN ArticleGetArticleEtRegroupements vueFab		ON vueFab.IdRegroupement = IncompatibiliteDefinition.IdArticle
				INNER JOIN IncompatibiliteInterdite		ON IncompatibiliteDefinition.IdIncompatibilite = IncompatibiliteInterdite.IdIncompatibilite
				LEFT JOIN ArticleGetArticleEtRegroupements vueInterdit	ON vueInterdit.IdRegroupement = IncompatibiliteInterdite.IdArticle
			)

1ère méthode : je tente de faire un select direct de ce que je veux

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
--  WITH mis au dessus
 
SELECT PlanningCourant.IdPlanning , ListeIncompatibilites.IdIncompatibilite, ListeIncompatibilites.IdArticle, ListeIncompatibilites.IdArticleInterdit
, ArticleFab.Code, ArticlePasse.Code
 
	FROM Planning PlanningCourant
		INNER JOIN ListePlanning						ON PlanningCourant.IdPlanning = ListePlanning.IdPlanning
		INNER JOIN ListePlanning TrouvePrecedent		ON TrouvePrecedent.Numero = ListePlanning.Numero - 1
		INNER JOIN Planning PlanningPrecedent			ON PlanningPrecedent.IdPlanning = TrouvePrecedent.IdPlanning -- récupération pour chaque idplanning, l'idplanning précédent
		INNER JOIN ListeArticlesUtilisesPourPlanning lc	ON lc.IdPlanning = PlanningCourant.IdPlanning
		INNER JOIN ListeArticlesUtilisesPourPlanning lp ON lp.IdPlanning = PlanningPrecedent.IdPlanning
		INNER JOIN ListeIncompatibilites				ON lc.IdArticle = ListeIncompatibilites.IdArticle
														AND lp.IdArticle = ListeIncompatibilites.IdArticleInterdit
		INNER JOIN Article ArticleFab					ON ArticleFab.IdArticle = ListeIncompatibilites.IdArticle
		INNER JOIN Article ArticlePasse					ON ArticlePasse.IdArticle = ListeIncompatibilites.IdArticleInterdit

2 ème méthode : je retire 2 jointures sur la table Article et je passe par une table @


Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
DECLARE @IncompatibiliteTable table 
	(IdPlanning bigint, IdIncompatibilite bigint, IdArticle bigint, IdArticleInterdit bigint)
 
--  WITH mis au dessus
 
INSERT INTO @IncompatibiliteTable
 
SELECT PlanningCourant.IdPlanning , ListeIncompatibilites.IdIncompatibilite, ListeIncompatibilites.IdArticle, ListeIncompatibilites.IdArticleInterdit
 
	FROM Planning PlanningCourant
		INNER JOIN ListePlanning						ON PlanningCourant.IdPlanning = ListePlanning.IdPlanning
		INNER JOIN ListePlanning TrouvePrecedent		ON TrouvePrecedent.Numero = ListePlanning.Numero - 1
		INNER JOIN Planning PlanningPrecedent			ON PlanningPrecedent.IdPlanning = TrouvePrecedent.IdPlanning -- récupération pour chaque idplanning, l'idplanning précédent
		INNER JOIN ListeArticlesUtilisesPourPlanning lc	ON lc.IdPlanning = PlanningCourant.IdPlanning
		INNER JOIN ListeArticlesUtilisesPourPlanning lp ON lp.IdPlanning = PlanningPrecedent.IdPlanning
		INNER JOIN ListeIncompatibilites				ON lc.IdArticle = ListeIncompatibilites.IdArticle
														AND lp.IdArticle = ListeIncompatibilites.IdArticleInterdit
 
 
select tmp.*, ArticleFab.Code, ArticlePasse.Code
	FROM @IncompatibiliteTable tmp
		INNER JOIN Article ArticleFab					ON ArticleFab.IdArticle = tmp.IdArticle
		INNER JOIN Article ArticlePasse					ON ArticlePasse.IdArticle = tmp.IdArticleInterdit

on répète souvent que les tables temporaires ralentissent les traitements, que des lectures sont plus performantes donc j'ai essayé de décomposer mon traitement en plusieurs sous requetes

dans le 1er cas, je retrouve 2 IdArticle, et je fais une jointure sur la table article pour retrouver le code de l'article
ca prend des 10aines de secondes

dans le 2eme cas, je stocke le résultat et donc les 2 IdArticle dans une table temporaire, puis je fais un select de cette table temporaire avec la table article pour avoir le Code
c'est instantané

ma table article comporte 300 ligne

si quelqu'un peut m'expliquer pourquoi sql server s'emmele les pinceaux avec ma requete ...