Externe Apply vs performance de jointure gauche

37

J'utilise SQL SERVER 2008 R2

Je viens de trouver APPLY dans SQL et j'ai adoré la résolution des problèmes de requête dans de nombreux cas,

La plupart des tables que j’utilisais joignaient à gauche pour obtenir le résultat, j’ai pu entrer dans une application externe.

J'ai peu de données dans mes tables de base de données locales et après le déploiement, le code est censé fonctionner sur des données au moins 20 fois plus grandes.

Je crains que l’application externe ne prenne plus de temps que les deux conditions de jointure restantes pour une grande quantité de données,

Quelqu'un peut-il dire exactement comment fonctionne exactement et comment cela affectera les performances dans des données très volumineuses, Si possible, des relations proportionnelles avec la taille de chaque tableau, telles que proportionnelles à n1 ^ 1 ou n1 ^ 2 ... où n1 est le nombre de lignes du tableau 1.

Voici la requête avec 2 jointures à gauche

select EC.*,DPD.* from Table1 eC left join
  (
   select member_id,parent_gid,child_gid,LOB,group_gid,MAX(table2_sid) mdsid from Table2
   group by member_id,parent_gid,child_gid,LOB,group_gid

  ) DPD2 on DPD2.parent_gid = Ec.parent_gid
        AND DPD2.child_gid = EC.child_gid
        AND DPD2.member_id = EC.member_id
        AND DPD2.LOB = EC.default_lob
        AND DPD2.group_gid = EC.group_gid
  left join
  Table2 dpd on dpd.parent_gid = dpd2.parent_gid 
            and dpd.child_gid = dpd2.child_gid
            and dpd.member_id = dpd2.member_id 
            and dpd.group_gid = dpd2.group_gid 
            and dpd.LOB = dpd2.LOB
            and dpd.table2_sid = dpd2.mdsid

Voici la requête avec outer apply

select * from Table1 ec   
OUTER APPLY (
      select top 1 grace_begin_date,retroactive_begin_date,Isretroactive
                    from Table2 DPD 
                    where DPD.parent_gid = Ec.parent_gid
                    AND DPD.child_gid = EC.child_gid
                    AND DPD.member_id = EC.member_id
                    AND DPD.LOB = EC.default_lob
                    AND DPD.group_gid = EC.group_gid
                    order by DPD.table2_sid desc
     ) DPD 
Pratyush Dhanuka
la source

Réponses:

44

Quelqu'un peut-il savoir comment exactement appliquer fonctionne et comment cela affectera les performances dans les très grandes données

APPLYest une jointure corrélée (appelée LATERAL JOINdans certains produits et versions plus récentes de SQL Standard). Comme toute construction logique, elle n’a pas d’impact direct sur les performances. En principe, nous devrions pouvoir écrire une requête en utilisant une syntaxe logiquement équivalente, et l'optimiseur transformerait notre entrée en exactement le même plan d'exécution physique.

Bien entendu, cela nécessiterait que l'optimiseur connaisse toutes les transformations possibles et ait le temps de les prendre en compte. Ce processus peut prendre plus de temps que l’âge actuel de l’univers, de sorte que la plupart des produits commerciaux n’adoptent pas cette approche. Par conséquent, la syntaxe de la requête peut avoir, et a souvent, une incidence sur les performances finales, bien qu'il soit difficile de formuler des déclarations générales sur ce qui est préférable et pourquoi.

La forme spécifique de OUTER APPLY ( SELECT TOP ... )est le plus susceptible d’entraîner la création d’une boucle imbriquée corrélée dans les versions actuelles de SQL Server, car l’optimiseur ne contient pas de logique pour transformer ce modèle en un équivalent JOIN. La jointure de boucles imbriquées corrélée peut ne pas fonctionner correctement si l'entrée externe est grande et si l'entrée interne n'est pas indexée ou si les pages nécessaires ne sont pas déjà en mémoire. De plus, des éléments spécifiques du modèle de coût de l'optimiseur signifient qu'une jointure de boucles imbriquées corrélée est moins susceptible qu'une sémantique identique JOINde produire un plan d'exécution parallèle.

J'ai pu faire la même requête avec une jointure à gauche et un numéro de ligne ()

Cela peut ou peut ne pas être mieux dans le cas général. Vous devrez tester les performances des deux alternatives avec des données représentatives. Le LEFT JOINet a ROW_NUMBERcertainement le potentiel d'être plus efficace, mais cela dépend de la forme précise du plan de requête choisie. Les principaux facteurs qui affectent l'efficacité de cette approche sont la disponibilité d'un index pour couvrir les colonnes nécessaires et pour fournir l'ordre requis par les clauses PARTITION BYet ORDER BY. Un deuxième facteur est la taille de la table. Une solution efficace et bien indexée APPLYpeut surpasser une ROW_NUMBERindexation optimale si la requête touche une partie relativement petite de la table concernée. Les tests sont nécessaires.

Paul White dit GoFundMonica
la source
2

La première requête peut être exécutée en parallèle par une seule demande au serveur SQL. Il récupère tous les enregistrements et donne une sortie basée sur des critères de filtre.

Mais dans le cas de la deuxième option, elle s'exécute ligne par ligne et pour chaque ligne, Table2 sera analysé et ajouté au résultat.

si votre requête externe a moins d’enregistrements, la seconde est meilleure (OUTER APPLY). Mais si la première requête peut obtenir plus de données, vous devez utiliser la première.

utilisateur55424
la source