L'ajout d'une clause Where supplémentaire dans SQL génère un grand succès

J'ai une requête SQL qui traverse plusieurs vues et tables.

La requête fonctionne bien, mais lorsque j'ai ajouté une autre condition dans la clause WHERE, elle a commencé à avoir un impact énorme sur la performance.

La requête est structurée comme …

SELECT a.* FROM vw_myView a LEFT OUTER JOIN tbl1 b ON a.ID = b.ID LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID WHERE a.Column1 = 'VALUE' AND a.Column2 LIKE ISNULL(@parameter, a.Column2) 

À partir de la requête ci-dessus, lorsque j'ajoute l'autre condition dans la clause WHERE, ma requête prend maintenant beaucoup de time (plus de 3 minutes) pour exécuter et renvoyer 1000 loggings. La suppression de la clause conditionnelle et de la requête ajoutées renvoie les loggings en less de 7 secondes.

Merci. Que devrais-je vérifier pour voir où la performance est énorme

Votre clause de requête AND a.Column2 LIKE ISNULL(@parameter, a.Column2) implique l'appel d'une fonction, ainsi SQL Server doit effectuer une parsing de table (ie tester cette fonction sur chaque ligne) dans votre table pour voir si elle satisfait la requête .

Même si vous aviez un index sur a.Column2, Sql Server ne serait pas capable de l'utiliser.

[EDIT] C'est un moyen de l'accélérer dans la plupart des cas

 -- Only this part executes when the @parameter has a value. -- It returns nothing and executes fast when @parameter is NULL SELECT a.* FROM vw_myView a LEFT OUTER JOIN tbl1 b ON a.ID = b.ID LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID WHERE a.Column1 = 'VALUE' AND a.Column2 LIKE @parameter UNION ALL -- This part does not execute when the @paramter has a value -- This will leave the 2nd query clause out and run faster when @parameter is not specified, avoiding a table scan SELECT a.* FROM vw_myView a LEFT OUTER JOIN tbl1 b ON a.ID = b.ID LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID WHERE a.Column1 = 'VALUE' AND @parameter IS NULL 

Regardez le plan d'exécution de votre requête. Je vais parier des dollars à des beignets que votre argument de search supplémentaire provoque une parsing de table, une procédure très coûteuse, au niveau de la performance.

Le SQL dynamic est probablement votre meilleur pari. Créez une instruction si le paramètre est nul et différent si ce n'est pas le cas. C'est la manière commune que les searchs sont faites plus rapidement avec beaucoup de parameters possibles.

Puisque vous avez seulement les deux conditions, je pourrais essayer de l'écrire comme ceci: IF @parameter IS NULL

 BEGIN SELECT a.* FROM vw_myView a LEFT OUTER JOIN tbl1 b ON a.ID = b.ID LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID WHERE a.Column1 = 'VALUE' AND a.Column2 LIKE a.Column2 END ELSE BEGIN SELECT a.* FROM vw_myView a LEFT OUTER JOIN tbl1 b ON a.ID = b.ID LEFT OUTER JOIN vw_OtherView c ON a.ID = c.ID LEFT OUTER JOIN tbl2 d ON c.OtherID = d.OtherID WHERE a.Column1 = 'VALUE' AND a.Column2 LIKE @parameter END 

Bien sûr, vous ne devez jamais utiliser SELECT * dans le code de production et utiliser = si possible au lieu de LIKE. Et si ces vues referencent les mêmes tables, l'interrogation directe des tables peut être un meilleur choix pour les performances.

essaye ça.

 AND (a.Column2 = @parameter OR @parameter is NULL) 

Ne comprends pas pourquoi vous utilisez comme?

voulez-vous faire quelque chose comme ça

 AND (a.Column2 like @parameter+'%' OR @parameter is NULL) 

Pourquoi faire ceci? AND a.Column2 LIKE ISNULL(NULL, a.Column2)
Cela va toujours vérifier a.Column2 LIKE a.Column2
a.Column2 IS NULL -tu de vérifier a.Column2 IS NULL ?

Pouvez-vous publier la requête telle qu'elle était avant de la modifier?

[Modifier]
Je ne connais pas votre database cible, mais si c'est Sybase je vous met en garde contre l'utilisation de @parameter + '%' qui effectuera une parsing de table. Vous pouvez en lire plus sur To LIKE ou ne pas aimer .