疑難排解索引檢視的 DBCC 錯誤

您可以使用 DBCC CHECKDB 與 DBCC CHECKTABLE 查看索引檢視是否包含相同的資料列,而這些資料列是透過計算基底資料表的檢視找到的。如果 DBCC 傳回錯誤 8907 或 8908,則表示儲存檢視與計算檢視不一樣,請考慮下列項目以解決該問題。

您的檢視定義是包含提示?

在 SQL Server 2000 中,您可以建立包含 NOLOCK 等資料表提示的索引檢視。在某些情況下,這可能會導致索引檢視損毀。如果檢視中包含資料表提示,請卸除檢視、編輯其定義以移除諸如提示等定義,然後重新建立它。接著,在檢視上重新建立索引。

索引檢視是否會針對浮點數或實數類型的值計算 SUM 彙總?

如果會,這是否為索引檢視與計算檢視在彙總資料行中之間的唯一差異,以及對應的儲存資料列和計算資料列之差異是否很小?如果它們的差異不大,請考慮您的資料和應用程式,不需要進行修正的動作。

如果差異很大,請卸除檢視上的索引,然後重新建立它。在此情況下有可能會因為浮點算術的近似本質而造成損毀。在索引檢視維謢期間加入數字的順序,有時會對最後的結果造成稍微的影響。如需如何使用近似資料類型的詳細資訊,請參閱<使用 decimal、float 與 real 資料>。如果應用程式使用浮點類型,但是您的需求可以使用精確的十進位類型 (numeric、money 或 decimal) 符合,請考慮在索引檢視修訂版本中改用 numeric。

如果索引檢視並未包含 float 或 real 類型值的彙總,而且您收到錯誤 8907 或 8708,請卸除檢視上的索引並重新建立它。

請勿使用 ALTER INDEX REBUILD 來嘗試移除儲存檢視和計算檢視之間的差異,因為 ALTER INDEX REBUILD 不會在重建索引之前先重新計算檢視。

在重新建立檢視上的索引後,請在檢視上執行 DBCC CHECKTABLE,以確認沒有任何的差異。如果仍有差異,請考慮硬體或其他問題為可能的原因。

如何判斷索引檢視和計算檢視之間的差異是否很大?

如果索引檢視和計算檢視之間的差異不只是 float 或 real 值之 SUM 彙總的小差異,則其差異可能很大。在這些情況下,應該卸除和重新建立檢視上的索引。如果檢視之間的差異僅止於 float 或 real 值的 SUM 差異而且檢視很小,請就外觀上比較索引和計算檢視的差異,並決定這些差異是否很大。對於檢視的 ViewName,請依照下列方式取得計算值和儲存值:

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

在彙總檢視的相同群組中觀察不相等的資料列之絕對差異或百分比差異,可能會非常有助益,將可協助您判斷差異是否很大。例如,下列指令碼顯示如何比較索引檢視和計算檢視之間是否有些不同。此指令碼會顯示相同群組中具有不同儲存總合和計算總合的資料列配對。

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

結果顯示只有一個群組有不同的 SUM 值,而且差異 sum_b_diff 非常小。