web-dev-qa-db-fra.com

Application externe vs performances de jointure gauche

J'utilise SQL SERVER 2008 R2

Je suis juste tombé sur APPLY dans SQL et j'ai adoré la façon dont il résout les problèmes de requête dans de nombreux cas,

Beaucoup de tables que j'utilisais 2 jointures gauches pour obtenir le résultat, j'ai pu entrer dans 1 application externe.

J'ai une petite quantité de données dans mes tables de base de données locales et après le déploiement, le code est censé s'exécuter sur des données au moins 20 fois plus importantes.

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

Quelqu'un peut-il dire comment fonctionne exactement l'application et comment cela affectera-t-il les performances dans les données très volumineuses? Si possible, des relations proportionnelles avec la taille de chaque table comme 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 application externe

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 
38
Pratyush Dhanuka

Quelqu'un peut-il dire comment fonctionne exactement l'application et comment cela affectera-t-il les performances dans les très grandes données

APPLY est un jointure corrélée (appelé LATERAL JOIN dans certains produits et versions plus récentes de la norme SQL). Comme toute construction logique, elle n'a pas d'impact direct sur les performances. En principe, nous devrions être capables d'écrire une requête en utilisant n'importe quelle syntaxe logiquement équivalente, et l'optimiseur transformerait notre entrée en exactement le même plan d'exécution physique.

Bien sûr, cela nécessiterait que l'optimiseur connaisse toutes les transformations possibles et ait le temps de considérer chacune. Ce processus pourrait bien 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 des requêtes peut, et a souvent, un impact sur les performances finales, bien qu'il soit difficile de faire des déclarations générales sur ce qui est le mieux et pourquoi.

La forme spécifique de OUTER APPLY ( SELECT TOP ... ) est plus susceptible d'entraîner une jointure de boucles imbriquées corrélées dans les versions actuelles de SQL Server, car l'optimiseur ne contient pas de logique pour transformer ce modèle en JOIN équivalent. La jointure de boucles imbriquées corrélées 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ées est moins susceptible qu'un JOIN sémantiquement identique de produire un plan d'exécution parallèle.

J'ai pu faire la même requête avec une seule jointure gauche et row_number ()

Cela peut être meilleur ou pas dans le cas général. Vous devrez tester les performances des deux alternatives avec des données représentatives. LEFT JOIN Et ROW_NUMBER Ont certainement le potentiel d'être plus efficaces, 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 la commande requise par les clauses PARTITION BY Et ORDER BY. Un deuxième facteur est la taille de la table. Un APPLY efficace et bien indexé peut surpasser un ROW_NUMBER Avec une indexation optimale si la requête touche une portion relativement petite de la table concernée. Des tests sont nécessaires.

46
Paul White 9

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

Mais dans le cas du second, il s'exécute ligne par ligne et pour chaque ligne, le tableau 2 sera analysé et ajouté en conséquence.

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

3
user55424