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;
SELECT TOP 1000
tanpaORDER BY
, itu tidak baik. Saya pikir Anda perlu menambahkanORDER BY A.id;
untuk dua cara agar setara.Jawaban:
@ 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!
sumber
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).
sumber