Appel de la fonction table T-SQL plusieurs fois plus rapide que l'appel une fois?

Je suis confus par quelque chose. J'utilise T-SQL et j'essaie d'optimiser le code qui ressemble à ceci:

SELECT * FROM MyTable mt LEFT JOIN (SELECT * FROM Table1 t1 LEFT JOIN api.tableValuedFunc(@someArgs) tvf on tvf.Key = t1.Key) firstJoin on mt.Key = firstJoin.key LEFT JOIN (SELECT * FROM Table2 t2 LEFT JOIN api.tableValuedFunc(@someArgs) tvf on tvf.Key = t2.Key) secondJoin on mt.Key = secondJoin.key 

en faisant cela:

 declare @tvfResult TABLE ( ... some columns ... ) insert into @tvfResults SELECT * FROM api.tableValuedFunc(@someArgs); SELECT * FROM MyTable mt LEFT JOIN (SELECT * FROM Table1 t1 LEFT JOIN @tvfResults tvf on tvf.Key = t1.Key) firstJoin on mt.Key = firstJoin.key LEFT JOIN (SELECT * FROM Table2 t2 LEFT JOIN @tvfResults tvf on tvf.Key = t2.Key) secondJoin on mt.Key = secondJoin.key 

Cela double le time d'exécution! Pourquoi est-ce? Dans le deuxième exemple, je suppose (naïvement) que j'exécute la moitié de la fonction aussi souvent. Y at-il une sorte de magie SQL qui se passe derrière les scènes que je suis en train de ruiner?

Au lieu de créer une variable de table, créer une table temporaire locale peut améliorer les performances si elle génère un grand nombre de lignes.

 create table #tvfResult ( ... some columns ... ) insert into #tvfResults SELECT * FROM api.tableValuedFunc(@someArgs); SELECT * FROM MyTable mt LEFT JOIN (SELECT * FROM Table1 t1 LEFT JOIN #tvfResults tvf on tvf.Key = t1.Key) firstJoin on mt.Key = firstJoin.key LEFT JOIN (SELECT * FROM Table2 t2 LEFT JOIN #tvfResults tvf on tvf.Key = t2.Key) secondJoin on mt.Key = secondJoin.key 

Les tables temporaires locales sont visibles uniquement pour leurs créateurs lors de la même connection à une instance de SQL Server que lorsque les tables ont été créées ou référencées pour la première fois. Les tables temporaires locales sont supprimées après que l'user se soit déconnecté de l'instance de SQL Server.

Déposez la table temporaire explicitement si vous réexécutez la requête avec la même session.

 drop table #tvfResult 

Notez que, sauf si vous avez omis plusieurs facteurs critiques de votre question, votre première requête se réduit à:

 SELECT * FROM MyTable mt LEFT JOIN Table1 t1 on mt.Key = t1.key LEFT JOIN Table2 t2 on mt.Key = t2.key LEFT JOIN api.tableValuedFunc(@someArgs) tvf1 on tvf1.Key = t1.key LEFT JOIN api.tableValuedFunc(@someArgs) tvf2 on tvf2.Key = t2.key 

Maintenant, l'parsing se réduit à ce que votre sélection de colonne est dans la clause SELECT – s'il vous plaît fournir ces détails car il est impossible d'parsingr votre requête sans vraiment savoir quelle est la requête – avec des détails atroces – car les problèmes de performance sont invariablement dans les détails.