Utilisation de l'indicateur de table FORCESEEK

L'indicateur de table FORCESEEK force l'optimiseur de requête à utiliser uniquement une opération de recherche d'index comme chemin d'accès aux données dans la table ou la vue référencée dans la requête. Cet indicateur de table vous permet de substituer le plan par défaut choisi par l'optimiseur de requête pour éviter des problèmes de performances provoqués par un plan de requête inefficace. Par exemple, si un plan contient des opérateurs d'analyse de table ou d'index, et que les tables correspondantes entraînent un nombre élevé de lectures pendant l'exécution de la requête, comme observé dans la sortie STATISTICS IO, forcer une opération de recherche d'index peut améliorer les performances des requêtes. Cela est particulièrement vrai lorsque des estimations de cardinalité ou de coût inexactes conduisent l'optimiseur à favoriser des opérations d'analyse au moment de la compilation du plan.

FORCESEEK s'applique aux opérations de recherche d'index cluster et non-cluster. Il peut être spécifié pour toute table ou vue dans la clause FROM d'une instruction SELECT et dans la clause FROM <table_source> d'une instruction UPDATE ou DELETE.

AttentionAttention

Étant donné que l'optimiseur de requête SQL Server sélectionne généralement le meilleur plan d'exécution pour une requête, nous vous recommandons de ne recourir aux indicateurs qu'en dernier ressort, et à condition d'être un développeur ou un administrateur de base de données expérimenté.

Évaluation de plans de requête pour l'applicabilité de FORCESEEK

L'indicateur de table FORCESEEK peut être utile lorsque le plan de requête utilise un opérateur d'analyse de table ou d'index sur une table ou une vue, alors qu'un opérateur de recherche d'index pourrait être plus efficace. Considérez la requête et le plan d'exécution suivants.

USE AdventureWorks2008R2;
GO
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d 
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO

Le plan d'exécution suivant indique que l'optimiseur de requête a choisi un opérateur d'analyse d'index cluster pour accéder aux données dans les deux tables.

Plan d'exécution avec opérateurs d'analyse d'index cluster

Vous pouvez forcer l'optimiseur de requête à effectuer une opération de recherche sur la table Sales.SalesOrderDetail en spécifiant l'indicateur FORCESEEK, tel qu'indiqué dans la requête suivante.

USE AdventureWorks2008R2;
GO
SELECT *
FROM Sales.SalesOrderHeader AS h
INNER JOIN Sales.SalesOrderDetail AS d WITH (FORCESEEK)
    ON h.SalesOrderID = d.SalesOrderID 
WHERE h.TotalDue > 100
AND (d.OrderQty > 5 OR d.LineTotal < 1000.00);
GO

Le plan d'exécution suivant montre les résultats de l'utilisation de l'indicateur FORCESEEK dans la requête. Une opération de recherche d'index cluster est utilisée pour accéder aux données dans la table Sales.SalesOrderDetail.

Plan d'exécution avec opérateur d'analyse d'index cluster

Prise en charge de l'union et de l'intersection d'index

L'indicateur FORCESEEK prend en charge les unions et les intersections d'index. L'indicateur rend l'optimiseur de requête plus susceptible d'utiliser ces techniques. Pour éviter de ralentir le temps de compilation des requêtes simples, les unions et intersections d'index sont normalement choisies uniquement d'après des règles qui prennent en compte la cardinalité et la sélectivité des colonnes. Toutefois, lorsque l'indicateur FORCESEEK est spécifié, ces règles sont ignorées et ces techniques sont toujours considérées. Examinons, par exemple, la requête suivante :

SELECT * FROM T WITH(FORCESEEK) WHERE T.a = 1 AND T.b = 2;

Si les colonnes a et b contiennent des index non-cluster distincts dans la table T, un plan d'intersection d'index peut être choisi. Autrement dit, le plan contient une opération de recherche d'index non-cluster sur les colonnes a et b et croise les jeux de clés d'index obtenus avant d'effectuer une opération de recherche dans la table de base.

Dans l'exemple suivant, un plan d'union d'index est choisi. Autrement dit, le plan contient une opération de recherche sur les colonnes a et b, et unit les jeux de clés d'index obtenus, avant d'effectuer une opération de recherche dans la table de base.

SELECT * FROM T WITH(FORCESEEK) WHERE T.a = 1 OR T.b = 2;

Utilisation de FORCESEEK dans des requêtes contenant des prédicats LIKE ou IN

Les règles de l'optimiseur de requête et une estimation médiocre de la cardinalité peuvent également conduire l'optimiseur à effectuer une opération d'analyse d'index plutôt qu'une recherche d'index lorsqu'une requête utilise IN ou LIKE comme prédicats de recherche.

