2017-10-05 16 views
1

Quelle est la meilleure façon de structurer/écrire une requête dans Hive quand j'ai une sous-requête complexe répétée plusieurs fois dans l'instruction select?Hive - comment réutiliser une sous-requête dans la ruche avec des performances optimales

J'ai créé à l'origine une table temporaire pour la sous-requête qui a été actualisée avant chaque exécution. Ensuite, j'ai commencé à utiliser un CTE dans le cadre de la requête d'origine (en supprimant la table temporaire) pour la lisibilité et j'ai remarqué une dégradation des performances. Cela m'a rendu curieux de savoir quelles méthodes d'implémentation sont les meilleures en termes de performances lorsque vous avez besoin de réutiliser des sous-requêtes.

Les données avec lesquelles je travaille contiennent plus de 10 millions d'enregistrements. Voici un exemple de la requête que j'ai écrite qui a fait usage d'un CTE.

with temp as (
    select 
     a.id, 
     x.type, 
     y.response 
    from sandbox.tbl_form a 
    left outer join sandbox.tbl_formStatus b 
    on a.id = b.id 
    left outer join sandbox.tbl_formResponse y 
    on b.id = y.id 
    left outer join sandbox.tbl_formType x 
    on y.id = x.typeId 
    where b.status = 'Completed' 
) 
select 
    a.id, 
    q.response as user, 
    r.response as system, 
    s.response as agent, 
    t.response as owner 
from sandbox.tbl_form a 
left outer join (
    select * from temp x 
    where x.type= 'User' 
) q 
on a.id = q.id 
left outer join (
    select * from temp x 
    where x.type= 'System' 
) r 
on a.id = r.id 
left outer join (
    select * from temp x 
    where x.type= 'Agent' 
) s 
on a.id = s.id 
left outer join (
    select * from temp x 
    where x.type= 'Owner' 
) t 
on a.id = t.id; 

Répondre

1

Il y a des problèmes dans votre requête.

1) Dans le CTE, vous avez trois jointures à gauche sans clause ON. Cela peut entraîner de sérieux problèmes de performances car les jointures sans clause ON sont des CROSS JOINS.

2) La clause BTW where b.status = 'Completed' convertit la jointure LEFT avec la table b pour la jointure interne bien que toujours sans la clause ON elle multiplie tous les enregistrements d'un par tous les enregistrements de b avec un où.

3) Très probablement, vous n'avez pas besoin de CTE du tout. Il suffit de joindre correctement la clause ON et d'utiliser case when type='User' then response end + agrégat en utilisant min() ou max() par id