Résolution des erreurs DBCC dans les vues indexées

Vous pouvez utiliser DBCC CHECKDB et DBCC CHECKTABLE pour voir si une vue indexée contient les mêmes lignes que celles qui sont détectées lors du calcul de la vue à partir des tables de base. Si DBCC renvoie les erreurs 8907 ou 8908 indiquant que la vue stockée n'est pas identique à la vue calculée, utilisez les quelques pistes suivantes pour les résoudre.

Votre définition de vue contient-elle des indicateurs ?

Dans SQL Server 2000, vous pouvez créer des vues indexées qui contiennent des indicateurs de table tels que NOLOCK. Dans certains cas, ceci peut provoquer leur corruption. Si votre vue contient des indicateurs de table, supprimez-la, modifiez sa définition en supprimant les indicateurs et recréez-la. Ensuite, recréez l'index sur la vue.

Votre vue indexée calcule-t-elle un agrégat SUM sur la base des valeurs de type float ou real ?

Si oui, les différences entre la vue indexée et la vue calculée se trouvent-elles uniquement dans la colonne agrégée ? Ces différences sont-elles minimes pour les lignes stockées et calculées correspondantes ? Si les différences sont minimes, examinez vos données et votre application. Aucune action corrective n'est requise.

Si les différences sont importantes, supprimez l'index sur la vue et recréez-le. La corruption est sans doute due à la nature trop approximative de l'arithmétique avec virgule flottante. L'ordre dans lequel les numéros sont ajoutés pendant la maintenance de la vue indexée peut parfois influencer, bien que de manière limitée, le résultat final. Pour plus d'informations sur l'utilisation de types de données approximatifs, consultez Utilisation des types de données decimal, float et real. Si votre application utilise des types de données avec virgule flottante, mais que vos besoins peuvent être couverts par l'utilisation de données décimales exactes (types numeric, money ou decimal), envisagez de les remplacer par des données de type numeric dans une version corrigée de votre vue indexée.

Si la vue indexée ne contient pas d'agrégat sur la base des valeurs de types float ou real et que vous obtenez malgré tout les erreurs 8907 ou 8708, supprimez l'index sur la vue et recréez-le.

N'utilisez pas ALTER INDEX REBUILD pour essayer de supprimer ces différences entre la vue stockée et la vue calculée, car cette instruction ne recalcule pas la vue avant de reconstruire l'index.

Après avoir recréé l'index sur la vue, exécutez DBCC CHECKTABLE sur la vue pour vérifier que toutes les différences ont été supprimées. Si ce n'est pas le cas, orientez vos recherches vers un problème matériel ou autre.

Comment savoir si les différences entre la vue indexée et la vue calculée sont importantes ?

Si les différences entre votre vue indexée et votre vue calculée se situent ailleurs que dans l'agrégat SUM d'une valeur de type float ou real , elles sont probablement importantes. Dans ce cas, il vaut mieux supprimer et recréer l'index sur la vue. Si les vues sont petites et ne diffèrent qu'au niveau d'une valeur float ou real dans un agrégat SUM, comparez-les visuellement et décidez vous-même de l'importance des différences. Par exemple, pour une vue ViewName, obtenez les valeurs calculées et stockées comme suit :

SELECT * FROM ViewName OPTION(EXPAND VIEWS) -- Get calculated view.
SELECT * FROM ViewName WITH(NOEXPAND)       -- Get stored view.

Pour déterminer l'importance des différences, il peut être utile d'examiner la différence (absolue ou en %) entre des lignes non identiques du même groupe dans une vue agrégée. Par exemple, le script suivant vous montre comment comparer une vue indexée et une vue calculée légèrement différentes. Il affiche des paires de lignes du même groupe mais dont les sommes calculées et stockées sont différentes.

IF OBJECT_ID('v') IS NOT NULL DROP VIEW v
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
go
CREATE TABLE t
   (id int NOT NULL PRIMARY KEY, 
    a int NOT NULL, 
    b float(53) NOT NULL)
GO
CREATE VIEW v WITH SCHEMABINDING AS
SELECT a, SUM(b) AS sum_b, COUNT_BIG(*) AS c
FROM dbo.t
GROUP BY a
GO
CREATE UNIQUE CLUSTERED INDEX idx ON v(a)
GO
INSERT t VALUES(1, 1,1.0e1)
INSERT t VALUES(2, 1,1.0e2)
INSERT t VALUES(3, 2, 1.0e0)
INSERT t VALUES(4, 2, 5.0e-17)
INSERT t VALUES(5, 2, 5.0e-17)
INSERT t VALUES(6, 2, 5.0e-17)
GO
DELETE FROM t WHERE id=3
GO
DBCC CHECKTABLE ('v')
GO
-- Show the groups that have different SUMs, 
-- and the difference between the sums.
SELECT *, v1.sum_b - v2.sum_b AS sum_b_diff
FROM (SELECT * FROM v WITH (NOEXPAND)) AS v1,
     (SELECT * FROM v) AS v2
WHERE v1.a=v2.a
AND (v1.sum_b - v2.sum_b) <> 0
OPTION(EXPAND VIEWS)
GO

Le résultat indique qu'un seul groupe a une valeur SUM différente et que la différence sum_b_diff est insignifiante.