Saya sedang melihat artikel di sini Tabel Sementara vs Variabel Tabel dan Efeknya pada Kinerja SQL Server dan pada SQL Server 2008 mampu mereproduksi hasil yang serupa dengan yang ditunjukkan di sana untuk tahun 2005.
Saat menjalankan prosedur tersimpan (definisi di bawah) dengan hanya 10 baris versi variabel tabel keluar melakukan versi tabel sementara lebih dari dua kali.
Saya membersihkan cache prosedur dan menjalankan kedua prosedur yang tersimpan 10.000 kali kemudian mengulangi proses untuk 4 berjalan lagi. Hasil di bawah (waktu dalam ms per batch)
T2_Time V2_Time
----------- -----------
8578 2718
6641 2781
6469 2813
6766 2797
6156 2719
Pertanyaan saya adalah: Apa alasan untuk kinerja versi variabel tabel yang lebih baik?
Saya sudah melakukan investigasi. mis. Melihat penghitung kinerja dengan
SELECT cntr_value
from sys.dm_os_performance_counters
where counter_name = 'Temp Tables Creation Rate';
menegaskan bahwa dalam kedua kasus objek sementara sedang di-cache setelah dijalankan pertama seperti yang diharapkan daripada dibuat dari awal lagi untuk setiap doa.
Demikian pula menelusuri Auto Stats
, SP:Recompile
, SQL:StmtRecompile
peristiwa di Profiler (gambar di bawah) menunjukkan bahwa peristiwa ini hanya terjadi sekali (pada doa pertama dari #temp
tabel disimpan prosedur) dan 9.999 eksekusi lain tidak menaikkan salah satu peristiwa ini. (Versi variabel tabel tidak mendapatkan salah satu dari peristiwa ini)
Overhead yang sedikit lebih besar dari proses pertama dari prosedur tersimpan tidak dapat menjelaskan perbedaan keseluruhan yang besar namun karena masih hanya membutuhkan beberapa ms untuk menghapus cache prosedur dan menjalankan kedua prosedur sekali jadi saya tidak percaya statistik atau kompilasi ulang bisa menjadi penyebabnya.
Buat Objek Database yang Diperlukan
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
Skrip Tes
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
meja satu kali meskipun itu dibersihkan dan dihuni kembali sebanyak 9999 kali berikutnya.