CTE ve Temp Table arasındaki fark nedir?


174

Bir Ortak Tablo İfadesi (CTE) ile geçici tablo arasındaki fark nedir? Birini diğerine ne zaman kullanmalıyım?

CTE

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

SELECT * FROM cte

Sıcaklık tablosu

SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable

SELECT * FROM #tmpTable


Yanıtlar:


200

Bu oldukça geniş, ancak size olabildiğince genel bir cevap vereceğim.

CTEs ...

  • İndekslenebilir değiller (ancak başvurulan nesnelerde mevcut dizinleri kullanabilirler)
  • Kısıtlamaları olamaz
  • Tek kullanımlık VIEWs vardır
  • Sadece bir sonraki sorgu çalıştırılana kadar devam
  • Özyineli olabilir
  • Özel istatistiklere sahip değilsiniz (alttaki nesnelerdeki istatistiklere dayanın)

#Temp Masaları ...

  • Tempdb içinde var olan gerçek materyalize tablolar
  • Endekslenebilir
  • Kısıtlamaları olabilir
  • Mevcut BAĞLANTI yaşamı için devam
  • Diğer sorgular veya alt işlemler tarafından referans alınabilir
  • Motor tarafından oluşturulan özel istatistikler

Her birinin ne zaman kullanılacağı kadarıyla, çok farklı kullanım durumları vardır. Çok büyük bir sonuç kümeniz olacaksa veya bir kereden fazla başvuru yapmanız gerekiyorsa, bir #temptabloya yerleştirin. Özyinelemeli olması, tek kullanımlık olması veya mantıklı bir şeyi basitleştirmek için CTEolması durumunda , a tercih edilir.

Ayrıca, CTEgereken performansı için asla kullanılmayacaktır . CTE kullanarak şeyleri neredeyse hiç hızlandırmazsınız, çünkü yine de tek kullanımlık bir görüntü. Onlarla bazı güzel şeyler yapabilirsiniz ama sorguyu hızlandırmak gerçekten onlardan biri değil.


CTE kullanarak büyük bir MERGE hızlandırmak bir şey
AgentFire

1
CTE'leri kullanarak birçok sorguyu hızlandırmak da bir şeydir, çünkü CTE'ler ile sorgu optimizerinden daha iyi bir performans elde etmek için kendi işletme bilgilerinizi ekleyebilirsiniz. Örneğin, CTE'nizin 1. bölümünü, elde edilen satırların çok küçük olacağını bildiğiniz tablolardan seçebilirsiniz. Aynı sorguda, bu küçük sonuç kümesine daha büyük bir sonuç kümesine katılabilir ve eski istatistiklerin neden olduğu sorunları tamamen atlayabilirsiniz. Bunu yapmak için siparişi zorlamak için sorgu ipuçları eklemeniz gerekir. Çalışır, performansı arttırır.
Dave Hilditch

"asla performans için kullanılamaz" ifadesini anladığım halde geniş ve biraz öznel bir ifade. Diğer yorumlara ek olarak, bir tekrarlayıcı prosedür çağrıları veya bir imleç gibi başka bir tekrarlama biçiminden bir tekrarlamalı CTE'ye geçerken bir CTE kullanmanın bir başka potansiyel performans kazancı ortaya çıkabilir.
JD

29

DÜZENLE:

Lütfen Martin'in yorumlarına bakınız:

CTE, bellekte bir tablo olarak gerçekleşmez. Bu sadece bir sorgu tanımını içine almanın bir yoludur. OP durumunda, satır içi olacak ve sadece yaptığınız gibi olacak SELECT Column1, Column2, Column3 FROM SomeTable. Çoğu zaman önden gerçekleşmezler, bu yüzden satır döndürmez WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X, idam planlarını da kontrol edin. Rağmen bazen bir makara almak için planı kesmek mümkündür. Bunun için ipucu isteyen bir bağlantı maddesi var. - Martin Smith 15 Şubat'ta saat 17: 08'de


Orijinal cevap

CTE

MSDN hakkında daha fazla bilgi edinin

