Em uma pergunta anterior, é uma boa idéia desativar a escalação de bloqueios enquanto adiciona novas colunas calculadas a uma tabela? , Estou criando uma coluna computada:
ALTER TABLE dbo.tblBGiftVoucherItem
ADD isUsGift AS CAST
(
ISNULL(
CASE WHEN sintMarketID = 2
AND strType = 'CARD'
AND strTier1 LIKE 'GG%'
THEN 1
ELSE 0
END
, 0)
AS BIT
) PERSISTED;
A coluna calculada é PERSISTED
e, de acordo com a computed_column_definition (Transact-SQL) :
PERSISTIDO
Especifica que o Mecanismo de Banco de Dados armazenará fisicamente os valores calculados na tabela e atualizará os valores quando quaisquer outras colunas das quais a coluna calculada depende forem atualizadas. Marcar uma coluna computada como PERSISTED permite que um índice seja criado em uma coluna calculada que é determinística, mas não precisa. Para mais informações, consulte Índices em colunas computadas. Quaisquer colunas computadas usadas como colunas de particionamento de uma tabela particionada devem ser explicitamente marcadas como PERSISTED. computed_column_expression deve ser determinístico quando PERSISTED for especificado.
Mas quando tento criar um índice na minha coluna, recebo o seguinte erro:
CREATE INDEX FIX_tblBGiftVoucherItem_incl
ON dbo.tblBGiftVoucherItem (strItemNo)
INCLUDE (strTier3)
WHERE isUsGift = 1;
O índice filtrado 'FIX_tblBGiftVoucherItem_incl' não pode ser criado na tabela 'dbo.tblBGiftVoucherItem' porque a coluna 'isUsGift' na expressão de filtro é uma coluna calculada. Reescreva a expressão de filtro para que ela não inclua esta coluna.
Como posso criar um índice filtrado em uma coluna computada?
ou
Existe uma solução alternativa?
fonte
WHERE (sintMarketID = 2 AND strType = 'CARD' AND strTier1 LIKE 'GG%')
entanto.Respostas:
Infelizmente, no SQL Server 2014, não há capacidade de criar um
Filtered Index
local em que o filtro esteja em uma coluna computada (independentemente de sua persistência ou não).Há um item do Connect aberto desde 2009, então vá em frente e vote nele. Talvez a Microsoft conserte isso um dia.
Aaron Bertrand tem um artigo que cobre uma série de outras questões com índices filtrados .
fonte
Embora você não possa criar um índice filtrado em uma coluna persistente, há uma solução bastante simples que você pode usar.
Como teste, criei uma tabela simples com uma
IDENTITY
coluna e uma coluna computada persistente com base na coluna de identidade:Em seguida, criei uma exibição vinculada ao esquema com base na tabela com um filtro na coluna computada:
Em seguida, criei um índice em cluster na visualização ligada ao esquema, que tem o efeito de persistir os valores armazenados na visualização, incluindo o valor da coluna computada:
Insira alguns dados de teste na tabela:
Crie um item de estatística e um índice na exibição:
A execução de
SELECT
instruções na tabela com a coluna persistente agora pode usar automaticamente a exibição persistida, se o otimizador de consultas determinar que faz sentido fazer isso:O plano de execução real da consulta acima mostra que o otimizador de consulta optou por usar a exibição persistente para retornar os resultados:
Você deve ter notado a conversão explícita na
WHERE
cláusula acima. Esse explícitoCONVERT(INT, 26)
permite que o otimizador de consulta use corretamente o objeto de estatísticas para estimar o número de linhas que serão retornadas pela consulta. Se escrevermos a consulta comWHERE pv.TestComputedColumn = 26
, o otimizador de consulta poderá não estimar adequadamente o número de linhas, pois 26 é realmente considerado umTINY INT
; isso pode fazer com que o SQL Server não use a exibição persistente. Conversões implícitas podem ser muito dolorosas e vale a pena usar de maneira consistente os tipos de dados corretos para comparações e junções.Obviamente, todas as "pegadinhas" padrão resultantes do uso de ligação de esquema se aplicam ao cenário acima; isso pode impedir o uso dessa solução alternativa em todos os cenários. Por exemplo, não será mais possível modificar a tabela base sem primeiro remover a ligação do esquema da visualização. Para fazer isso, você precisará remover o índice clusterizado da exibição.
Se você não possui o SQL Server Enterprise Edition, o otimizador de consulta não usará automaticamente a exibição persistente para consultas que não fazem referência direta à exibição usando a
WITH (NOEXPAND)
dica. Para obter o benefício de usar a exibição persistente em versões que não são da Enterprise Edition, será necessário reescrever a consulta acima para algo como:Agradecemos a Ian Ringrose por apontar a limitação da Enterprise Edition acima e a Paul White pela
(NOEXPAND)
dica.Esta resposta de Paul tem alguns detalhes interessantes sobre o otimizador de consultas em relação às visualizações persistentes.
fonte
TestComputedColumn
alternativa. No entanto, como o índice em cluster contém todos os dados da tabela / exibição, decidi que seria melhor usar um número monotonicamente crescente como a chave de cluster. Observe, na verdade, eu não testei essa suposição e, de fato, pode estar incorreta para algumas variações da reprodução.De
Create Index
e suawhere
cláusula, isso não é possível:Fonte: MSDN
fonte
Antes de calcularmos as colunas, usamos gatilhos para calcular o valor das colunas sempre que a linha era alterada ou inserida.
(Um gatilho também pode ser usado para inserir / remover a PK do item de uma segunda tabela que foi usada nas consultas.)
fonte
Esta é uma tentativa de melhorar o trabalho de Max Vernon . Em sua solução, ele sugere usar 2 índices na exibição e um objeto de estatística.
O 1º índice é agrupado, o que é realmente necessário, pois, diferentemente de um índice não clusterizado em uma tabela, um erro será gerado se a criação de um índice não clusterizado na exibição for tentada sem primeiro ter um índice clusterizado.
O segundo índice é um índice não clusterizado, usado como o índice por trás da consulta. Na seção de comentários de sua resposta, perguntei o que aconteceria se um índice clusterizado fosse usado em vez de um índice não clusterizado.
A análise a seguir tenta responder a essa pergunta.
Estou usando exatamente o mesmo código, exceto que não estou criando um índice não clusterizado na exibição.
Também não estou criando um objeto de estatística. Se estiver acompanhando e usando o SSMS (SQL Server Management Studio) para inserir o código abaixo, você deve estar ciente de que poderá ver algumas linhas onduladas vermelhas - que parecem erros. Estes (provavelmente) não são erros, mas envolvem um problema com o intellisense.
Você pode desativar o intellisense ou simplesmente ignorar os erros e executar os comandos. Eles devem ser concluídos sem erros.
O seguinte plano de execução (sem exibição / exibição de índice) é produzido depois que a seguinte consulta é executada na tabela:
Isso fornece uma linha de base para comparação. Observe que, após a consulta concluída, um objeto estatístico foi criado (_WA_Sys_00000003_1FCDBCEB). O objeto de estatísticas PK_PersistedViewTest foi criado quando o índice da tabela em cluster foi criado.
Em seguida, a visualização filtrada e o índice clusterizado nessa visualização são criados:
Agora, vamos tentar executar a consulta novamente, mas desta vez na visualização:
O novo plano de execução é agora:
Se o novo plano deve ser acreditado, após a adição da visualização e do índice clusterizado nessa visualização, as estatísticas parecem indicar que o tempo necessário para executar a consulta agora dobrou. Além disso, observe que nenhum novo objeto de estatística foi criado para oferecer suporte ao novo índice após a execução da consulta, que é diferente da consulta na tabela.
O plano de consulta ainda sugere que a criação de um índice não clusterizado seria bastante útil para melhorar o desempenho da consulta. Então, isso significa que um índice não clusterizado deve ser adicionado à visualização antes que a melhoria de desempenho desejada possa ser obtida? Há uma última coisa a tentar. Modifique a consulta para usar a opção "WITH NOEXPAND":
Isso resulta no seguinte plano de consulta:
Esse plano de execução é bastante semelhante ao produzido com o índice não clusterizado, fornecido na resposta de Max Vernon. Mas, este é feito com um índice a menos (não clusterizado) e um objeto a menos de estatística.
Acontece que a opção NOEXPAND deve ser usada com as versões expressa e padrão do SQL Server para fazer uso adequado de uma exibição indexada. Paul White tem um excelente artigo que expõe os benefícios do uso da opção NOEXPAND. Ele também recomenda que essa opção seja usada com a edição corporativa para garantir que a garantia de exclusividade fornecida pelos índices de exibição seja usada pelo otimizador.
A análise acima foi feita com a edição expressa do SQL Sever 2014. Também tentei com a edição do desenvolvedor do SQL Server 2016. A opção NOEXPAND não parece ser necessária com a edição de desenvolvimento para obter ganhos de desempenho, mas ainda é recomendada .
Há menos de 5 meses, a Microsoft disponibilizou as edições do desenvolvedor . A licença restringe o uso apenas ao desenvolvimento, o que significa que o banco de dados não pode ser usado em um ambiente de produção. Portanto, se você estiver procurando testar tabelas, criptografia, R etc. otimizadas para memória, não terá mais a desculpa da ausência de licença. Eu o instalei com sucesso no meu computador há alguns dias, ao lado do SQL Server 2014 Express, sem problemas.
fonte