Problembehandlung von DBCC-Fehlern in indizierten Sichten

Sie können DBCC CHECKDB und DBCC CHECKTABLE verwenden, wenn Sie untersuchen möchten, ob eine indizierte Sicht die gleichen Zeilen enthält, die beim Berechnen der Sicht aus den Basistabellen gefunden werden. Wenn DBCC den Fehler 8907 oder 8908 zurückgibt, der besagt, dass die gespeicherte Sicht nicht identisch mit der berechneten Sicht ist, untersuchen Sie Folgendes, um das Problem zu beheben.

Enthält Ihre Sichtdefinition Hinweise?

In SQL Server 2000 können Sie indizierte Sichten erstellen, die Tabellenhinweise wie z. B. NOLOCK enthalten. Gelegentlich kann dies zu einer Beschädigung der indizierten Sicht führen. Wenn Ihre Sicht Tabellenhinweise enthält, löschen Sie die Sicht, bearbeiten ihre Definition, um solche Hinweise zu entfernen, und erstellen die Sicht dann neu. Erstellen Sie anschließend den Index für die Sicht neu.

Berechnet die indizierte Sicht eine SUM-Aggregatfunktion für alle Werte vom Typ float oder real?

Wenn dies der Fall ist, bestehen die einzigen Unterschiede zwischen der indizierten Sicht und der berechneten Sicht in der Aggregatfunktionsspalte, und sind die Unterschiede für die entsprechenden gespeicherten und berechneten Zeilen nur gering? Wenn die Unterschiede in Anbetracht Ihrer Daten und der Anwendung nicht erheblich sind, sind keine korrigierenden Maßnahmen erforderlich.

Sollten die Unterschiede erheblich sein, löschen Sie den Index für die Sicht und erstellen ihn dann neu. Die Beschädigung liegt in diesem Fall möglicherweise vor, weil Gleitkommazahlen ungefähre Werte zur Verfügung stellen. Die Reihenfolge, in der die Zahlen während der Wartung indizierter Sichten hinzugefügt werden, kann manchmal Auswirkungen auf das Endergebnis besitzen, die im Allgemeinen nur geringfügig sind. Weitere Informationen zum Verwenden von ungefähren Datentypen finden Sie unter Verwenden von decimal-, float- und real-Daten. Wenn Ihre Anwendung Gleitkomma-Datentypen verwendet, Ihre Anforderung jedoch durch die Verwendung eines genauen Dezimaldatentyps (numeric, money oder decimal) erfüllt werden kann, ziehen Sie die Verwendung von numeric in einer überarbeiteten Version der indizierten Sicht in Erwägung.

Wenn die indizierte Sicht keine Aggregatfunktion zu Werten des Typs float oder real enthält und Sie den Fehler 8907 bzw. 8708 erhalten, löschen Sie den Index der Sicht und erstellen ihn dann neu.

Verwenden Sie nicht ALTER INDEX REBUILD für den Versuch, die Unterschiede zwischen der gespeicherten und der berechneten Sicht zu entfernen, weil ALTER INDEX REBUILD die Sicht nicht neu berechnet, bevor der Index neu erstellt wird.

Nachdem der Index für die Sicht neu erstellt wurde, führen Sie DBCC CHECKTABLE für die Sicht aus, um sicherzustellen, dass keine Unterschiede verblieben sind. Wenn noch Unterschiede vorhanden sind, ziehen Sie Hardware- oder andere Probleme als mögliche Ursachen in Betracht.

Wie kann ich ermitteln, ob die Unterschiede zwischen den indizierten und berechneten Sichten erheblich sind?

Wenn die Unterschiede zwischen Ihren indizierten und berechneten Sichten nicht nur kleine Abweichungen in einer SUM-Aggregatfunktion eines float- oder real -Werts sind, sind die Unterschiede wahrscheinlich erheblich. Löschen Sie in diesen Fällen den Index für die Sicht, und erstellen Sie ihn dann neu. Wenn in Sichten nur Unterschiede in einer SUM-Funktion für float- oder real-Werte auftreten und die Sicht klein ist, vergleichen Sie die indizierte und berechnete Sicht visuell miteinander. Entscheiden Sie dann, ob die Unterschiede erheblich sind. Für eine ViewName-Sicht rufen Sie die berechneten und gespeicherten Werte wie folgt ab:

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

Es kann hilfreich sein, den absoluten oder Prozentsatzunterschied für ungleiche Zeilen für die gleiche Gruppe in einer Aggregatsicht zu untersuchen, wenn Sie ermitteln möchten, ob die Unterschiede erheblich sind. Das folgende Skript zeigt z. B. die Vorgehensweise beim Vergleichen einer indizierten und einer berechneten Sicht, die sich geringfügig unterscheiden. Das Skript zeigt Zeilenpaare für die gleiche Gruppe an, die unterschiedliche gespeicherte und berechnete Summen aufweisen.

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

Das Ergebnis zeigt, dass nur eine Gruppe einen anderen SUM-Wert aufweist und dass der Unterschied sum_b_diff sehr klein ist.