Solucionando problemas de erros de DBCC em exibições indexadas

Você pode usar DBCC CHECKDB e DBCC CHECKTABLE para consultar se uma exibição indexada contém as mesmas linhas que são achadas ao computar a exibição das tabelas base. Se DBCC retornar erros 8907 ou 8908, que indicarão que a exibição armazenada não é idêntica à exibição computada, considere os seguintes para resolver o assunto.

Sua definição de exibição contém dicas?

Em SQL Server 2000, você pode criar exibições indexadas que contêm dicas de tabela como NOLOCK. Às vezes, isto pode conduzir à corrupção da exibição indexada. Se sua exibição contiver dicas de tabela, derrube a exibição, edite sua definição para remover tais dicas e recrie-a. Então, recrie o índice na exibição.

A exibição indexada computa um agregado de SUM em cima de valores de tipo float ou real?

Nesse caso, as únicas diferenças estão entre a exibição indexada e exibição computada na coluna agregada? e as diferenças são pequenas para linhas correspondentes armazenadas e computadas? Se elas não forem significativas, considerando seus dados e aplicativo, nenhuma ação corretiva será solicitada.

Se as diferenças forem significativas, derrube o índice da exibição e recrie-o. A corrupção neste caso provavelmente acontece pela natureza aproximada da aritmética de ponto flutuante. A ordem em que os números são somados durante a manutenção da exibição indexada às vezes pode ter um efeito geralmente pequeno no resultado final. Para obter mais informações sobre como usar tipos de dados aproximados, consulte Usando dados decimais, flutuantes e reais. Se seu aplicativo usar tipos de ponto flutuante, mas seus requisitos poderão ser atendidos usando um tipo decimal exato (numeric, moneyou decimal), então considere usar numeric em uma versão revisada de sua exibição indexada.

Se a exibição indexada não contiver um agregado em cima de valores do tipo float ou real e você receber erros 8907 ou 8708, derrube o índice na exibição e recrie-o.

Não use ALTER INDEX REBUILD para tentar remover as diferenças entre as exibições computada e armazenada, porque ALTER INDEX REBUILD não recalcula a exibição antes de reconstruir o índice.

Depois de recriar o índice na exibição, execute DBCC CHECKTABLE na exibição para verificar se não permaneceram diferenças. Se diferenças permanecerem, considere o hardware ou outros problemas como uma possível causa.

Como eu determino se as diferenças entre as exibições indexadas e computadas são significativas?

Se as diferenças entre sua exibição indexada e exibição computada são mais que diferenças pequenas em um agregado de SUM de um valor float ou real , as diferenças são provavelmente significativas. Nesses casos, você deveria derrubar e recriar o índice na exibição. Se houver uma diferença entre exibições apenas em um SUM em float ou valor real e a exibição for pequena, compare visualmente as exibições indexadas e calculadas e decida se as diferenças são significativas. Para uma exibição ViewName, obtenha os valores calculados e armazenados como se segue:

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

Você pode achar útil examinar a diferença absoluta ou percentual para linhas desiguais para o mesmo grupo em uma exibição agregada para ajudar a determinar se as diferenças são significativas. Por exemplo, o script seguinte mostra como comparar uma exibição indexada e uma exibição computada que diferem ligeiramente. O script exibe pares de linhas para o mesmo grupo que têm somas armazenadas e calculadas diferentes.

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

O resultado mostra que só um grupo tem um valor SUM diferente, e que a sum_b_diff de diferença é muito pequena.