2017-10-17 187 views
0

我有一個subscription表和一個payments表,我需要加入。 我試圖在2個選項之間做出決定,性能是一個關鍵考慮因素。我應該在連接條件還是先前的CTE中放置行號過濾器?

以下兩個選項中哪一個表現更好?

我正在使用Impala,並且這些表很大(數百萬行)我只需要爲每個iddate分組(因此爲row_number()分析函數)獲得一行。

我已經縮短了的查詢來說明我的問題:

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 

選項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

只要將條件放在'on'子句中即可。無需使用兩個CTE混淆查詢。 –

+0

謝謝。因此,考慮到它是內連接,所以沒有任何性能影響?我想知道這是否類似於連接條件過濾的性能與最終SQL語句的SQL謂詞中的where子句過濾的性能? – cdabel

+2

您應該能夠通過查看查詢計劃來查看優化程序是要在開始還是結束時應用篩選器。 – Connor

回答

1

的 「選項0」 也存在。一個更傳統的「派生表」,它根本不需要使用任何CTE。

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 

所有選項0,1和2都可能產生相同或非常相似的解釋計劃(雖然我對SQL Server的這一陳述比Impala更有信心)。

採用CTE本身並不會使查詢效率更高或性能更好,因此選項1和2之間的語法更改並不重要。我更喜歡選項0,因爲我更喜歡將CTE用於特定任務(例如遞歸)。

你應該做的是use explain plans研究每個選項產生什麼。

相關問題