Genel Tablo İfadesi (CTE) faydaları?


21

Gönderen msdn :

Türetilmiş bir tablonun aksine, bir CTE kendi kendine referans verebilir ve aynı sorguda birden çok kez referans alınabilir.

CTE'leri çok fazla kullanıyorum, ancak bunları kullanmanın yararları hakkında derinden düşünmedim.

Bir CTE'ye aynı sorguda birden çok kez başvuru yaparsam:

  • Herhangi bir performans avantajı var mı?
  • Kendi kendine katılıyorsam, SQL Server hedef tabloları iki kez tarayacak mı?

2
Profiler iki kez tararsa size söylemesi gerekir. IMHO, CTE'ler özyineleme için harika.
Dan Andrews,

3
Sorgu en iyi duruma getiricisi oyundayken zor cevaplar yoktur. Bazı sorgular, performans avantajları görecek, bazıları görmeyecek. Bazen CTE yerine temp tablosu kullanmak daha hızlı olur, bazen olmaz.

Yanıtlar:


25

Kural olarak, bir CTE ASLA performansı iyileştirmez .

Bir CTE aslında tek kullanımlık bir görünümdür. Saklanan ek istatistik yok, dizin yok, vb. Alt sorgu için bir steno işlevi görür.

Benim düşünceme göre KOLAY aşırı kullanılmış olabilirler (işimde kodda çok fazla aşırı kullanım görüyorum). Bazı iyi cevaplar burada, ancak bir kereden fazla bir şeye başvurmanız gerekiyorsa veya birkaç yüz binden fazla satır varsa, bir #temptabloya koyun ve dizine ekleyin.


3
Anlaşmak. Özyinelemeli
CTE'ler

CTE, hesaplanması pahalı olan (büyük bir tabloda toplama) ve bu sonuç bir kereden fazla kullanıldığında yalnızca birkaç satır (bellekte tutulabilsin) döndürürse? Bu performansı arttırmalı, değil mi? (en azından bu PostgreSQL ve Oracle ile geçici tablonun çok nadir kullanıldığı yerlerde benim deneyimim)
a_horse_with_no_name 6:12

2
@ a_horse_with_no_name - onu sadece bir alt sorgu yapmakla eşdeğerdir. Sonuç tek bir sorguda bir kereden fazla kullanılıyorsa, yeniden kullanılacak ve yeniden hesaplanmayacaktır. Birden fazla sorguda kullanılıyorsa CTE, sonuçlar ilk sorgudan sonra atıldığından a kötü bir seçimdir.
JNK,

@ JNK: teşekkürler. Görünüşe göre SQL Server burada farklı davranıyor.
a_horse_with_no_name

Bazı insanlar
CTE'leri

14

CTE'leri inanılmaz derecede yararlı bulduğum özyinelemenin yanı sıra karmaşık raporlama sorguları oluştururken. İhtiyacım olan verilerin parçalarını almak için bir dizi CTE kullanıyorum ve ardından son seçimde birleştiriyorum. Bunları sürdürmek daha kolay, birçok türetilmiş tablo veya 20 katılımla aynı şeyi yapmaktan daha kolay buluyorum ve bir çok ilişkiden dolayı birden fazla kaydın etkisiyle doğru verileri döndürdüğüme daha fazla güvenebileceğimi düşünüyorum. tüm farklı birleşimler. Hızlı bir örnek vereyim:

;WITH Conferences (Conference_id)
AS 
(select  m.Conference_id
FROM mydb.dbo.Conference m 
WHERE client_id = 10
    and Conference_id in 
            (select Conference_id from mydb.dbo.Expense 
            where amount <>0
            and amount is not null)
     )
--select * from Conferences
,MealEaters(NumberMealEaters, Conference_id, AttendeeType)
AS
(Select count(*) as NumberMealEaters, m.Conference_id,  AttendeeType 
from mydb.dbo.attendance ma 
join Conferences m on m.Conference_id = ma.Conference_id
where (ma.meals_consumed>0 or meals_consumed is null)and attended = 1
group by m.Conference_id)
--select * from MealEaters

,Expenses (Conference_id,expense_date, expenseDescription,  RecordIdentifier,amount)
AS
(select Conference_id,max(expense_date) as Expense_date, expenseDescription,  RecordIdentifier,sum(amount) as amount
    FROM
        (SELECT Conference_id,expense_date,  amount, RecordIdentifier
        FROM mydb.dbo.Expense
        WHERE  amount <> 0 
            and Conference_id IN 
            (SELECT  Conference_id
            FROM mydb.dbo.Conferences ) 
        group by Conference_id, RecordIdentifier) a
)
--select * from Expenses
Select m.Conference_id,me.NumberMealEaters, me.AttendeeType, e.expense_date,         e.RecordIdentifier,amount
from Conferences m
join mealeaters me on m.Conference_id = me.Conference_id
join expenses e on e.Conference_id = m.Conference_id

Böylece, istediğiniz farklı bilgi gruplarını ayırarak, her bir bölümü ayrı ayrı kontrol edebilirsiniz (yorumlu seçimleri kullanarak, her birini ayrı ayrı yorumlayarak ve yalnızca bu seçime kadar koşarak) ve masrafta bir değişiklik yapmanız gerekiyorsa hesaplama (bu örnekte), hepsi bir araya getirildiğinde tek bir büyük sorguda karıştırılmış olduklarından daha kolaydır. Elbette bunu kullandığım gerçek raporlama sorguları genellikle örnekten çok daha karmaşık.


1
Sadece sorguları bildirdiğiniz için mi? Her gün üzerinde çalıştığım sistemler, karmaşık olan işlem sorgularına sahip. İşin garibi raporlama sorgularımız çoğu zaman basit sorularımızdan bazıları. (Tabii ki önemsiz eklemsiz CRUD sorgularını dışlamak).
Kevin Cathcart

Bunu örnek olarak kullandım çünkü bunlar tipik olarak en karmaşık olanlarıdır
HLGEM

+1 bazen potansiyel olarak daha iyi performans gösteren birine daha mantıklı (insan tarafından okunabilir) bir sorgu tercih edilir.
07.07'de

Evet. Bir CTE'nin genellikle aynı sonuç planını üreteceği göz önüne alındığında, korkunç bir şekilde iç içe geçmiş, çok alt sorgu içeren canavarlıklar oluşturmak için hiçbir neden göremiyorum - bunun yerine her bir bileşeni gerektiğinde görsel olarak yerleştirebildiğimiz zaman. XML dosyalarını içe aktarıyorum ve verileri doğru forma sokmak için çeşitli akrobasi yapıyorum, bu da CTE'ler olmadan yazmak / okumakta zorlanacaktır. (Eski kodumun bazılarının muhtemelen her yönden korkunç alt sorguları var!)
underscore_d

0

Her zaman olduğu gibi, ancak performansın büyük ölçüde arttığı durumlar var. Seçim için bir CTE kullandığınız ve daha sonra INSERT INTO'da kullandığınız SELECT deyimleriyle INSERT INTO ifadeleri ile görüyorum. Veri tabanı için RCSI'nin ayarlanması gerekebilir, ancak çok az seçili olan zamanlar için biraz yardımcı olabilir.

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.