web-dev-qa-db-fra.com

SQL Server SELECT INTO et blocage avec tables temporaires

Ainsi, récemment, un administrateur de base de données essaie de nous dire que nous ne pouvons pas utiliser la syntaxe de

SELECT X, Y, Z
INTO #MyTable
FROM YourTable

Pour créer des tables temporaires dans notre environnement, car cette syntaxe provoque un verrouillage sur TempDB pour la durée de l’exécution de la procédure stockée. Maintenant, j'ai trouvé un certain nombre d'éléments expliquant le fonctionnement des tables temporaires, la portée de l'exécution, le nettoyage, etc. Mais pour ma vie, je ne vois rien au blocage en raison de leur utilisation.

Nous essayons de trouver des preuves que nous ne devrions pas avoir à passer par CREATE TABLE #MyTable ... pour toutes nos tables temporaires, mais aucune des deux parties ne peut en trouver. Je recherche toute idée SO que les gens ont.

Information additionnelle

Travaille actuellement avec SQL Server 2005, et bientôt SQL Server 2008 (éditions Enterprise)

26
Mitchel Sellers

Ce conseil flotte depuis depuis longtemps :

Goulots d'étranglement dans SQL Server 6.5

De nombreuses personnes utilisent une requête SELECT ... INTO créer une table temporaire, quelque chose comme ça:

SELECT * INTO #TempTable FROM SourceTable

Tant que cela fonctionne, cela crée des verrous contre la base de données tempdb pour le durée de l'instruction SELECT (pas mal de temps si vous parcourez dans beaucoup de données de la table source , et plus longtemps encore si SELECT ... INTO est au début d’un plus long transaction) Tant que le verrou est en place, aucun autre l'utilisateur peut créer des tables temporaires. Le l'emplacement réel du goulot d'étranglement est un verrouille les tables système tempdb. Au plus tard versions de SQL Server, le verrouillage le modèle a changé et le problème est évité.

Heureusement, ce n'était qu'un problème pour SQL 6.5. Il a été corrigé dans 7.0 et plus tard.

34
BradC

Cela va probablement flotter pendant un long moment, alimentant les poches de divers «consultants». Comme tous les mythes, il a un noyau de vérité et beaucoup de BS.

La vérité: SQL 2000 et les versions précédentes avaient connu des problèmes de conflit autour de l'allocation des étendues dans tempdb. La controverse était vraie dans toutes les bases de données, mais plus visible dans tempdb en raison d'une utilisation intensive de tempdb. Il est documenté dans KB328551 :

Lorsque la base de données tempdb est fortement chargée utilisé, SQL Server peut rencontrer conflit quand il essaie d'allouer pages. 

Depuis la table système sysprocesses En sortie, la ressource peut apparaître comme "2: 1: 1" (page PFS) ou "2: 1: 3" (SGAM Page). En fonction du degré de conflit, cela peut également conduire à SQL Le serveur ne répond pas pour courtes périodes.

Ces opérations utilisent fortement tempdb:
Répétée créer et déposer de temporaire tables (locales ou globales).
Variables de table utilisant tempdb pour le stockage fins.
Tables de travail associées à CURSEURS.
Tables de travail associées à une clause ORDER BY.
Tables de travail associées à une clause GROUP BY.
Fichiers de travail associés aux plans de hachage. 

Utilisation lourde et significative de ceux-ci les activités peuvent mener à la contention problèmes.

Un indicateur de suivi -T1118 a été ajouté dans SQL Server 2000 SP3, ce qui forçait SQL à utiliser un algorithme alternatif pour les allocations de pages mixtes. Ce nouvel algorithme, une fois corrélé à la pratique consistant à déployer tempdb sur un ensemble de fichiers de taille égale, un pour chaque processeur, permettrait de réduire le conflit. L'indicateur de trace est toujours présent dans SQL 2005/2008, bien qu'il soit beaucoup moins nécessaire.