L'exemple suivant montre comment l'indicateur FORCESEEK peut forcer l'optimiseur de requête à effectuer une opération de recherche d'index plutôt qu'une analyse de table lorsque LIKE ou IN sont utilisés comme prédicats de recherche. Pour afficher les plans d'exécution de requête, cliquez sur le bouton de la barre d'outils Inclure le plan d'exécution réel avant d'exécuter l'exemple.

USE tempdb;
GO
DROP TABLE t;
GO
CREATE TABLE t(i int UNIQUE, j int, vc varchar(100));
CREATE INDEX t_vc ON t(vc);
GO
DECLARE @p1 int, @p2 int, @p3 int, @p4 int, @p5 int;
SELECT * FROM t WHERE i IN (@p1, @p2, @p3, @p4, @p5);
GO
DECLARE @p1 int, @p2 int, @p3 int, @p4 int, @p5 int;
SELECT * FROM t WITH (FORCESEEK) WHERE i IN (@p1, @p2, @p3, @p4, @p5);
GO
SELECT * FROM t WHERE vc LIKE 'Test%';
GO
SELECT * FROM t WITH (FORCESEEK) WHERE vc LIKE 'Test%';
GO
DECLARE @vc varchar(100);
SELECT * FROM t WHERE vc LIKE @vc;
GO
DECLARE @vc varchar(100);
SELECT * FROM t WITH (FORCESEEK) where vc like @vc;
GO

Utilisation de FORCESEEK sur des vues

FORCESEEK peut être spécifié avec ou sans indicateur d'index. Lorsque vous appliquez un indicateur de table FORCESEEK à une vue ou une vue indexée, l'indicateur FORCESEEK est propagé de manière récursive sur toutes les tables dans la version développée de la vue. L'indicateur d'index, s'il est spécifié, est ignoré. Si les tables sous-jacentes ne possèdent pas au moins un index chacune, aucun plan n'est trouvé et l'erreur 8622 est retournée.

Lorsque vous utilisez simultanément les indicateurs FORCESEEK et NOEXPAND sur une référence à une vue indexée, la vue indexée est utilisée sans être développée au préalable. L'indicateur FORCESEEK est appliqué directement à la vue indexée, qui est traitée comme une table.

Si vous appliquez un indicateur FORCESEEK à une référence de table, la référence de table ne peut pas participer à la mise en correspondance de vue indexée. Toutefois, les autres parties de la requête qui ne sont pas affectées par l'indicateur FORCESEEK peuvent participer à la mise en correspondance de vue indexée. Ceci est comparable au comportement de la correspondance de vue indexée lorsqu'elle est utilisée avec des indicateurs INDEX.

Méthodes préconisées

Nous vous recommandons d'appliquer les méthodes conseillées ci-dessous :

  • Avant d'utiliser l'indicateur de table FORCESEEK, assurez-vous que les statistiques sur la base de données sont actuelles et exactes.

    Avec des statistiques à jour, l'optimiseur peut évaluer correctement le coût de différents plans de requête et choisir un plan de haute qualité. Par conséquent, nous vous recommandons d'affecter la valeur ON (la valeur par défaut) aux options AUTO_CREATE_STATISTICS et AUTO_UPDATE_STATISTICS pour chaque base de données utilisateur. Vous pouvez également mettre à jour manuellement les statistiques sur une table ou une vue en utilisant l'instruction UPDATE STATISTICS.

  • Évaluez la requête pour des éléments qui peuvent engendrer des estimations de cardinalité ou de coût médiocres et supprimez ces éléments si possible. Par exemple, remplacez des variables locales par des paramètres ou des littéraux et limitez l'utilisation de fonctions table à plusieurs instructions et de variables de table dans la requête. Pour plus d'informations sur les autres éléments à rechercher, consultez Statistiques utilisées par l'optimiseur de requête dans Microsoft SQL Server 2005.

  • N'utilisez pas inutilement l'indicateur INDEX en association avec FORCESEEK. Autrement dit, si FORCESEEK seul produit un plan suffisant, le fait d'utiliser également l'indicateur INDEX peut limiter excessivement les choix dont dispose l'optimiseur. En outre, un indicateur INDEX provoque l'échec de la requête si vous modifiez le schéma physique de la table pour éliminer l'index spécifié dans l'indicateur. En revanche, tant qu'il existe au moins un index utilisable sur la table sur laquelle l'indicateur FORCESEEK est appliqué, la requête est compilée même si vous modifiez les structures d'index.

  • N'utilisez pas l'indicateur INDEX (0) avec l'indicateur FORCESEEK. L'indicateur INDEX (0) force une analyse de la table de base. Lorsqu'il est associé à FORCESEEK, aucun plan n'est trouvé et l'erreur 8622 est retournée.

  • N'utilisez pas l'indicateur de requête USE PLAN avec l'indicateur FORCESEEK. Si vous le faites, l'indicateur FORCESEEK est ignoré.