it-swarm.asia

Apa perbedaan antara CTE dan Tabel Temp?

Apa perbedaan antara Common Table Expression (CTE) dan tabel temp? Dan kapan saya harus menggunakan yang satu?

CTE

WITH cte (Column1, Column2, Column3)
AS
(
    SELECT Column1, Column2, Column3
    FROM SomeTable
)

SELECT * FROM cte

Temp Table

SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable

SELECT * FROM #tmpTable
179
Rachel

Ini cukup luas, tetapi saya akan memberi Anda jawaban umum yang saya bisa.

CTE ...

  • Tidak dapat dijelaskan (tetapi dapat menggunakan indeks yang ada pada objek yang direferensikan)
  • Tidak dapat memiliki kendala
  • Pada dasarnya adalah VIEWs sekali pakai
  • Tetap hanya sampai permintaan berikutnya dijalankan
  • Dapat bersifat rekursif
  • Tidak memiliki statistik khusus (mengandalkan statistik pada objek yang mendasarinya)

# Tabel Temp ...

  • Adalah tabel terwujud nyata yang ada di tempdb
  • Dapat diindeks
  • Dapat memiliki kendala
  • Bertahanlah untuk kehidupan CONNECTION saat ini
  • Dapat dirujuk oleh kueri atau sub-prosedur lainnya
  • Memiliki statistik khusus yang dihasilkan oleh mesin

Sejauh kapan harus menggunakan masing-masing, mereka memiliki kasus penggunaan yang sangat berbeda. Jika Anda memiliki set hasil yang sangat besar, atau perlu merujuknya lebih dari satu kali, letakkan di #temp meja. Jika perlu rekursif, sekali pakai, atau hanya untuk menyederhanakan sesuatu secara logis, CTE lebih disukai.

Juga, CTE harus tidak pernah digunakan untuk kinerja. Anda hampir tidak akan pernah mempercepat dengan menggunakan CTE, karena, sekali lagi, ini hanya tampilan sekali pakai. Anda dapat melakukan beberapa hal yang rapi dengan mereka tetapi mempercepat permintaan tidak benar-benar salah satunya.

204
JNK

EDIT:

Silakan lihat komentar Martin di bawah ini:

CTE tidak terwujud sebagai tabel dalam memori. Ini hanya cara merangkum definisi permintaan. Dalam kasus OP, itu akan digarisbawahi dan sama dengan hanya melakukan SELECT Column1, Column2, Column3 FROM SomeTable. Sebagian besar waktu mereka tidak terwujud di muka, itulah sebabnya ini tidak mengembalikan baris WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X, juga memeriksa rencana eksekusi. Meskipun terkadang ada kemungkinan untuk meretas rencana untuk mendapatkan gulungan. Ada item sambung yang meminta petunjuk untuk ini. - Martin Smith 15 Feb 12 jam 17:08


Jawaban asli

CTE

Baca lebih lanjut tentang MSDN

CTE membuat tabel yang digunakan dalam memori, tetapi hanya valid untuk kueri tertentu yang mengikutinya. Saat menggunakan rekursi, ini bisa menjadi struktur yang efektif.

Anda mungkin juga ingin mempertimbangkan menggunakan variabel tabel. Ini digunakan as tabel temp digunakan dan dapat digunakan beberapa kali tanpa perlu direalisasi ulang untuk setiap bergabung. Juga, jika Anda perlu bertahan beberapa catatan sekarang, tambahkan beberapa catatan lagi setelah pilih berikutnya, tambahkan beberapa catatan lagi setelah op lain, lalu kembalikan hanya beberapa catatan, maka ini bisa menjadi struktur yang berguna, karena tidak perlu dijatuhkan setelah eksekusi. Sebagian besar hanya gula sintaksis. Namun, jika Anda tetap menghitung baris rendah, itu tidak pernah terwujud ke disk. Lihat Apa perbedaan antara tabel temp dan variabel tabel di SQL Server? untuk lebih jelasnya.

Tabel Temp