Bir CTE bellekte kullanılan tabloyu yaratır, ancak yalnızca onu takip eden belirli sorgu için geçerlidir. Özyinelemeyi kullanırken, bu etkili bir yapı olabilir.

Bir tablo değişkeni kullanmayı da düşünebilirsiniz. Bu, kullanılan olarak geçici bir tablo kullanılır ve birleştirme her biri için tekrar hayata yapılmasına gerek kalmadan birden fazla kez kullanılabilir. Ayrıca, şimdi birkaç kayıt tutmanız gerekiyorsa, bir sonraki seçimden sonra bir kaç kayıt daha ekleyin, başka bir işlemden sonra bir kaç kayıt daha ekleyin, sonra sadece bu kayıtların bir kısmını geri getirin, o zaman bu kullanışlı bir yapı olabilir. İnfazdan sonra düşürülmeye gerek yok. Çoğunlukla sadece sözdizimsel şeker. Ancak, satır sayısını düşük tutarsanız, hiçbir zaman diske aktarılmaz. Bkz SQL Server geçici masa ve masa değişkeni arasındaki fark nedir? daha fazla ayrıntı için.

Sıcaklık tablosu

MSDN hakkında daha fazla bilgi edinin - Yolun yaklaşık% 40'ını aşağı kaydırın

Temp tablo tam anlamıyla diskte oluşturulan bir tablodur, sadece herkesin silinebileceğini bildiği belirli bir veritabanında. Artık ihtiyaç duyulmadığında bu tabloları imha etmek iyi bir dev'ın sorumluluğudur, ancak bir DBA da onları silebilir.

Geçici tablolar iki çeşittir: Yerel ve küresel. MS Sql Sunucusu açısından, #tableNameyerel bir atama ve ##tableNamegenel atama kullanırsınız (tanımlayıcı karakteristik olarak tek veya çift # kullanımına dikkat edin).

Tablo değişkenleri veya CTE'nin yerine temp tablolarıyla kelimenin normal anlamındaki meşru tabloları olduğu için indeksleri ve benzerlerini uygulayabildiğinizi unutmayın.


Genelde temp tabloları daha uzun veya daha büyük sorgular için ve CTE'ler veya tablo değişkenleri zaten küçük bir veri setine sahip olsaydım ve küçük bir şey için hızlıca biraz kod yazmayı isterdim. Tecrübe ve başkalarının tavsiyesi, ondan az sayıda satırın geldiği CTE'leri kullanmanız gerektiğini gösterir. Çok sayıda numaranız varsa, büyük olasılıkla temp tablosundaki indeksleme özelliğinden yararlanabilirsiniz.


11
CTE, bellekte bir tablo olarak gerçekleşmez. Bu sadece bir sorgu tanımını içine almanın bir yoludur. OP durumunda, sıraya konulacak ve sadece yaptığınız gibi olacakSELECT Column1, Column2, Column3 FROM SomeTable
Martin Smith,

4
Çoğu zaman önden gerçekleşmezler, bu yüzden satır döndürmez WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X, idam planlarını da kontrol edin. Rağmen bazen bir makara almak için planı kesmek mümkündür . Bunun için ipucu isteyen bir bağlantı maddesi var .
Martin Smith

16

Kabul cevap ama bu yanlış yönlendirebilir - burada "bir CTE performans için asla kullanılmamalıdır" diyor. CTE'lerin geçici tablolara karşı bağlamında, bazı doofusların geçici tabloları kullanmanın çok az veya hiç olmadığını düşünmüş olması gerekirken, saklanan bir procs paketinden bir çöp parçasını çıkarmayı yeni bitirdim. İşlem boyunca meşru bir şekilde yeniden kullanılacak olanlar haricinde , CTE'lere çok şey verdim . Tüm ölçümlerle% 20 performans elde ettim. Daha sonra özyinelemeli işlem yapmaya çalışan tüm imleçleri kaldırmaya başladım. Burası en büyük kazancı gördüm. Tepki sürelerini 10 kat azaltarak bitirdim.