Tout le reste de ce mythe est à peu près BS.

  • l'utilisation des tables #temp provoque-t-elle le blocage? Au pire, il accroît la contention sous charge dans SQL 2000 et versions antérieures, mais on n’a pas l’intention de dire qu’il bloque quoi que ce soit. Vous devez d'abord mesurer et voir que c'est le cas, puis déployez les mesures de correction (allouez un fichier tempdb par processeur, donnez-leur la même taille, activez -T1118).
  • Est-ce que select ... into #temp bloque quelque chose pendant la durée de la sélection? Pas vraiment.
  • Est-ce que select ... into #temp bloque quelque chose pendant la durée de la procédure stockée contenant la sélection? Sûrement pas. En lisant cette affirmation, j'ai éclaté de rire.

Pour plus de détails, consultez cet article: Idées fausses autour de TF1118 .

17
Remus Rusanu

Pourquoi ne pas faire ce qui suit?

SELECT X, Y, Z
INTO #MyTable
FROM YourTable
WHERE 1 = 2

L'instruction s'exécutera instantanément - créant votre table temporaire et évitant tout verrouillage possible. Ensuite, vous pouvez insérer comme d'habitude:

INSERT #MyTable
SELECT X, Y, Z
FROM YourTable
10
Eric Pelot

Vous pouvez obtenir un blocage si vous créez des tables #temp dans une transaction. Bien que cela ne soit généralement pas recommandé, j'ai souvent vu cela se faire.

Cependant, le blocage est dû à certaines tables système de tempdb qui n'affectent pas la création de tables temporaires par d'autres connexions (à l'exception peut-être des versions SQL antérieures à 2000?). Cela signifie que l'exécution de sp_spacesused sur tempdb bloquera sauf si vous définissez le niveau d'isolation de transaction sur lecture non validée. De plus, la visualisation des propriétés sur tempdb à partir de SSMS échouera et expirera sans aucun doute, car elle utilise le niveau d'isolation de transaction validée en lecture.

1
IainS

SELECT INTO #temp_table conserve un verrou shema dans tempdb pour la durée de l'instruction, car une partie du travail qu'il accomplit consiste à créer la table. Ceci est fondamentalement différent de la création initiale de la table à l'aide de CREATE TABLE #...., puis de l'exécution d'un INSERT basé sur un ensemble. SELECT INTO présente des avantages par rapport à INSERT, en particulier l'opération est journalisée de manière minimale si le modèle de récupération de la base de données est un journal simple ou en bloc.

0
Michael Lutz

Bien que SELECT INTO ait bloqué le blocage de la base de données tempdb, j’aimerais faire preuve de prudence lors de l’écriture du code, car certaines tables système sont bloquées lors des tests.

Référence: http://www.sqlservercentral.com/Forums/Topic1642797-2799-1.aspx

0
SeeCoolGuy

Je dirais que l'absence de preuve de verrouillage signifie pas de verrouillage, ce qui est votre preuve. Pourquoi la méthode dans laquelle la table temporaire est créée (CREATE ou SELECT ... INTO) aurait-elle une influence sur le verrouillage de TempDB?

0
KM.

Eh bien, si cela était vrai, alors mssql aurait des problèmes, car toute requête volumineuse peut utiliser tempdb pour conserver une copie des lignes. Cela se voit souvent dans les plans de requête sous forme de spool de table ou peut être utilisé par l'opérateur HASH JOIN s'il manque de mémoire pour ses compartiments.

Vous pouvez utiliser des variables de table que mssql essaiera de stocker en mémoire et de passer à tempdb si leur taille est trop grande.

DECLARE @foo TABLE (x int, y int, z int)
INSERT INTO @foo(x, y, z) SELECT x, y, z FROM YourTable

Bien sûr, vous devez évaluer si la table temporaire et la copie sont requises en premier. Bien que si la requête soit suffisamment complexe pour que l’utilisation d’une table temporaire soit beaucoup plus lisible, elle peut également être suffisamment complexe pour qu’une table temporaire en vaille la peine.

0
Chris Chilvers