Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Mana yang lebih berkinerja, CTE atau tabel sementara?

Itu tergantung.

Pertama-tama

Apa yang dimaksud dengan Ekspresi Tabel Umum?

CTE (non rekursif) diperlakukan sangat mirip dengan konstruksi lain yang juga dapat digunakan sebagai ekspresi tabel sebaris di SQL Server. Tabel turunan, Tampilan, dan fungsi bernilai tabel sebaris. Perhatikan bahwa sementara BOL mengatakan bahwa CTE "dapat dianggap sebagai kumpulan hasil sementara" ini adalah deskripsi yang murni logis. Lebih sering daripada tidak, hal itu tidak terwujud dengan sendirinya.

Apa yang dimaksud dengan tabel sementara?

Ini adalah kumpulan baris yang disimpan pada halaman data di tempdb. Halaman data mungkin berada sebagian atau seluruhnya dalam memori. Selain itu, tabel sementara dapat diindeks dan memiliki statistik kolom.

Data Uji

CREATE TABLE T(A INT IDENTITY PRIMARY KEY, B INT , F CHAR(8000) NULL);

INSERT INTO T(B)
SELECT TOP (1000000)  0 + CAST(NEWID() AS BINARY(4))
FROM master..spt_values v1,
     master..spt_values v2;

Contoh 1

WITH CTE1 AS
(
SELECT A,
       ABS(B) AS Abs_B,
       F
FROM T
)
SELECT *
FROM CTE1
WHERE A = 780

Perhatikan dalam rencana di atas tidak disebutkan CTE1. Itu hanya mengakses tabel dasar secara langsung dan diperlakukan sama seperti

SELECT A,
       ABS(B) AS Abs_B,
       F
FROM   T
WHERE  A = 780 

Menulis ulang dengan mewujudkan CTE menjadi tabel sementara perantara di sini akan sangat kontra produktif.

Mewujudkan definisi CTE dari

SELECT A,
       ABS(B) AS Abs_B,
       F
FROM T

Akan melibatkan penyalinan sekitar 8GB data ke dalam tabel sementara, maka masih ada biaya tambahan untuk memilih darinya juga.

Contoh 2

WITH CTE2
     AS (SELECT *,
                ROW_NUMBER() OVER (ORDER BY A) AS RN
         FROM   T
         WHERE  B % 100000 = 0)
SELECT *
FROM   CTE2 T1
       CROSS APPLY (SELECT TOP (1) *
                    FROM   CTE2 T2
                    WHERE  T2.A > T1.A
                    ORDER  BY T2.A) CA 

Contoh di atas memakan waktu sekitar 4 menit di komputer saya.

Hanya 15 baris dari 1.000.000 nilai yang dihasilkan secara acak yang cocok dengan predikat, tetapi pemindaian tabel yang mahal terjadi 16 kali untuk menemukannya.

Ini akan menjadi kandidat yang baik untuk mewujudkan hasil antara. Penulisan ulang tabel temp yang setara membutuhkan waktu 25 detik.

INSERT INTO #T
SELECT *,
       ROW_NUMBER() OVER (ORDER BY A) AS RN
FROM   T
WHERE  B % 100000 = 0

SELECT *
FROM   #T T1
       CROSS APPLY (SELECT TOP (1) *
                    FROM   #T T2
                    WHERE  T2.A > T1.A
                    ORDER  BY T2.A) CA 

Perwujudan antara bagian dari kueri ke dalam tabel sementara kadang-kadang dapat berguna bahkan jika hanya dievaluasi sekali - ketika memungkinkan sisa kueri untuk dikompilasi ulang dengan memanfaatkan statistik pada hasil yang terwujud. Contoh pendekatan ini ada di artikel SQL Cat When To Break Down Complex Query.

Dalam beberapa keadaan SQL Server akan menggunakan spool untuk men-cache hasil antara, mis. dari CTE, dan hindari mengevaluasi kembali subpohon itu. Ini dibahas dalam item Connect (dimigrasikan) Memberikan petunjuk untuk memaksa materialisasi menengah CTE atau tabel turunan. Namun tidak ada statistik yang dibuat untuk ini dan bahkan jika jumlah baris yang digulung menjadi sangat berbeda dari perkiraan, rencana eksekusi yang sedang berlangsung tidak mungkin beradaptasi secara dinamis sebagai respons (setidaknya dalam versi saat ini. Rencana Kueri Adaptif dapat menjadi mungkin di masa depan).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Agregat bitwise-ATAU dalam subquery

  2. Cara menghasilkan Sisipkan Pernyataan dari Data Excel dan Muat ke Tabel SQL Server - Tutorial SQL Server / TSQL Bagian 103

  3. Sisipkan SqlBulkCopy dengan Kolom Identitas

  4. SQL SERVER:Dapatkan total hari antara dua tanggal

  5. Instalasi SQL Server 2017