2010-12-31 2 views
0

Dies ist eine Frage der SQL-Theorie. Ich kann ein Beispiel geben, aber ich denke nicht, dass es nötig ist, um meinen Standpunkt zu verdeutlichen. Jeder, der Erfahrung mit SQL hat, wird sofort wissen, wovon ich rede.Wann CTEs zum Verkapseln von Unterergebnissen und wann sich das RDBMS über massive Joins Sorgen machen sollte

Normalerweise verwenden wir Joins, um die Anzahl der Datensätze zu minimieren, die durch die Übereinstimmung der linken und rechten Zeilen entstehen. Unter bestimmten Bedingungen verursachen Joining-Tabellen jedoch eine Multiplikation der Ergebnisse, wenn das Ergebnis alle Permutationen der linken und rechten Datensätze sind.

Ich habe eine Datenbank, die 3 oder 4 solche Joins hat. Dies macht aus ein paar Aufzeichnungen eine Vielzahl. Meine Sorge ist, dass die Tische in der Produktion groß sein werden, also wird die Anzahl dieser verbundenen Reihen immens sein. Außerdem wird in jeder Zeile eine schwere Mathematik ausgeführt, und die Idee, Mathe in doppelten Zeilen auszuführen, reicht aus, um jemanden zum Zittern zu bringen.

Ich habe zwei Fragen. Die erste ist, ist das etwas, das ich kümmern sollte, oder wird SQL Server intelligent erkennen diese Zeilen sind alle Duplikate und optimieren alle Verarbeitung entsprechend?

Die zweite ist, gibt es keinen Vorteil, jeden Teil der Abfrage gruppieren, um nur die unterschiedlichen Werte in den nächsten Teil der Abfrage in Gang zu bringen, wie etwas mit:

WITH t1 AS (
    SELECT DISTINCT... [or GROUP BY] 

), 
t2 AS (
    SELECT DISTINCT... 

), 
t3 AS (
    SELECT DISTINCT... 

) 
SELECT... 

ich oft gesehen die Verwendung von DISTINCT auf Unterabfragen angewendet. Es gibt offensichtlich einen Grund dafür. Ich spreche jedoch über etwas anderes und vielleicht subtiler und kniffliger.

+0

SQL Server wird wahrscheinlich nach unten drücken den Rechen skalare Operator auf die minimale Anzahl von Zeilen zu betreiben. Überprüfen Sie den Ausführungsplan. Ich würde logisch nicht unnötige "distinct" Anweisungen eingeben, da dies unnötige Sortierungen verursachen könnte. –

+0

Also die Hunderttausende von Zeilen, die tatsächlich auf nur ein paar Hundert herunterkochen, sind wahrscheinlich "virtuell"? Wenn Sie jedoch "SELECT * FROM T, T, T, T, T, T" sagen, wobei T 10 Zeilen hat, werden 1 Million Zeilen erstellt. Die Frage ist, werden diese nur erstellt, wenn sie gefragt werden?Warum fühlt sich das plötzlich wie die Frage an: "Wenn ein Baum in den Wald fällt und niemand da ist, um ihn zu hören, macht er immer noch ein Geräusch?" lol – IamIC

+0

Ich würde Ihre Datenbank-Design oder Abfrage-Design in Frage stellen, wenn Sie in den verschiedenen von Anfang an backen müssen. – DForck42

Antwort

0

ich nicht ganz sicher, ob der Frage bin, um ehrlich zu sein ...

Es gibt keinen Unterschied zwischen einem CTE und einer abgeleiteten Tabelle. Der CTE ist nur ein Makro.

WITH 
    t1 AS (SELECT DISTINCT... [or GROUP BY]), 
    t2 AS (SELECT DISTINCT...) 
SELECT * FROM t1 JOIN t2 ON ... 

ist die gleiche wie

SELECT 
    * 
FROM 
    (SELECT DISTINCT... [or GROUP BY]) t1 
    JOIN 
    (SELECT DISTINCT...) t2 ON ... 

Wo Sie Fragen ist Assoziativität von Tabellen

FROM 
    t1 
    LEFT JOIN 
    t2 ON t1. = t2. 
    JOIN 
    t3 ON t2. = t3. 

können unterschiedlich sein zu

FROM 
    t1 
    LEFT JOIN 
    (
    SELECT * 
    FROM 
    t2 
    JOIN 
    t3 ON t2. = t3. 
) Td ON t1. = Td. 

Allerdings haben kann, wenn Sie brauchen DISTINCTs in der Linie, dann es cou ld be "warum benutzt du EXISTS?" oder "warum hast du ave cartesian verbindet?"

+0

@gbn Ich hatte gehofft du würdest vorbeikommen. Frohes neues Jahr für Sie. Ich frage nicht nach einem CTE. Ich frage darüber, ob die Gruppierung/Unterscheidung der Ergebnisse entlang der Route Vorteile in einer mehrstufigen Abfrage bietet, oder ob es bedeutungslos ist, zuzulassen, dass die Datenmenge bis zum Ende multipliziert wird, an welchem ​​Punkt ein Unterschied besteht unoptional. – IamIC

+0

Ich würde es früh machen, wenn es Sinn macht. Aber für die Lesbarkeit, um ehrlich zu sein. Sie können Zwischenergebnisse reduzieren und das Problem effektiv in Schritte unterteilen. Vorbehaltlich meiner letzten Zeile über EXISTS oder kartesische Joins. Beachten Sie, dass die SQL-Anweisung deklarativ ist und Sie dem Optimierer nur mitteilen, was Sie wollen und nicht wie Sie es tun. Es kann irgendwelche Zwischengruppierungen ignorieren, oder es kann Ergebnisse "spoolen", wie Martins Antwort zeigt – gbn

+0

@ gbn, SQL-Server "wiederverwenden" das Zwischenergebnis, wenn Sie die gleiche Abfrage zweimal in der Hauptabfrage referenzieren? Oracle (manchmal) tut es, also wurde ich neugierig. – Ronnis

1

Sprichst du über eine Abfrage wie diese?

Sie können im Plan sehen, dass SQL Server die Berechnung für die kleine Anzahl von Zeilen vor dem Beitritt statt die große Anzahl Post-Join durchführt.

CREATE TABLE #BigTable 
(
n INT PRIMARY KEY 
); 


WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1), --2 
     E02(N) AS (SELECT 1 FROM E00 a, E00 b), --4 
     E04(N) AS (SELECT 1 FROM E02 a, E02 b), --16 
     E08(N) AS (SELECT 1 FROM E04 a, E04 b), --256 
     E16(N) AS (SELECT 1 FROM E08 a, E08 b) --65,536 
INSERT INTO #BigTable 
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT 0)) 
FROM E16   


CREATE TABLE #SmallTable 
(
n INT PRIMARY KEY 
); 

insert into #SmallTable select top 20 * from #BigTable ORDER BY n 

SELECT SIN(COS(LOG(#SmallTable.n))) 
FROM #SmallTable join #BigTable on #BigTable.n > #SmallTable.n 

Plan

+0

Punkt nochmal schön gemacht @Martin. – IamIC

Verwandte Themen