2017-10-17 5 views
0

Ich habe eine subscription Tabelle und eine payments Tabelle, die ich beitreten muss. Ich versuche, zwischen 2 Optionen zu entscheiden und die Leistung ist ein wichtiger Gesichtspunkt.Sollte ich einen Zeilennummernfilter im Join-Zustand oder in einem vorherigen CTE setzen?

Welche der folgenden beiden OPTIONEN wird besser funktionieren?

Ich bin mit Impala, und diese Tabellen sind groß (mehrere Millionen Zeilen) Ich bin, um nur für jede id eine Reihe zu bekommen und date Gruppierung (daher die row_number() analytische Funktion).

Ich habe die Anfragen verkürzt meine Frage zu erläutern:

OPTION 1:

WITH cte 
    AS (
    SELECT * 
     , SUM(amount) OVER (PARTITION BY id, date) 
     AS sameday_total 
     , ROW_NUMBER() OVER (PARTITION BY id, date ORDER BY purchase_number DESC) 
     AS sameday_rownum 
    FROM payments 
), 
payment 
AS (
    SELECT * 
    FROM cte 
    WHERE sameday_rownum = 1 
    ) 
    SELECT s.* 
     , p.sameday_total 
    FROM subscription 
    INNER JOIN payment ON s.id = p.id 

OPTION 2:

WITH payment 
    AS (
    SELECT * 
      , SUM(payment_amount) OVER (PARTITION BY id, date) 
      AS sameday_total 
      , ROW_NUMBER() OVER (PARTITION BY id, date ORDER BY purchase_number DESC) 
      AS sameday_rownum 
    FROM payments 
) 
SELECT s.* 
     , p.sameday_total 
FROM subscription 
INNER JOIN payment ON s.id = p.id 
        AND p.sameday_rownum = 1 
+1

Setzen Sie die Bedingung in die On-Klausel. Sie müssen die Abfrage nicht mit zwei CTEs überladen. –

+0

Danke. Also keine Auswirkung auf die Performance, da es sich um eine innere Verbindung handelt? Ich fragte mich, ob dies ähnlich der Leistung der Join-Bedingung Filterung im Vergleich zu Where-Klausel-Filterung im SQL-Prädikat der endgültigen SQL-Anweisung ist? – cdabel

+2

Sie sollten in der Lage sein, den Abfrageplan zu sehen, um zu sehen, ob der Optimierer den Filter am Anfang oder am Ende anwenden wird. – Connor

Antwort

1

Eine "Option 0" gibt es auch . Eine weit traditionellere "abgeleitete Tabelle", die einfach keine CTE benötigt.

SELECT s.* 
     , p.sameday_total 
FROM subscription 
INNER JOIN (
      SELECT * 
      , SUM(payment_amount) OVER (PARTITION BY id, date) 
       AS sameday_total 
      , ROW_NUMBER() OVER (PARTITION BY id, date ORDER BY purchase_number DESC) 
       AS sameday_rownum 
      FROM payments 
      ) p ON s.id = p.id 
        AND p.sameday_rownum = 1 

Alle Optionen 0,1 und 2 sind wahrscheinlich Pläne identisch oder sehr ähnlich erklären erzeugen (obwohl ich über diese Aussage für SQL Server zuversichtlicher bin als Impala).

Die Übernahme eines CTE führt - an sich - nicht zu einer effizienteren oder leistungsfähigeren Abfrage, so dass die Syntaxänderung zwischen Option 1 und 2 nicht wesentlich ist. Ich bevorzuge Option 0 selbst, da ich CTEs für bestimmte Aufgaben (z. B. Rekursion) bevorzuge.

Was Sie tun sollten, ist use explain plans zu studieren, was jede Option produziert.

Verwandte Themen