INSÉRER la différence de performances entre les tables temporaires et la variable de table

12

J'ai le problème suivant dans SQL Server 2005: essayer d'insérer des lignes dans une variable de table prend beaucoup de temps par rapport à la même insertion utilisant une table temporaire.

Ceci est le code à insérer dans la variable de table

DECLARE @Data TABLE(...)
INSERT INTO @DATA( ... )
SELECT ..
FROM ...

Ceci est le code à insérer dans la table temporaire

CREATE #Data TABLE(...)
INSERT INTO #DATA( ... )
SELECT ..
FROM ...
DROP TABLE #Data

La table temporaire n'a pas de clés ou d'index, la partie sélection est la même entre les 2 requêtes et le nombre de résultats renvoyés par la sélection est ~ 10000 lignes. Le temps nécessaire pour exécuter la sélection seule est d'environ 10 secondes.

La version de la table temporaire prend jusqu'à 10 secondes pour s'exécuter, j'ai dû arrêter la version variable de la table après 5 minutes.

Je dois utiliser une variable de table car la requête fait partie d'une fonction de valeur de table, qui ne permet pas d'accéder à une table temporaire.

Plan d'exécution pour la version variable de table Plan d'exécution

Plan d'exécution pour la version de table temporaire Plan d'exécution

munissor
la source

Réponses:

8

La différence évidente entre les deux plans est que le rapide est parallèle et le plus lent en série.

C'est l'une des limitations des plans qui s'insèrent dans des variables de table. Comme mentionné dans les commentaires (et il semble que cela ait eu l'effet souhaité), vous pouvez essayer de faire

INSERT INTO @DATA ( ... ) 
EXEC('SELECT .. FROM ...')

pour voir si cela contourne la limitation.

Martin Smith
la source
C'était une excellente suggestion, même si je pensais que vous ne pouviez pas utiliser EXECune fonction ... devinez que j'avais tort
Lamak
1
@Lamak - Doh! Vous ne pouvez pas, donc cela ne fonctionnera pas pour l'OP. Invalid use of a side-effecting operator 'INSERT EXEC' within a function.. Le OPENQUERYtravail autour pourrait cependant fonctionner.
Martin Smith
Ah, bon à savoir, merci pour la clarification
Lamak
2
En règle générale, vous ne voulez pas utiliser de variables de table si vous vous attendez à obtenir un ensemble de données volumineux retourné. Les tables temporaires sont généralement plus rapides dans ce cas.
HLGEM
1
@munissor, n'utilisez pas de fonction table. Si vous voulez de meilleurs conseils, affichez exactement ce que vous faites.
HLGEM
-1

Les variables de table sont parfois plus lentes car il n'y a pas de statistiques sur les variables de table, et donc l'optimiseur suppose toujours un seul enregistrement.

Cependant, je ne peux pas garantir que c'est le cas ici, vous devrez jeter un œil aux informations sur les "lignes estimées" dans le plan de requête pour la variable de table.

yoel halb
la source
Comment cela affecterait-il une insertion dans une variable de table?
Martin Smith
C'est ce qui semble se produire, car vous pouvez voir qu'il n'y a pas seulement une différence entre parallèle et série mais aussi entre les jointures de hachage et les boucles imbriquées, apparemment l'optimiseur suppose que puisque la variable de table contient un enregistrement dans son esprit, le résultat de la requête sera également un enregistrement, une fois de plus le seul moyen de le prouver serait de voir les statistiques réelles pour chaque partie de la requête, mais le fait est que toutes les requêtes impliquant des variables de table se retrouvent avec des jointures en boucle et un traitement en série, donc je pense qu'il est juste de le suspecter ici
yoel halb