J'apprends plus de détails dans la variable de table. Il indique que les tables temporaires sont toujours sur le disque et que les variables de table sont en mémoire, c'est-à-dire que les performances de la variable de table sont meilleures que la table temporaire car la variable de table utilise moins d'opérations d'E / S que la table temporaire.
Mais parfois, s'il y a trop d'enregistrements dans une variable de table qui ne peuvent pas être contenus en mémoire, la variable de table sera placée sur le disque comme la table temporaire.
Mais je ne sais pas ce que sont les "trop de disques". 100 000 enregistrements? ou 1 000 000 enregistrements? Comment savoir si une variable de table que j'utilise est en mémoire ou sur disque? Existe-t-il une fonction ou un outil dans SQL Server 2005 pour mesurer l'échelle de la variable de table ou pour me faire savoir quand la variable de table est placée sur le disque à partir de la mémoire?
tempDB
- que "en mémoire" est un mythe. Aussi: les variables de table seront toujours considérées par l'optimiseur de requêtes comme contenant exactement une ligne - si vous en avez beaucoup plus, cela peut conduire à de mauvais plans d'exécution.tempdb
(mais peut aussi être entièrement en mémoire)Réponses:
Votre question montre que vous avez succombé à certaines des idées fausses courantes concernant les variables de table et les tables temporaires.
J'ai écrit une réponse assez complète sur le site DBA en examinant les différences entre les deux types d'objet. Cela répond également à votre question sur le disque par rapport à la mémoire (je n'ai pas vu de différence de comportement significative entre les deux).
En ce qui concerne la question dans le titre, cependant, quand utiliser une variable de table par rapport à une table temporaire locale, vous n'avez pas toujours le choix. Dans les fonctions, par exemple, il est uniquement possible d'utiliser une variable de table et si vous avez besoin d'écrire dans la table dans une portée enfant, seule une
#temp
table fera l'affaire (les paramètres de valeur de table autorisent l' accès en lecture seule ).Lorsque vous avez le choix, certaines suggestions sont ci-dessous (bien que la méthode la plus fiable consiste à simplement tester les deux avec votre charge de travail spécifique).
Si vous avez besoin d'un index qui ne peut pas être créé sur une variable de table, vous aurez bien sûr besoin d'une
#temporary
table. Cependant, les détails dépendent de la version. Pour SQL Server 2012 et versions antérieures, les seuls index pouvant être créés sur des variables de table étaient ceux créés implicitement via une contrainteUNIQUE
ouPRIMARY KEY
. SQL Server 2014 a introduit la syntaxe d'index en ligne pour un sous-ensemble des options disponibles dansCREATE INDEX
. Cela a été étendu depuis pour permettre des conditions d'index filtrées.INCLUDE
Cependant, il n'est toujours pas possible de créer des index avec des colonnes -d ou des index columnstore.Si vous allez ajouter et supprimer plusieurs fois de nombreuses lignes du tableau, utilisez un
#temporary
tableau. Cela prend en chargeTRUNCATE
(ce qui est plus efficace queDELETE
pour les grandes tables) et les insertions ultérieures suivant unTRUNCATE
peuvent avoir de meilleures performances que celles qui suivent unDELETE
comme illustré ici .#temporary
tableau. Cela prend en charge la création de statistiques qui permet au plan d'être recompilé dynamiquement en fonction des données (bien que pour les tables temporaires mises en cache dans les procédures stockées, le comportement de recompilation doit être compris séparément).SELECT
instruction potentiellement coûteuse , considérez que l'utilisation d'une variable de table bloquera la possibilité de cette utilisation d'un plan parallèle.#temp
table dans un utilisateur, les verrous de transaction peuvent être conservés plus longtemps que pour les variables de table (potentiellement jusqu'à la fin de la transaction vs fin de l'instruction en fonction du type de verrouillage et du niveau d'isolement) et cela peut également empêcher la troncature dutempdb
journal des transactions jusqu'à ce que le la transaction utilisateur se termine. Cela pourrait donc favoriser l'utilisation de variables de table.#temporary
tables. Bob Ward souligne dans satempdb
présentation que cela peut provoquer des conflits supplémentaires sur les tables système dans des conditions de concurrence élevée. De plus, lorsque vous traitez de petites quantités de données, cela peut faire une différence mesurable dans les performances .Effets du partage d'ensemble de lignes
la source
id
et l'utilisation deOPTION (RECOMPILE)
serait probablement très bien pour cela - mais testez les deux.Utilisez une variable de table si pour une très petite quantité de données (milliers d'octets)
Utiliser une table temporaire pour beaucoup de données
Une autre façon de penser: si vous pensez que vous pourriez bénéficier d'un index, de statistiques automatisées ou de tout optimiseur SQL, votre ensemble de données est probablement trop volumineux pour une variable de table.
Dans mon exemple, je voulais simplement mettre environ 20 lignes dans un format et les modifier en tant que groupe, avant de les utiliser pour METTRE À JOUR / INSÉRER une table permanente. Une variable de table est donc parfaite.
Mais j'exécute également SQL pour remplir des milliers de lignes à la fois, et je peux certainement dire que les tables temporaires fonctionnent bien mieux que les variables de table.
Ce n'est pas différent de la façon dont les CTE sont un problème pour une raison de taille similaire - si les données dans le CTE sont très petites, je trouve qu'un CTE fonctionne aussi bien ou mieux que ce que l'optimiseur propose, mais s'il est assez grand, alors ça vous fait très mal.
Ma compréhension est principalement basée sur http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ , qui a beaucoup plus de détails.
la source
Microsoft dit ici
la source
Je suis totalement d'accord avec Abacus (désolé - je n'ai pas assez de points pour commenter).
En outre, gardez à l'esprit que cela ne se résume pas nécessairement au nombre d' enregistrements dont vous disposez, mais à la taille de vos enregistrements.
Par exemple, avez-vous pris en compte la différence de performances entre 1 000 enregistrements avec 50 colonnes chacun et 100 000 enregistrements avec seulement 5 colonnes chacun?
Enfin, vous interrogez / stockez peut-être plus de données que vous n'en avez besoin? Voici une bonne lecture des stratégies d'optimisation SQL . Limitez la quantité de données que vous extrayez, surtout si vous n'utilisez pas tout (certains programmeurs SQL deviennent paresseux et sélectionnent tout, même s'ils n'utilisent qu'un minuscule sous-ensemble). N'oubliez pas que l'analyseur de requêtes SQL peut également devenir votre meilleur ami.
la source
La table variable n'est disponible que pour la session en cours, par exemple, si vous avez besoin d'
EXEC
une autre procédure stockée dans la session en cours, vous devrez passer la table au furTable Valued Parameter
et à mesure que cela affectera les performances, avec les tables temporaires, vous ne pouvez le faire qu'avec passer le nom de la table temporairePour tester une table temporaire:
Pour tester une table de variables:
quelque chose d'autre que j'ai vécu est: Si votre schéma n'a pas le
GRANT
privilège de créer des tables, utilisez des tables variables.la source
en écrivant des données dans des tables déclarées
declare @tb
et après avoir rejoint d'autres tables, j'ai réalisé que le temps de réponse par rapport aux tables temporairestempdb .. # tb
est beaucoup plus élevé.Lorsque je les rejoins avec @tb, le temps est beaucoup plus long pour retourner le résultat, contrairement à #tm , le retour est presque instantané.
J'ai fait des tests avec une jointure de 10 000 lignes et joint avec 5 autres tables
la source