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
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.
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.