Tôi đã xem bài viết ở đây Bảng tạm thời so với biến bảng và ảnh hưởng của chúng đối với hiệu suất của máy chủ SQL và trên SQL Server 2008 có thể tái tạo kết quả tương tự với kết quả được hiển thị ở đó cho năm 2005.
Khi thực hiện các thủ tục được lưu trữ (định nghĩa bên dưới) chỉ với 10 hàng, phiên bản biến bảng sẽ thực hiện phiên bản bảng tạm thời hơn hai lần.
Tôi đã xóa bộ đệm thủ tục và chạy cả hai thủ tục được lưu trữ 10.000 lần sau đó lặp lại quy trình cho 4 lần chạy khác. Kết quả bên dưới (thời gian tính bằng ms trên mỗi đợt)
T2_Time V2_Time
----------- -----------
8578 2718
6641 2781
6469 2813
6766 2797
6156 2719
Câu hỏi của tôi là: lý do cho hiệu suất tốt hơn của phiên bản biến bảng là gì?
Tôi đã thực hiện một số điều tra. ví dụ: Nhìn vào các quầy hiệu suất với
SELECT cntr_value
from sys.dm_os_performance_counters
where counter_name = 'Temp Tables Creation Rate';
xác nhận rằng trong cả hai trường hợp, các đối tượng tạm thời đang được lưu trữ sau lần chạy đầu tiên như mong đợi thay vì được tạo lại từ đầu cho mỗi lần gọi.
Tương tự truy tìm các Auto Stats
, SP:Recompile
, SQL:StmtRecompile
sự kiện trong Profiler (ảnh chụp màn hình dưới đây) cho thấy rằng những sự kiện chỉ xảy ra một lần (trên gọi đầu tiên của #temp
thủ tục lưu trữ bảng) và 9.999 hành khác không tăng bất kỳ của những sự kiện này. (Phiên bản biến của bảng không nhận được bất kỳ sự kiện nào trong số này)
Tuy nhiên, chi phí lớn hơn một chút trong lần chạy đầu tiên của thủ tục được lưu trữ có thể không gây ra sự khác biệt lớn về tổng thể, tuy nhiên, chỉ mất vài ms để xóa bộ đệm thủ tục và chạy cả hai thủ tục một lần nên tôi không tin thống kê hoặc biên dịch lại có thể là nguyên nhân.
Tạo các đối tượng cơ sở dữ liệu cần thiết
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
Kiểm tra tập lệnh
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
bảng một lần mặc dù nó bị xóa và được điền lại 9,999 lần sau đó.