10
votes

est "où (paramid = @paramid) ou (@paramid = -1)" une bonne pratique dans la sélection SQL

J'écris des stations SQL comme xxx

En savoir plus

et passe @Teacherid value = -1 pour sélectionner tous les enseignants

maintenant Je m'inquiète de la performance Pouvez-vous me dire que c'est une bonne pratique ou une mauvaise pratique?

Merci beaucoup


2 commentaires

George, vous ne pouvez pas imaginer à quel point votre question est «chaude». Vous venez de faire un grand mélange de «meilleures pratiques» et de «SQL» dans une seule question. Ajouté +1, ajouterait +100 si je pouvais.


J'écrirais généralement deux requêtes distinctes comme suggérées par @jeff O. Aussi, vous voudrez peut-être lire sur le paramètre reniflant. SQL dynamique et recompilation peuvent être plus chères dans ce cas - nous n'avons que deux scénarios distincts.


3 Réponses :


6
votes

Nous utilisons cela de manière très limitée dans les procédures stockées.

Le problème est que le moteur de base de données ne soit pas en mesure de conserver un bon plan de requête. Lorsque vous traitez avec beaucoup de données, cela peut avoir un impact sérieux de performance négatif grave. P>

Toutefois, pour des ensembles de données plus petits (je dirais moins de 1000 enregistrements, mais c'est une supposition) Ce devrait être bien. Vous devrez tester votre environnement particulier. P>

S'il est dans une procédure stockée, vous pouvez inclure quelque chose comme un avec recompiler code> option de sorte que le Plan est régénéré sur chaque exécution . Cela ajoute (légèrement) au moment de chaque exécution, mais plus de plusieurs exécutions peuvent réellement réduire le temps d'exécution moyen. En outre, cela permet à la base de données d'inspecter la requête réelle et "Court circuit" les pièces qui ne sont pas nécessaires sur chaque appel. P>

Si vous créez directement votre SQL et que vous le transmettez, je vous suggère de faire la pièce qui construit votre SQL un peu plus intelligent afin que cela n'inclut que le une partie de la clause où vous avez réellement besoin. P>


Un autre chemin à envisager est d'utiliser un syndicat toutes les requêtes, par opposition à des paramètres facultatifs. Par exemple: P>

SELECT * FROM Teacher WHERE (TeacherId = @TeacherID)
UNION ALL
SELECT * FROM Teacher WHERE (@TeacherId = -1)


3 commentaires

Votre union tout suppose enseignant id ne peut jamais être -1, donc je me demande, est-il possible de mettre cela dans une contrainte de telle manière que SQL Server peut figurer un bon plan en soi?


@HVD: Il est extrêmement rare que quelqu'un utiliserait un nombre négatif pour un identifiant. Au point que si vous êtes dans cette situation, vous devriez simplement passer null et tester pour cela au lieu d'utiliser -1


Je sais que, mais mon point est que l'optimiseur SQL Server Query NE PAS.



6
votes

Si enseignant id est indexé et que vous passez une valeur autre que -1 comme enseignante pour rechercher des informations détaillées d'un enseignant spécifique. La requête finira par faire une analyse de table complète plutôt que l'option potentiellement plus efficace de rechercher dans l'index pour récupérer les détails de l'enseignant spécifique ...

... à moins que vous ne soyez sur SQL 2008 SP1 CU5 et ultérieurement et utilisez l'option (recompiler) indice. Voir Conditions de recherche dynamiques dans T-SQL pour l'article définitif sur le sujet.


1 commentaires

+1 pour le lien vers le travail d'Erland. C'est absolument la réponse.



3
votes

Si vous êtes vraiment inquiet pour la performance, vous pouvez rompre votre procédure pour appeler deux processus différents: un pour tous les enregistrements et sur la base du paramètre.

If @TeacherID = -1
   exec proc_Get_All_Teachers
else
   exec proc_Get_Teacher_By_TeacherID @TeacherID


2 commentaires

Pour une simple situation comme ce que l'OP a montré, ce serait très bien. Cependant, il n'est pas maintenu si le nombre de paramètres de recherche facultatifs est supérieur à 1. Par exemple, si c'était 2, vous devriez avoir 4 S'ProCs ...


@Chrisllivement - SQL Server 2008 permettra le passage d'un paramètre de valorisation de table. L'instruction SELECT à l'intérieur du PROC pourrait utiliser cela au lieu d'un paramètre de valeur unique.