Question

La question après assez longtemps de ébullition dans ma tête, à savoir celle sur les deux procédures stockées suivantes dont l’une serait plus performante.

Proc 1

CREATE PROCEDURE GetEmployeeDetails @EmployeeId uniqueidentifier,
@IncludeDepartmentInfo bit

AS
BEGIN

    SELECT * FROM Employees 
    WHERE Employees.EmployeeId = @EmployeeId

    IF (@IncludeDepartmentInfo = 1)
    BEGIN
        SELECT Departments.* FROM Departments, Employees
        WHERE Departments.DepartmentId = Employees.DepartmentId 
        AND Employees.EmployeeId = @EmployeeId
    END
END

Proc 2

CREATE PROCEDURE GetEmployeeDetails @EmployeeId uniqueidentifier,
 @IncludeDepartmentInfo bit
AS
BEGIN

    SELECT * FROM Employees 
    WHERE Employees.EmployeeId = @EmployeeId

    SELECT Departments.* FROM Departments, Employees
    WHERE Departments.DepartmentId = Employees.DepartmentId 
    AND Employees.EmployeeId = @EmployeeId 
    AND @IncludeDepartmentInfo = 1

END

la seule différence entre les deux réside dans l'utilisation de 'if statment'.

si proc 1 / proc 2 sont appelés avec des valeurs alternées de @IncludeDepartmentInfo, alors, à ma connaissance, proc 2 fonctionnerait mieux, car il conservera le même plan de requête, quelle que soit la valeur de @IncludeDepartmentInfo, alors que proc1 modifiera le plan de requête en chaque appel

les réponses sont vraiment impérieuses

PS: il ne s’agit que d’un scénario. Ne vous adressez pas aux résultats de la requête explicite, mais à l’essence de l’exemple. Je suis particulièrement attentif au résultat de l'optimiseur de requêtes (dans les deux cas de 'si et où' et de leur différence), de nombreux aspects pourraient affecter les performances que je souhaite éviter dans cette question.

Était-ce utile?

La solution

SELECT Departments.* FROM Departments, Employees
    WHERE Departments.DepartmentId = Employees.DepartmentId 
    AND Employees.EmployeeId = @EmployeeId 
    AND @IncludeDepartmentInfo = 1

Lorsque SQL compile une requête de ce type, elle doit être compilée pour toute valeur de @IncludeDepartmentInfo. Le plan résultant peut en être un qui analyse les tables et effectue la jointure et après qui vérifie la variable, ce qui entraîne des entrées / sorties inutiles. L'optimiseur peut être intelligent et déplacer la vérification de la variable avant les opérations d'E / S réelles dans le plan d'exécution, mais cela n'est jamais garanti. C'est pourquoi je recommande toujours d'utiliser des FI explicites dans le T-SQL pour les requêtes qui doivent être exécutées très différemment en fonction d'une valeur de variable (l'exemple typique étant les conditions OU).

L’observation de gbn est également importante: du point de vue de la conception de l’API, il est préférable d’avoir un type de retour cohérent (c’est-à-dire qu'il renvoie toujours la même forme et le même nombre d’ensembles de résultats).

Autres conseils

Du point de vue de la cohérence, le numéro 2 renverra toujours 2 jeux de données. Outre la surcharge, vous n’auriez pas de méthode de code client susceptible de renvoyer un résultat, peut-être pas.

Si vous réutilisez ce code, l'autre client appelant devra également connaître cet indicateur.

Si le code fait 2 choses différentes, alors pourquoi ne pas 2 procs stockées différentes?

Enfin, il est de loin préférable d'utiliser la syntaxe JOIN moderne et de séparer la jointure du filtrage. Dans ce cas, personall y utiliserais également EXISTS.

SELECT
    D.*
FROM
    Departments D
    JOIN
    Employees E ON D.DepartmentId = E.DepartmentId
WHERE  
    E.EmployeeId = @EmployeeId 
    AND
    @IncludeDepartmentInfo = 1

Lorsque vous utilisez l'instruction 'if', vous ne pouvez exécuter qu'une requête au lieu de deux. Je penserais qu'une requête serait presque toujours plus rapide que deux. Votre remarque sur les plans de requête peut être valable si la première requête était complexe et longue à exécuter, et la seconde était triviale. Cependant, la première requête donne l'impression de récupérer une seule ligne basée sur une clé primaire, ce qui est probablement assez rapide à chaque fois. Donc, je garderais le 'si' - mais je testerais pour vérifier.

La différence de performances serait trop petite pour que personne ne puisse la remarquer.

L'optimisation prématurée est à l'origine du mal. Ne vous inquiétez plus pour les performances et commencez à mettre en œuvre des fonctionnalités qui font sourire vos clients.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top