CTE'ler ve geçici tablolar çok farklı kullanım durumlarına sahiptir. Sadece, her derde deva olmasa da, CTE'lerin anlaşılmasının ve doğru kullanımının hem kod kalitesi / bakımı ve hem de hızda bazı gerçekten mükemmel gelişmelere yol açabileceğini vurgulamak istiyorum. Onlarla başa çıktığım için, temp tabloları ve imleçleri SQL işlemenin en büyük kötülükleri olarak görüyorum. Hemen hemen her şey için tablo değişkenleri ve CTE'leri kullanarak gayet iyi geçebiliyorum. Kodum daha temiz ve hızlı.


Şimdi, adil olalım - göstericiler büyük kötülükler; temp tabloları en kötü durumda daha az kötüdür. :-) O var gerçekten kendinizi gördüğümüz gibi, aynı seviyede onları koymak haksız.
RDFozz

@RDFozz haklı, cehennemin hepimizin bildiği gibi 9 dairesi var . 2. sicaklik masalari ve imleçleri 7'ye koyalım. ;)
ypercubeᵀᴹ

1
Programlamada 'büyük kötülüğün' ne olduğunu biliyor musunuz? İnsanlar belli bir tekniğin kötü olduğunu söylediğinde. İmleçler için bir yer var. Bazı senaryolarda diğer tekniklerden daha iyi performans gösterebilirler. Burada kötülük yok - iş için doğru aracı kullanmayı öğrenmelisin. Ne yaptığınızı ölçün ve CTE'lerin, Temp Tabloları veya Cursors'ın kötü olduğuna inanmayın. Tedbir - çünkü gerçek senaryoya göre değişir.
Dave Hilditch

@DaveHilditch bu adil bir yorum, ancak aynı zamanda, pek çok durumda imleclerin doğru bir çözüm olmadığını, bu yüzden neredeyse son bir çare olarak görmeleri için uygulanabilir bir genelleme olduğunu iddia etmek de adil bir yorum.
Mel Padden

1
Tecrübelerime göre bir CURSOR kendi içinde fena değil. CURSORS genellikle geliştiriciler tarafından "yanlış" kullanılır, çünkü çoğu programlama dilinde, çoğunlukla partiler halinde düşünmek zorunda olduğunuz SQL'in aksine yinelemeli düşünmeniz gerekir. Bunun, işyerimde Devs'in bir CURSOR'dan başka bir problemi çözemediğini "göremediği" sık rastlanan bir hata olduğunu biliyorum, bu yüzden neden iyi bir DBA'nın bunları öğretmek ve düzeltmek için kullanışlıdır. @DaveHilditch tamamen haklıdır: Doğru iş için doğru araç her şeydir.
Philippe,

14

Bir CTE bir sorgu içinde tekrar tekrar çağrılabilir ve her başvurulan zaman değerlendirilir - bu süreç özyinelemeli olabilir. Eğer sadece bir kez belirtilirse, CTE'ler parametreleştirilebilse de, bir alt sorgu gibi davranır.

Geçici bir masa fiziksel olarak ısrar edilir ve indekslenebilir. Uygulamada sorgu optimizatörü ayrıca, biriktirme işlemlerinde olduğu gibi, sahnelerin arkasındaki ara birleştirme veya alt-sorgulama sonuçlarına da dayanabilir, bu nedenle CTE'lerin sonuçlarının hiçbir zaman diske dayanmadığı kesin olarak doğru değildir.

IIRC tablo değişkenleri (diğer taraftan) daima hafıza içi yapılardır.


4
CTE'ler parametrelendirilebilir mi? Nasıl? Ayrıca, tablo değişkenleri her zaman bellekteki yapılar değildir. Martin'in ilgili soruya verdiği mükemmel cevaba bakınız .
Paul Beyaz

11

Tempdb, tempdb'deki gerçek bir nesnedir, ancak cte, organize yinelemenin tek bir adımda sözdizimini basitleştirmek için karmaşık sorgu etrafında yalnızca bir tür sarıcıdır.


