Диагностика ошибок DBCC на индексированных представлениях

DBCC: проверка индексированного представления на наличие строк, извлекаемых при вычислении представления базовой таблицы, выполняется с помощью инструкций CHECKDB и DBCC CHECKTABLE. Если DBCC возвращает ошибки 8907 или 8908 (хранимое представление отличается от вычисляемого), для решения проблемы рассмотрите следующие вопросы.

Содержит ли определение представления какие-либо подсказки?

В SQL Server 2000 можно создавать индексированные представления, содержащие табличные подсказки (например, NOLOCK). В некоторых случаях это может привести к повреждению индексированного представления. Если представление содержит табличные подсказки, то его необходимо очистить, удалить из его определения подсказки, а затем создать повторно. Затем необходимо создать повторно индекс представления.

Производятся ли в индексированном представлении вычисления статистических функций SUM с аргументами, имеющими тип float или real?

Если подобные вычисления производятся, то необходимо выяснить, является ли столбец вычисленных статистических данных единственным различием между индексированным и вычисленным представлениями, а также насколько велико данное различие. Если различия незначительны, то данные и приложение не нужно подвергать исправлению.

Если различия существенны, то необходимо очистить индекс представления и создать его повторно. В данном случае повреждение может являться следствием приблизительности вычислений с плавающей точкой. Порядок, в котором значения добавляются к индексированному представлению, часто слабо влияет на результат. Дополнительные сведения об использовании неточных типов данных см. в разделе Использование типов данных decimal, float и real. Если в приложении используются типы данных с плавающей запятой и при этом аналогичные требования могут быть выполнены с использованием точных десятичных типов (numeric, money или decimal), то после обновления индексированного представления рекомендуется использовать тип numeric.

Если индексированное представление не содержит статистических вычислений со значениями типа float или real, но выдается ошибка 8907 или 8708, необходимо очистить индекс представления и создать его повторно.

Не следует использовать инструкцию ALTER INDEX REBUILD для устранения различий между хранимым и вычисленным представлениями, так как при его использовании с целью перестройки индекса пересчет представления не производится.

После повторного создания индекса представления выполните инструкцию DBCC CHECKTABLE и убедитесь в том, что различий не осталось. В случае если остались какие-либо различия, необходимо искать неполадку в оборудовании.

Инструкции по методам, позволяющим определить степень различия между индексированным и вычисляемым представлениями

Для индексированного и вычисляемого представлений допускаются небольшие различия между статистическими выражениями SUM, имеющими тип float или real . Все другие различия, вероятнее всего, являются значительными. В таких случаях необходимо очистить индекс представления и создать его повторно. Если различие между представлениями имеется только в выражениях SUM с данными типа float или real и при этом представление имеет небольшие размеры, то следует оценить различия визуально и определить, являются ли они значительными. Для представления 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 очень мала.