インデックス付きビューの DBCC エラーに関するトラブルシューティング

DBCC CHECKDB と DBCC CHECKTABLE を使用して、ベース テーブルのビューを計算して求めた行と同じ行が、インデックス付きビューに含まれているかどうかを確認できます。DBCC を使用したときに、保存されているビューと計算されたビューが異なることを示す 8907 エラーまたは 8908 エラーが返される場合、問題を解決するには次に示す項目について検討してください。

ビュー定義にヒントが含まれているかどうか

SQL Server 2000 では、NOLOCK などのテーブル ヒントを含むインデックス付きビューを作成できました。テーブル ヒントが含まれていると、そのことが原因でインデックス付きビューが破損する場合があります。ビューにテーブル ヒントが含まれている場合は、そのビューを削除し、ビュー定義を編集してヒントを削除してから、ビューを再作成します。その後、ビューのインデックスを再作成します。

インデックス付きビューで float 型または real 型の値に SUM 集計が計算されているかどうか

これに該当する場合は、インデックス付きビューと計算されたビューで異なるのが集計列だけなのか、また、対応する保存されている行と計算された行の差が小さいかどうかを確認します。データとアプリケーションについて検討したうえで、それほど大きな違いではない場合、修正措置は不要です。

違いが重大な場合は、ビューのインデックスを削除し、インデックスを再作成します。このような場合のビューの破損は、浮動小数点演算が持つ概数の性質が原因です。状況によっては、インデックス付きビューのメンテナンス中に追加する数値の順序は、最終結果にあまり影響を与えません。データ型の概数を使用する方法の詳細については、「小数型データ、浮動小数型データ、および実数型データの使用」を参照してください。アプリケーションで浮動小数点型を使用していても、固定小数点型 (numericmoney、または 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 値が異なるのは 1 グループだけであり、その違い sum_b_diff は非常に小さいことが示されます。

参照

概念

インデックス付きビューのデザイン
インデックス付きビューの作成

その他の技術情報

DBCC CHECKDB (Transact-SQL)
DBCC CHECKTABLE (Transact-SQL)
クエリに関するトラブルシューティング

ヘルプおよび情報

SQL Server 2005 の参考資料の入手