Les performances de requête SQL se dégradent en fonction de l'ordre des valeurs de search

J'ai une double requête d'auto-jointure où la performance est sévèrement dégradée lorsque les valeurs de search sont permutées.

-- 500,000 i/o & 500ms execution select fooA.ID , fooB.ID from foo AS fooA INNER JOIN bar AS barA ON fooA.barID = barA.barID INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join INNER JOIN bar AS barB ON fooB.barID = barB.barID where barA.value = 'xyz' AND barB.value = '60' -- 5,000 i/o & 5ms execution select fooA.ID , fooB.ID from foo AS fooA INNER JOIN bar AS barA ON fooA.barID = barA.barID INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join INNER JOIN bar AS barB ON fooB.barID = barB.barID where barA.value = '60' AND barB.value = 'xyz' 
  • La valeur "xyz" est répertoriée 150 000 fois dans le tableau "barre".
  • La valeur "60" est répertoriée 500 fois dans le tableau "barre".
  • Les plans de requête sont les mêmes, sauf que la boucle la plus interne renvoie 150 000 lignes ou 500 lignes selon la valeur de search répertoriée en premier.
  • Les searchs effectuées searchnt des index non clusterisés.
  • Les statistics ont été mises à jour sur les deux tables avec FULLSCAN.

Pourquoi l'optimiseur de requête SQL n'identifie-t-il pas correctement que dans les deux instances, la jointure la plus interne du plan de requête doit être celle avec le less de lignes?

    SQL Server ne recomstack pas une requête chaque fois qu'il est exécuté. Il le fait une fois, et il est optimisé pour les valeurs exactes qu'il voit la première fois. Je suppose que vous avez un plan malheureux mis en cache.

    Essayez d'append OPTION (RECOMPILE) à la fin.