2017-10-17 6 views
0

J'ai une table subscription et une table payments que j'ai besoin de joindre. J'essaie de choisir entre deux options et la performance est une considération clé.Dois-je mettre un filtre de numéro de ligne en condition de jointure ou dans un CTE antérieur?

Laquelle des deux OPTIONS ci-dessous fonctionnera le mieux?

J'utilise Impala, et ces tables sont grandes (plusieurs millions de lignes) Je suis besoin de seulement obtenir une ligne pour chaque id et date de groupement (donc la fonction analytique row_number()).

J'ai raccourci les requêtes pour illustrer ma question:

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

Mettez simplement la condition dans la clause 'on'. Pas besoin d'encombrer la requête avec deux CTE. –

+0

Merci. Donc, aucun impact sur les performances de toute façon, étant donné que c'est une jointure interne? Je me demandais si cela est similaire à la performance du filtrage des conditions de jointure par rapport au filtrage des clauses where dans le prédicat sql de l'instruction SQL finale? – cdabel

+2

Vous devriez être capable de dire en regardant le plan de requête pour voir si l'optimiseur va appliquer le filtre au début ou à la fin. – Connor

Répondre

1

Un "Option 0" existe aussi . Une «table dérivée» beaucoup plus traditionnelle qui n'exige pas l'utilisation d'un 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 

Toutes les options 0,1 et 2 sont susceptibles de produire des plans expliquer identiques ou très similaires (même si je suis plus confiant au sujet de cette déclaration pour SQL Server que Impala).

L'adoption d'un CTE ne permet pas, en soi, de rendre une requête plus efficace ou plus performante, donc l'altération de la syntaxe entre les options 1 et 2 n'est pas majeure. Je préfère moi-même l'option 0 car je préfère utiliser des CTE pour des tâches spécifiques (par exemple, la récursivité).

Ce que vous devez faire est use explain plans pour étudier ce que chaque option produit.