8

CTE'leri kullanmanın birincil nedeni, row_number()ve diğerleri gibi Pencere İşlevlerine erişmektir .

Bu, grup başına ilk veya son sırayı ÇOK ÇOK ÇOK hızlı ve verimli bir şekilde yapabileceğiniz anlamına gelir - çoğu pratik durumda diğer araçlardan daha verimli .

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

Benzer bir sorguyu, ilişkili bir alt sorgu kullanarak veya bir alt sorgu kullanarak yukarı çalıştırabilirsiniz ancak CTE neredeyse tüm senaryolarda daha hızlı olacaktır.

Ek olarak, CTE'ler kodunuzu gerçekten basitleştirmenize yardımcı olabilir. Bu, performans artışlarına yol açabilir, çünkü sorguyu daha iyi anlarsınız ve en iyi duruma getiricinin daha seçici olmasına yardımcı olmak için daha fazla iş mantığı sunar.

Ek olarak, iş mantığınızı anlarsanız ve sorgunun hangi bölümlerinin önce çalıştırılması gerektiğini biliyorsanız, CTE'ler performansı artırabilir - tipik olarak, bir sonraki birleşimlerinde bir dizin kullanabilen sonuç kümelerine yol açan ve option(force order)sorguyu ekleyen en seçici sorgularınızı ilk sıraya koyun ipucu

Son olarak, CTE'ler varsayılan olarak tempdb kullanmazlar;

Verileri birden çok kez sorgulamanız gerekiyorsa veya alternatifleri sorgularınızı ölçüp geçici bir tabloya ekleyerek performansınızın arttığını belirten bir dizin ekleyerek keşfetmeniz gerekiyorsa geçici tablolar kullanılmalıdır .


tüm iyi puanlar ... +1
Mel Padden

6

CTE'lere karşı burada biraz olumsuzluk var gibi görünüyor.

Bir CTE'yi anlıyorum, temelde bu tür bir anlık görüş. SQL hem bildirimsel hem de temelli bir dildir. CTE'ler bir set ilan etmenin harika bir yoludur! Bir CTE'yi endeksleyememek aslında iyi bir şey çünkü gerek yok! Sorgunun okunmasını / yazılmasını kolaylaştırmak gerçekten bir çeşit sözdizimsel şeker. İyi bir düzenleyici, temel tablolardaki dizinleri kullanarak en iyi erişim planını uygular. Bu, temel tablolarda indeks tavsiyesine uyarak CTE sorgunuzu etkin bir şekilde hızlandırabileceğiniz anlamına gelir.

Ayrıca, bir kümesi CTE olarak tanımladığınız için, kümedeki tüm satırların işlenmesi gerektiği anlamına gelmez. Sorguya bağlı olarak en iyi duruma getirici, sorguyu karşılamak için "yeterli" satırı işleyebilir. Belki de ekranınız için yalnızca ilk 20'ye ihtiyacınız vardı. Eğer bir temp tablosu oluşturduysanız, o zaman tüm bu satırları okumanız / yazmanız gerekir!

Buna dayanarak CTE'lerin SQL'in mükemmel bir özelliği olduğunu ve sorgunun okunmasını kolaylaştıracak her yerde kullanılabileceğini söyleyebilirim. Sadece her bir rekoru işlemesi gereken bir toplu iş süreci için geçici bir tablo düşünürdüm. O zaman bile, afaik gerçekten tavsiye edilmez çünkü geçici bir tabloda, veritabanının önbellekleme ve dizinler konusunda size yardımcı olması çok daha zordur. İşleminize özgü bir PK alanı olan kalıcı bir tabloya sahip olmak daha iyi olabilir.

Tecrübelerimin ağırlıklı olarak DB2 ile olduğunu itiraf etmeliyim, bu yüzden CTE'nin her iki üründe de aynı şekilde çalıştığını farz ediyorum. Eğer CTE'ler bir şekilde SQL server'da daha düşükse mutlu bir şekilde düzeltilmiş olarak duracağım. ;)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.