Baca lebih lanjut tentang MSDN - Gulir ke bawah sekitar 40% dari jalan

Tabel temp secara harfiah adalah tabel yang dibuat pada disk, hanya dalam database tertentu yang semua orang tahu dapat dihapus. Adalah tanggung jawab seorang dev yang baik untuk menghancurkan tabel itu ketika mereka tidak lagi dibutuhkan, tetapi DBA juga dapat menghapusnya.

Tabel sementara datang dalam dua variasi: Lokal dan global. Dalam hal MS Sql Server Anda menggunakan penunjukan #tableName Untuk lokal, dan ##tableName Penunjukan untuk global (catat penggunaan # tunggal atau ganda sebagai karakteristik pengidentifikasi).

Perhatikan bahwa dengan temp tables, sebagai kebalikan dari variabel table atau CTE, Anda bisa menerapkan indeks dan sejenisnya, karena ini adalah tabel yang sah dalam arti kata normal.


Secara umum saya akan menggunakan tabel temp untuk kueri yang lebih panjang atau lebih besar, dan variabel CTE atau tabel jika saya sudah memiliki dataset kecil dan ingin dengan cepat membuat skrip sedikit kode untuk sesuatu yang kecil. Pengalaman dan saran orang lain menunjukkan bahwa Anda harus menggunakan CTE di mana Anda memiliki sejumlah kecil baris yang dikembalikan darinya. Jika Anda memiliki jumlah yang besar, Anda mungkin akan mendapat manfaat dari kemampuan untuk mengindeks pada tabel temp.

29
jcolebrand

The jawaban yang diterima di sini mengatakan "CTE seharusnya tidak pernah digunakan untuk kinerja" - tetapi itu bisa menyesatkan. Dalam konteks CTE versus tabel temp, saya baru saja selesai menghapus sepotong sampah dari serangkaian procs yang disimpan karena beberapa doofus pasti mengira ada sedikit atau tidak ada overhead untuk menggunakan tabel temp. Saya memasukkan lot ke dalam CTE, kecuali yang akan digunakan kembali secara sah selama proses. Saya memperoleh kinerja sekitar 20% oleh semua metrik. Saya kemudian mulai menghapus semua kursor yang mencoba menerapkan pemrosesan rekursif. Di sinilah saya melihat keuntungan terbesar. Saya akhirnya memangkas waktu respons dengan faktor sepuluh.

CTE dan tabel temp memiliki kasus penggunaan yang sangat berbeda. Saya hanya ingin menekankan bahwa, meski bukan obat mujarab, pemahaman dan penggunaan CTE yang benar dapat menyebabkan beberapa peningkatan yang benar-benar luar biasa baik dalam kualitas kode/pemeliharaan dan kecepatan. Karena saya punya pegangan pada mereka, saya melihat tabel temporer dan kursor sebagai kejahatan besar pemrosesan SQL. Saya bisa mendapatkan dengan baik dengan variabel tabel dan CTE untuk hampir semuanya sekarang. Kode saya lebih bersih dan lebih cepat.

17
Mel Padden

CTE dapat dipanggil berulang kali dalam kueri dan dievaluasi setiap kali direferensikan - proses ini dapat bersifat rekursif. Jika hanya dirujuk sekali maka berperilaku seperti sub-kueri, meskipun CTE dapat parameter.

Tabel sementara secara fisik bertahan, dan mungkin diindeks. Dalam praktiknya, pengoptimal kueri juga dapat bertahan pada hasil gabung menengah atau sub-permintaan di belakang layar, seperti dalam operasi spool, sehingga tidak sepenuhnya benar bahwa hasil CTE tidak pernah bertahan ke disk.

Variabel tabel IIRC (di sisi lain) selalu dalam struktur memori.

Tabel temp adalah objek nyata dalam tempdb, tetapi cte hanyalah sejenis pembungkus di sekitar kueri kompleks untuk menyederhanakan sintaksis rekursi pengorganisasian dalam satu langkah.

11
Oleg Dok

