Como os grandes campos INCLUDE do índice afetam o desempenho do sistema?

15

Esta pergunta é sobre o desempenho do índice do SQL Server com a varchar(2000)como INCLUDEem um índice de cobertura.

Estou tentando melhorar o desempenho em um aplicativo de banco de dados lento e instável. Em alguns casos, os dados são acessados através de grandes cadeias de varchar, com as consultas, incluindo operações de cadeia multple como SUBSTRING(), SPACE(), e DATALENGTH(). Aqui está um exemplo simplificado de acesso;

update fattable set col3 =  
   SUBSTRING(col3,1,10) + '*' + 
   SUBSTRING(col3,12,DATALENGTH(col3)-12)
from fattable where substring(col3,10,1) = 'A' and col2 = 2

O esquema fica assim:

CREATE TABLE [dbo].[FatTable]( 
    [id] [bigint] IDENTITY(1,1) NOT NULL, 
    [col1] [nchar](12) NOT NULL, 
    [col2] [int] NOT NULL, 
    [col3] [varchar](2000) NOT NULL, ... 

O índice a seguir foi definido, com um campo de cobertura na coluna de texto grande.

CREATE NONCLUSTERED INDEX [IndexCol2Col3] ON [dbo].[FatTable]  ( [col2] ASC ) 
    INCLUDE( [col3] )

Pelo que li, é ruim colocar grandes campos de dados em um índice. Eu tenho lido vários artigos, incluindo http://msdn.microsoft.com/en-us/library/ms190806.aspx, que discutem o impacto da paginação e do tamanho do disco no desempenho do índice. Dito isto, o plano de consulta definitivamente usa o índice de cobertura. Não tenho informações suficientes para determinar quanto isso realmente está me custando em termos de carga do sistema. Sei que, no geral, o sistema está com um desempenho ruim e estou preocupado que esse seja um dos problemas. Questões:

  • Colocar essa varchar(2000)coluna no índice é INCLUDEsempre uma boa idéia?

  • Como os INCLUDEcampos são armazenados em nós folha, eles têm muito desempenho no índice de impacto?

Atualização: Obrigado pelas excelentes respostas! Essa é uma pergunta injusta, de certa forma - como vocês dizem, não há resposta certa absoluta sem estatísticas e perfis reais. Como tantos problemas de desempenho, acho que a resposta é "depende".

RaoulRubin
fonte
Quanto tempo são os valores reais? Uma VARCHAR(2000)que normalmente armazena apenas dez caracteres é uma coisa; 2.000 bytes sólidos por registro é outra coisa.
Jon de Todos os Negócios
Apenas uma observação: algo que "cheira" aqui é que a coluna grande pode conter 1) texto livre; nesse caso, as consultas podem se beneficiar de reescritas para usar um índice FULLTEXT ou 2) dados codificados "legíveis por humanos" (por exemplo, caracteres largamente inteligentes). chaves, como um VIN) que poderiam se beneficiar da divisão em colunas separadas ou colunas calculadas persistentes com INDEXes. Em outras palavras, o fluxo de inteligência e alterações de dados não é bem projetado.
Graeme
11
Sim #Graeme, há um cheiro ruim aqui - acho que é chamado de "legado". Existem muitos problemas nesses bancos de dados.
RaoulRubin

Respostas:

14

Ever é uma palavra grande, mas, em geral, não, eu não colocaria um campo varchar (2000) em um INCLUDE.

E sim, a maneira como os dados são armazenados no nível da página pode afetar seriamente o desempenho do índice, dependendo de como o índice é usado.

O problema é que, quanto mais linhas de dados você puder agrupar em uma página, menos páginas precisarão ser acessadas, mais rápido será o seu sistema, na maior parte. Adicionar uma coluna realmente grande significa menos informações armazenadas em uma página; portanto, no caso de buscas ou varreduras no intervalo, mais páginas precisam ser lidas para recuperar os dados, reduzindo a velocidade das coisas.

Para saber com certeza se esse é um problema na sua consulta ou no seu sistema, você precisa monitorar as leituras, especialmente o número de páginas que a consulta usa.

Grant Fritchey
fonte
Obrigado Grant. Como mencionei outro comentário, as informações de bom desempenho são escassas, daí a questão abstrata. Não tenho experiência em monitorar os custos de desempenho do tamanho da página. Meu palpite é que é um problema, vou ver se consigo algumas estatísticas.
RaoulRubin
11
definir estatísticas IO ativadas para a consulta informará muito, leituras lógicas representam o número de páginas acessadas. Você também pode monitorar segundos / ler nos contadores perfmon para obter informações gerais sobre desempenho.
Grant Fritchey
6

Você pode revisar a chave de índice em cluster atual e, talvez, criar col2a chave de índice em cluster? Dessa forma, você obtém o comportamento de 'incluir' de cobertura (já que os índices agrupados são sempre 'incluindo' tudo) sem duplicar os dados. Isso, é claro, está sujeito a muitos ife but, no entanto, talvez valha a pena considerar. Obviamente, se o índice clusterizado atual estiver aplicando uma restrição (chave primária, exclusiva), a restrição deverá ser movida para um índice não clusterizado.

Remus Rusanu
fonte
Sua sugestão sobre a PK é uma ótima idéia, embora não seja possível aplicá-la neste caso - a PK existente é necessária para outras consultas. (Esta é uma técnica que irá manter na caixa de ferramentas!)
RaoulRubin
4

É difícil responder. Tudo dependerá da sua taxa de leitura: gravação. Você testou uma carga de trabalho ou simulou um ciclo de negócios inteiro em um sistema de teste, com e sem a coluna incluída? A pesquisa sem ele pode custar muito, mas se você estiver atualizando os dados com mais frequência do que os lendo, isso pode ser bom.

Aaron Bertrand
fonte
Leitura geral vs atualização é principalmente equilibrada. Questões organizacionais e de privacidade dificultam a obtenção de estatísticas úteis e testes realistas. Já que estamos voando principalmente às cegas, temos que olhar as coisas de um ponto de vista abstrato (daí esta questão). Testar significará mudanças na produção e observação dos resultados - muito arriscado.
RaoulRubin
2
E a maioria das leituras realmente puxa essa VARCHAR(2000)coluna ou você está solucionando problemas de desempenho de uma consulta muito específica que não representa a maioria das consultas? Como Grant sugere, se essa coluna não for usada em muitas consultas ou realmente causar problemas nas buscas, provavelmente será melhor pagar o preço pela pesquisa quando você precisar, mas não pagar pelo armazenamento quando não precisar. . Novamente, é realmente difícil dizer em que lado da cerca você deve estar, já que realmente não temos detalhes específicos (e ainda mais difícil porque você não pode testar - você deve se esforçar para consertar isso).
Aaron Bertrand
3

Sei que estou atrasado para esta festa, mas indexaria exatamente as expressões usadas para localizar linhas, como substring (col3,10,1). Se todo o col3 for usado, eu indexaria CHECKSUM (col3) (entendendo que pode haver colisões, é claro).

AK
fonte