11
votes

Pourquoi les performances de ces 2 requêtes sont-elles si différentes?

J'ai un PROC stocké qui recherche des produits (250 000 lignes) à l'aide d'un index de texte complet.

Le processus stocké prend un paramètre qui est la condition de recherche de texte complète. Ce paramètre peut être null, alors j'ai ajouté une vérification nulle et la requête a soudainement commencé à exécuter des ordres de grandeur plus lentement. xxx

Voici les plans d'exécution:

Quertise n ° 1 usine d'exécution # 1

requête n ° 2 usine d'exécution # 2

Je dois admettre que je ne suis pas très familier avec les plans d'exécution. La seule différence évidente pour moi est que les jointures sont différentes. J'essaierais d'ajouter un indice mais de ne pas rejoindre dans ma requête, je ne sais pas comment faire ça.

Je ne comprends pas non plus pourquoi l'indice appelé ix_sectiondid est utilisé, car il s'agit d'un indice que contient la sectionIDE de la colonne et cette colonne n'est utilisée nulle part.


0 commentaires

3 Réponses :


8
votes

ou code> peut écraser les performances, alors faites-le ainsi:

DECLARE @Filter VARCHAR(100)
SET @Filter = 'FORMSOF(INFLECTIONAL, robe)'

IF @Filter IS NOT NULL
BEGIN
    SELECT TOP 100 ID FROM dbo.Products
    WHERE CONTAINS(Name, @Filter)
END
ELSE
BEGIN
    SELECT TOP 100 ID FROM dbo.Products
END


1 commentaires

Nice article - Ajout d'une option (recompilation) résout réellement le problème de performance sur la 2e requête (toutefois un autre problème est que contient () augmente une erreur lorsque le paramètre est null, mais C'est un autre problème).



1
votes

Vous avez introduit un ou des conditions. Dans la plupart des cas, il est tout simplement beaucoup plus rapide de vérifier explicitement pour NULL et de réaliser une requête vs votre méthode.

Par exemple, essayez ceci: xxx


0 commentaires

3
votes

Le premier plan de requête semble simple:

  1. Une recherche de texte complète à résolution contient (nom, @filter)
  2. Un scan d'index pour rechercher les autres colonnes des lignes correspondantes
  3. Combinez les deux à l'aide d'une jointure de hachage

    le Opérateur de concaténation forme une union de deux matches. Il semble donc que la deuxième requête fait:

    1. Un scan d'index (ultérieurement utilisé pour rechercher d'autres colonnes)
    2. une analyse constante. Je suppose que cela traite votre requête comme non paramétré, le plan de requête n'a donc pas à fonctionner pour une autre valeur de @filter . Si correct, la balayage constante résout @filter n'est pas null .
    3. Une recherche de texte complète à résolution contient (nom, @filter)
    4. Unions le résultat de 3 avec l'ensemble vide de 2
    5. La boucle relie le résultat de 1 et 4 pour rechercher les autres colonnes

      Un jointure de hachage Mémoire à la vitesse de la vitesse; Si votre système a suffisamment de mémoire, c'est beaucoup plus rapide qu'une jointure en boucle. Cela peut facilement expliquer un ralentissement 10-100x.

      Un correctif consiste à utiliser deux requêtes distinctes: xxx


2 commentaires

Intéressant - Y a-t-il un moyen de forcer une hachage rejoindre la deuxième requête?


Oui, vous pouvez le réécrire en utilisant Inner Hash Join Join , mais ce serait plutôt complexe. Il serait préférable d'utiliser l'une des solutions de l'article de Sommarskog.