Alasan utama untuk menggunakan CTE adalah untuk mengakses Fungsi Jendela seperti row_number() dan berbagai lainnya.

Ini berarti Anda dapat melakukan hal-hal seperti mendapatkan baris pertama atau terakhir per grup SANGAT SANGAT cepat dan efisien - lebih efisien daripada cara lain dalam kebanyakan kasus praktis .

with reallyfastcte as (
select *, 
row_number() over (partition by groupingcolumn order by sortingcolumn) as rownum
from sometable
)
select *
from reallyfastcte
where rownum = 1;

Anda dapat menjalankan kueri yang mirip dengan yang di atas menggunakan subquery yang berkorelasi atau dengan menggunakan sub-kueri tetapi CTE akan lebih cepat di hampir semua skenario.

Selain itu, CTE sangat membantu menyederhanakan kode Anda. Ini dapat menyebabkan peningkatan kinerja karena Anda lebih memahami kueri dan dapat memperkenalkan lebih banyak logika bisnis untuk membantu pengoptimal menjadi lebih selektif.

Selain itu, CTE dapat meningkatkan kinerja jika Anda memahami logika bisnis Anda dan tahu bagian mana dari kueri yang harus dijalankan terlebih dahulu - biasanya, menempatkan kueri paling selektif Anda terlebih dahulu yang mengarah ke set hasil yang dapat menggunakan indeks dalam bergabung berikutnya dan menambahkan option(force order) petunjuk permintaan

Akhirnya, CTE tidak menggunakan tempdb secara default sehingga Anda mengurangi pertikaian tentang bottleneck melalui penggunaannya.

Tabel sementara harus digunakan jika Anda perlu menanyakan data beberapa kali, atau jika Anda mengukur kueri Anda dan menemukan bahwa dengan menyisipkan ke tabel temp dan lalu menambahkan indeks bahwa kinerja Anda ditingkatkan.

8
Dave Hilditch

Tampaknya ada sedikit negatif di sini terhadap CTE.

Pemahaman saya tentang CTE adalah bahwa pada dasarnya semacam pandangan adhoc. SQL adalah bahasa berbasis deklaratif dan himpunan. CTE adalah cara yang bagus untuk mendeklarasikan set! Tidak dapat mengindeks CTE sebenarnya adalah hal yang baik karena Anda tidak perlu melakukannya! Ini benar-benar semacam gula sintaksis untuk membuat kueri lebih mudah dibaca/ditulis. Pengoptimal yang layak akan membuat rencana akses terbaik menggunakan indeks pada tabel yang mendasarinya. Ini berarti Anda dapat secara efektif mempercepat permintaan CTE Anda dengan mengikuti saran indeks pada tabel yang mendasarinya.

Juga, hanya karena Anda mendefinisikan suatu set sebagai CTE, itu tidak berarti bahwa semua baris dalam set harus diproses. Bergantung pada kueri, pengoptimal mungkin memproses baris "cukup" untuk memenuhi kueri. Mungkin Anda hanya membutuhkan 20 atau lebih pertama untuk layar Anda. Jika Anda membangun tabel temp maka Anda benar-benar perlu membaca/menulis semua baris itu!

Berdasarkan ini saya akan mengatakan bahwa CTE adalah fitur SQL yang hebat dan dapat digunakan di mana saja mereka membuat kueri lebih mudah dibaca. Saya hanya akan berpikir tentang tabel temp untuk proses batch yang benar-benar perlu memproses setiap catatan tunggal. Meski begitu afaik itu tidak benar-benar direkomendasikan karena pada tabel temp jauh lebih sulit bagi database untuk membantu Anda dengan caching dan indeks. Mungkin lebih baik memiliki tabel permanen dengan bidang PK yang unik untuk transaksi Anda.

Saya harus mengakui bahwa pengalaman saya terutama dengan DB2 jadi saya berasumsi bahwa CTE bekerja dengan cara yang sama di kedua produk. Saya dengan senang hati akan dikoreksi jika CTE entah bagaimana lebih rendah di SQL server. ;)

6
Ben Thurley