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