Apakah ada keuntungan menggunakan tabel sementara dari tabel yang diturunkan di SQL Server?

8

Saya membaca tabel turunan memiliki kinerja yang lebih baik daripada tabel sementara, tetapi bagaimanapun banyak pengembang SQL Server lebih suka yang kedua. Mengapa? Saya harus melakukan kueri dengan data besar (jutaan catatan) dan saya ingin memastikan saya menggunakan pilihan terbaik.

CREATE TABLE A(
    id BIGINT IDENTITY(1,1) NOT NULL,
    field1 INT NOT NULL,
    field2 VARCHAR(50) NULL,
);

CREATE TABLE B(
    id INT IDENTITY(1,1) NOT NULL,
    field1 VARCHAR(10) NULL,
    field2 INT NULL
);

INSERT INTO A 
    (field1,field2)
VALUES 
    (1,'a'),(2,'b'),(3,'c'),(2,'d'),(5,'e'),
    (6,'f'),(7,'g'),(8,'h'),(9,'i'),(2,'j');

INSERT INTO B 
    (field1,field2)
VALUES 
    ('a',1),('b',2),('c',3),('d',4),('e',5),
    ('f',6),('g',7),('h',8),('i',9),('j',2),('k',3);

DECLARE @begin INT=0,@end INT=200;

Tabel yang diturunkan

/*derived tables*/
SELECT 
    C.id,C.field1,C.field2,C.field3 
FROM
(
    SELECT
        A.id,A.field1,A.field2,B.field2 AS field3, 
        ROW_NUMBER() OVER (ORDER BY A.id) AS iRow
    FROM 
        A INNER JOIN B ON A.field1=B.id
) C
WHERE iRow BETWEEN @begin AND @end;

Meja sementara

/*temporary tables*/
CREATE TABLE #C (
    iRow INT IDENTITY(1,1),
    id bigint,
    field1 INT,
    field2 VARCHAR(50),
    field3 INT );

INSERT INTO #C 
    (id,field1,field2,field3)
SELECT TOP 1000 
    A.id,A.field1,A.field2,B.field2 
FROM  
    A INNER JOIN B ON A.field1=B.id
ORDER BY 
    A.id;

SELECT id,field1,field2,field3 
FROM #C 
WHERE iRow BETWEEN @begin AND @end;

DROP TABLE #C;
norgematos
sumber
1
Anda punya SELECT TOP 1000tanpa ORDER BY, itu tidak baik. Saya pikir Anda perlu menambahkan ORDER BY A.id;untuk dua cara agar setara.
ypercubeᵀᴹ
Itu hanya sampel. Tujuannya adalah untuk menunjukkan topik utama pertanyaan saya.
norgematos

Jawaban:

6

@ user16484 sudah mengarahkan Anda ke Mana yang memiliki kinerja lebih baik: Tabel Berasal atau Tabel Sementara dalam komentar.

Juga lihat Temp Table 'vs' Table Variable 'vs' CTE. yang juga mencakup tabel turunan.

Ringkasan cepat: tabel #temp dapat diindeks, dapat memiliki indeks / kendala UNIK, dapat menjadi referensi lebih dari satu kali dalam permintaan yang sama, dapat direferensikan (DARI atau GABUNG) dengan lebih dari satu permintaan. Tabel yang diturunkan dapat direferensikan (DARI atau GABUNG) sekali dalam satu permintaan.

Dari segi kinerja, cabut Profiler untuk SQL: BatchCompleted dan RPC: Completed, tonton kolom Read, Write, CPU, dan Duration, dan lihat apa yang dilakukan oleh beberapa tabel turunan vs. tabel #temp vs tabel #temp diindeks untuk setiap permintaan tertentu.

Secara umum - jika Anda akan menggunakannya lebih dari sekali, tabel #temp menang. Jika Anda bergabung dengan banyak tabel, tabel #temp mungkin menang. Jika Anda hanya bergabung dengan beberapa tabel, tabel turunan memiliki peluang yang wajar untuk menang. Benchmark it!

Kata sandi yang lemah
sumber
6

Secara umum, ini tergantung pada permintaan khusus Anda dan ukuran hasil sementara.

Untuk skenario khusus yang diberikan, yang merupakan paging, tabel temp sama sekali tidak perlu. Mengapa Anda ingin menyimpan 1000 baris ke tabel temp hanya untuk mengembalikan 200 pertama? Menggunakan tabel 'diturunkan' atau CTE dalam skenario ini jauh lebih efisien, karena set hasil lengkap tidak harus disimpan di mana saja, atau dalam kebanyakan kasus bahkan diproduksi. Misalnya ketika meminta halaman pertama dari 200 baris, hanya 200 baris pertama yang harus diambil dari tabel dasar (dengan asumsi indeks yang ada dapat mendukung urutan pengurutan yang diminta dalam permintaan).

Vlad G.
sumber
1
+1, meskipun saya akan menambahkan bahwa menggunakan tabel turunan juga memungkinkan kueri Pengoptimal berurusan dengan kedua kueri pada saat yang sama. Ini bisa baik atau kadang-kadang buruk, lagi "tergantung pada permintaan tertentu". Itulah mengapa selalu baik untuk menguji keduanya (pada data nyata, bukan data sampel) daripada menebak :-).
Solomon Rutzky