it-swarm.com.de

Vorteile des Common Table Expression (CTE)?

Von msdn :

Im Gegensatz zu einer abgeleiteten Tabelle kann ein CTE selbstreferenzierend sein und in derselben Abfrage mehrfach referenziert werden.

Ich verwende CTEs ziemlich oft, aber ich habe nie tief über die Vorteile ihrer Verwendung nachgedacht.

Wenn ich in derselben Abfrage mehrmals auf einen CTE verweise:

  • Gibt es einen Leistungsvorteil?
  • Wenn ich einen Self-Join durchführe, scannt SQL Server die Zieltabellen zweimal?
21
Royi Namir

In der Regel verbessert ein CTE NIEMALS die Leistung .

Ein CTE ist im Wesentlichen eine Wegwerfansicht. Es werden keine zusätzlichen Statistiken gespeichert, keine Indizes usw. Sie dienen als Abkürzung für eine Unterabfrage.

Meiner Meinung nach können sie EINFACH überbeansprucht werden (ich sehe in meinem Job viel Überbeanspruchung im Code). Einige gute Antworten finden Sie hier Wenn Sie jedoch mehr als einmal auf etwas verweisen müssen oder es sich um mehr als ein paar hunderttausend Zeilen handelt, setzen Sie es in ein #temp Tabelle stattdessen und indizieren Sie es.

25
JNK

Ein Ort neben der Rekursion, an dem ich CTEs unglaublich nützlich finde, ist das Erstellen komplexer Berichtsabfragen. Ich verwende eine Reihe von CTEs, um Teile der benötigten Daten abzurufen und sie dann in der endgültigen Auswahl zu kombinieren. Ich finde, dass sie einfacher zu pflegen sind, als dasselbe mit vielen abgeleiteten Tabellen oder 20 Verknüpfungen zu tun, und ich finde, dass ich sicherer sein kann, dass sie die korrekten Daten ohne Auswirkung mehrerer Datensätze aufgrund der Eins-Viele-Beziehungen in zurückgeben all die verschiedenen Joins. Lassen Sie mich ein kurzes Beispiel geben:

;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

Wenn Sie also die verschiedenen gewünschten Informationsblöcke trennen, können Sie jedes Teil einzeln überprüfen (mithilfe der auskommentierten Auswahlmöglichkeiten, indem Sie jedes einzeln auskommentieren und nur bis zu dieser Auswahl ausführen) und wenn Sie Änderungen an den Kosten vornehmen müssen Berechnung (in diesem Beispiel) ist es einfacher zu finden, als wenn sie alle zu einer massiven Abfrage zusammengemischt sind. Natürlich sind die tatsächlichen Berichtsabfragen, für die ich dies verwende, im Allgemeinen viel komplizierter als das Beispiel.

14
HLGEM

Wie immer kommt es darauf an, aber es gibt Fälle, in denen die Leistung stark verbessert wird. Ich sehe es mit INSERT INTO SELECT-Anweisungen, bei denen Sie einen CTE für die Auswahl verwenden und diesen dann in INSERT INTO verwenden. Dies hat möglicherweise damit zu tun, dass RCSI für die Datenbank aktiviert ist, aber in Zeiten, in denen nur sehr wenig ausgewählt ist, kann dies erheblich hilfreich sein.

0
Ron S