Comment optimiser l'utilisation du « OU » article lorsqu'il est utilisé avec les paramètres (SQL Server 2008)

StackOverflow https://stackoverflow.com/questions/2161573

Question

Je me demande s'il y a un moyen sage de réécrivez la requête suivante afin que les index sur les colonnes utilisées par se optimiseur?

Create Procedure select_Proc1
    @Key1 int=0,
    @Key2 int=0
As
BEGIN
    Select key3
    From Or_Table
    Where (@key1 =0 OR Key1 =@Key1) AND
          (@key2 =0 OR Key2 =@Key2)
END
GO

Même si des colonnes dans les clauses WHERE sont couvertes par des index, SQL Server ne peut pas utiliser ces indices. Cela pose la question de savoir si quelque chose est « blocage » l'utilisation des index. La réponse à cette question est oui - les coupables sont les paramètres et la condition « OU ». Les paramètres ne sont pas couverts par des index, ce qui signifie que SQL Server ne peut pas utiliser les indices pour évaluer « @ key1 = 0 » (une condition qui applique également à @ key2 = 0). En effet, cela signifie que SQL Server ne peut pas utiliser les index pour évaluer la clause « @ key1 = 0 OU clé1 = @ key1 » (comme la clause « OU » est l'union des lignes couvertes par les deux conditions). Le même principe s'applique à l'autre clause (re. Key2) ainsi. Cela conduit SQL Server pour conclure qu'aucun index peut être utilisé pour extraire les lignes, laissant SQL Server pour utiliser la meilleure approche suivante - un balayage index cluster

Comme vous le voyez, l'optimiseur SQL ne sera pas utiliser les index sur les colonnes si les prédicats sont « OU » ed dans la clause WHERE. Une solution à ce problème, est de séparer les requêtes avec la clause IF pour toutes les combinaisons possibles de paramètres.

S'il vous plaît lire cet article court pour obtenir une meilleure vue du problème: http://www.sql-server-performance.com/articles/per/optimize_or_clause_p1.aspx

Maintenant, ma question est, que devons-nous faire si les combinaisons possibles sont plus que seulement trois ou quatre? Rédaction d'une requête distincte pour chaque combinaison ne semble pas une solution rationnelle. Y at-il autre solution pour ce problème?

Était-ce utile?

La solution

SQL Server est pas très bon dans l'optimisation des prédicats OR.

Utilisez ceci:

SELECT  key3
FROM    or_table
WHERE   @key1 = 0
        AND @key2 = 0
UNION ALL
SELECT  key3
FROM    or_table
WHERE   @key1 = 0
        AND @key2 <> 0
        AND key2 = @key2
UNION ALL
SELECT  key3
FROM    or_table
WHERE   @key2 = 0
        AND @key1 <> 0
        AND key1 = @key1
UNION ALL
SELECT  key3
FROM    or_table
WHERE   @key1 <> 0
        AND @key2 <> 0
        AND key1 = @key1
        AND key2 = @key2

SQL Server regardera les valeurs des variables avant d'exécuter les requêtes et optimiser les requêtes redondantes sur.

Cela signifie qu'une seule requête de quatre sera effectivement exécuté.

Autres conseils

MSSQL 2008 a la syntaxe d'optimisation de la simplification de l'état, il est ici

 Where (@key1 =0 OR Key1 =@Key1) AND
      (@key2 =0 OR Key2 =@Key2) option(recompile)

Ceci permet d'optimiser l'utilisation des constantes

Avez-vous tente une fonction d'une valeur de table?

CREATE FUNCTION select_func1 (  
    @Key1 int=0,
    @Key2 int=0
)
RETURNS TABLE 
AS RETURN (
    Select key3
    From Or_Table
    Where (@key1 =0 OR Key1 =@Key1) AND
          (@key2 =0 OR Key2 =@Key2)
)


select * from select_func1(1,2)

Oui - attention utilisation de SQL dynamique va résoudre ce problème. Il y a deux façons de le faire:

a. Si vous êtes un « puriste » à propos de procs stockées, puis composer une chaîne de requête personnalisée dans un proc stocké et exécuter la chaîne. La requête spécifique peut alors être dynamiquement écrit par l'exécution d'inclure uniquement les critères pertinents.

b. Si vous êtes flexible sur l'emplacement de ce SQL, vous pouvez (encore une fois ATTENTIVEMENT) composes la chaîne de requête dans votre application et passez sur le serveur.

Le danger, bien sûr, est d'environ injection SQL. Donc, vous devez être très prudent lorsque les données sont transmises du client dans l'instruction SQL dynamique.

Information complète de Erland Sommarskog: http://www.sommarskog.se/dynamic_sql.html et http://www.sommarskog.se/dyn-search.html

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