Je regardais l'article ici Tables temporaires par rapport aux variables de table et leur impact sur les performances de SQL Server et sur SQL Server 2008 a été en mesure de reproduire des résultats similaires à ceux indiqués ici pour 2005.
Lors de l'exécution des procédures stockées (définitions ci-dessous) avec seulement 10 lignes, la version de variable de table exécute la version de table temporaire plus de deux fois.
J'ai effacé le cache de procédure et exécuté les deux procédures stockées 10 000 fois, puis répété le processus pendant 4 autres exécutions. Résultats ci-dessous (temps en ms par lot)
T2_Time V2_Time
----------- -----------
8578 2718
6641 2781
6469 2813
6766 2797
6156 2719
Ma question est la suivante: quelle est la raison de la meilleure performance de la version de la variable de table?
J'ai fait des recherches. Par exemple, regarder les compteurs de performance avec
SELECT cntr_value
from sys.dm_os_performance_counters
where counter_name = 'Temp Tables Creation Rate';
confirme que, dans les deux cas, les objets temporaires sont mis en cache après la première exécution, comme prévu, plutôt que créés à nouveau pour chaque invocation.
De même , le suivi Auto Stats
, SP:Recompile
, les SQL:StmtRecompile
événements dans Profiler (capture d' écran ci - dessous) montre que ces événements se produisent qu'une seule fois (la première invocation de la #temp
table de procédure stockée) et les autres 9.999 exécutions ne soulèvent aucun de ces événements. (La version de la variable de table ne reçoit aucun de ces événements)
La surcharge légèrement plus importante de la première exécution de la procédure stockée ne peut en aucune manière expliquer la grande différence globale, toutefois, comme il ne faut que quelques ms pour effacer le cache de procédure et exécuter les deux procédures une fois, je ne crois pas que les statistiques ou Les recompilations peuvent en être la cause.
Créer les objets de base de données requis
CREATE DATABASE TESTDB_18Feb2012;
GO
USE TESTDB_18Feb2012;
CREATE TABLE NUM
(
n INT PRIMARY KEY,
s VARCHAR(128)
);
WITH NUMS(N)
AS (SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY $/0)
FROM master..spt_values v1,
master..spt_values v2)
INSERT INTO NUM
SELECT N,
'Value: ' + CONVERT(VARCHAR, N)
FROM NUMS
GO
CREATE PROCEDURE [dbo].[T2] @total INT
AS
CREATE TABLE #T
(
n INT PRIMARY KEY,
s VARCHAR(128)
)
INSERT INTO #T
SELECT n,
s
FROM NUM
WHERE n%100 > 0
AND n <= @total
DECLARE @res VARCHAR(128)
SELECT @res = MAX(s)
FROM NUM
WHERE n <= @total
AND NOT EXISTS(SELECT *
FROM #T
WHERE #T.n = NUM.n)
GO
CREATE PROCEDURE [dbo].[V2] @total INT
AS
DECLARE @V TABLE (
n INT PRIMARY KEY,
s VARCHAR(128))
INSERT INTO @V
SELECT n,
s
FROM NUM
WHERE n%100 > 0
AND n <= @total
DECLARE @res VARCHAR(128)
SELECT @res = MAX(s)
FROM NUM
WHERE n <= @total
AND NOT EXISTS(SELECT *
FROM @V V
WHERE V.n = NUM.n)
GO
Script de test
SET NOCOUNT ON;
DECLARE @T1 DATETIME2,
@T2 DATETIME2,
@T3 DATETIME2,
@Counter INT = 0
SET @T1 = SYSDATETIME()
WHILE ( @Counter < 10000)
BEGIN
EXEC dbo.T2 10
SET @Counter += 1
END
SET @T2 = SYSDATETIME()
SET @Counter = 0
WHILE ( @Counter < 10000)
BEGIN
EXEC dbo.V2 10
SET @Counter += 1
END
SET @T3 = SYSDATETIME()
SELECT DATEDIFF(MILLISECOND,@T1,@T2) AS T2_Time,
DATEDIFF(MILLISECOND,@T2,@T3) AS V2_Time
#temp
table qu'une fois, bien qu'elles aient été effacées et à nouveau remplies 9 999 fois par la suite.