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
Tabel Temp
SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable
SELECT * FROM #tmpTable
sql-server
cte
Rachel
sumber
sumber
Jawaban:
Ini cukup luas, tetapi saya akan memberi Anda jawaban umum yang saya bisa.
CTE ...
VIEW
sTabel #Temp ...
Sejauh kapan harus menggunakan masing-masing, mereka memiliki kasus penggunaan yang sangat berbeda. Jika Anda akan memiliki set hasil yang sangat besar, atau perlu merujuknya lebih dari sekali, taruh dalam
#temp
tabel. Jika perlu rekursif, sekali pakai, atau hanya untuk menyederhanakan sesuatu secara logis,CTE
lebih disukai.Juga,
CTE
sebaiknya jangan 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.sumber
SUNTING:
Silakan lihat komentar Martin di bawah ini:
Jawaban asli
CTE
Baca lebih lanjut tentang MSDN
CTE membuat tabel yang digunakan dalam memori, tetapi hanya valid untuk kueri spesifik yang mengikutinya. Saat menggunakan rekursi, ini bisa menjadi struktur yang efektif.
Anda mungkin juga ingin mempertimbangkan menggunakan variabel tabel. Ini digunakan sebagai tabel temp digunakan dan dapat digunakan beberapa kali tanpa perlu direalisasikan kembali 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 segelintir catatan itu, 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 variabel tabel temp dan tabel dalam 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 di disk, hanya dalam database tertentu yang semua orang tahu dapat dihapus. Adalah tanggung jawab seorang dev yang baik untuk menghancurkan tabel-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
#tableName
penunjukan untuk lokal, dan##tableName
penunjukan untuk global (perhatikan penggunaan # tunggal atau ganda sebagai karakteristik pengidentifikasi).Perhatikan bahwa dengan temp tables, sebagai kebalikan dari variabel table atau CTE, Anda dapat menerapkan indeks dan sejenisnya, karena ini adalah tabel yang sah dalam arti kata yang 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 besar, Anda mungkin akan mendapat manfaat dari kemampuan untuk mengindeks pada tabel temp.
sumber
SELECT Column1, Column2, Column3 FROM SomeTable
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.The jawaban yang diterima di sini mengatakan "CTE tidak boleh digunakan untuk kinerja" - tapi 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 banyak ke dalam CTE, kecuali yang akan secara sah digunakan kembali sepanjang 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 mengarah pada 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.
sumber
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.
sumber
Tabel temp adalah objek nyata dalam tempdb, tetapi cte hanyalah sejenis pembungkus di sekitar kueri kompleks untuk menyederhanakan sintaksis rekursi pengorganisasian dalam satu langkah.
sumber
Alasan utama untuk menggunakan CTE adalah untuk mengakses Fungsi Jendela seperti
row_number()
dan berbagai fungsi 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 .
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 mengetahui 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)
kueri petunjukAkhirnya, CTE tidak menggunakan tempdb secara default sehingga Anda mengurangi pertikaian tentang hambatan itu 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 kemudian menambahkan indeks bahwa kinerja Anda ditingkatkan.
sumber
Tampaknya ada sedikit negativitas 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 kueri CTE Anda dengan mengikuti saran indeks pada tabel yang mendasarinya.
Selain itu, 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. ;)
sumber