Pergunta

Estou tentando melhorar o desempenho de uma consulta que está sendo executada muito lentamente.Depois de passar pelo Plano de Execução Real;Eu descobri que um Busca de índice agrupado estava ocupando 82%.Existe alguma maneira de melhorar o desempenho em um Busca de índice?Abaixo está uma imagem do problema Busca de índice do plano de execução, bem como do índice e da tabela que está usando.

texto alternativo http://img340.imageshack.us/img340/1346/seek.png

Índice:

/****** Object:  Index [IX_Stu]    Script Date: 12/28/2009 11:11:43 ******/
CREATE CLUSTERED INDEX [IX_Stu] ON [dbo].[stu] 
(
 [StuKey] ASC
)WITH (PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

Tabela (algumas colunas omitidas por questões de brevidade):

CREATE TABLE [dbo].[stu](
 [StuCertKey] [int] IDENTITY(1,1) NOT NULL,
 [StuKey] [int] NULL
 CONSTRAINT [PK_Stu] PRIMARY KEY NONCLUSTERED 
(
 [StuCertKey] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
Foi útil?

Solução

Estou generalizando aqui, mas ...

Uma busca de índice em cluster é, na maioria das vezes, o melhor cenário. As únicas maneiras pelas quais consigo pensar para melhorar o desempenho seriam:

  • Atualize a consulta para retornar menos linhas/colunas, se possível;
  • Desfragmentação ou reconstrução do índice;
  • Partição do índice em vários discos/servidores.

Se está retornando apenas 138 linhas, e é lento ... talvez esteja sendo bloqueado por algum outro processo? Você está testando isso isoladamente ou outros usuários/processos on -line ao mesmo tempo? Ou talvez seja um problema de hardware, como uma falha de disco.

Outras dicas

As buscas de índice clusterizado ocorrem quando índices não clusterizados são usados ​​e não são necessariamente ruins.

Considere a seguinte consulta:

SELECT s.StuKey, s.Name, s.Address, s.City, s.State FROM stu s WHERE State='TX'

Se houver apenas um índice clusterizado no StuKey, então o Sql Server terá apenas 1 opção, ele deverá varrer a tabela inteira procurando por linhas onde State="TX' e retornar essas linhas.

Se você adicionar um índice não clusterizado em State

CREATE INDEX IX_Stu_State on Stu (State)

Agora o SQL Server tem uma nova opção.Ele pode optar por buscar usando o índice não clusterizado, que produzirá as linhas onde State='TX'.No entanto, para que as colunas restantes retornem no SELECT, ele deve procurar essas colunas fazendo uma busca de índice clusterizado para cada linha.

Se você quiser reduzir as buscas de índice clusterizado, poderá fazer com que seu índice "cobra" incluindo colunas extras nele.

 CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city )

Este índice agora contém todas as colunas necessárias para responder à consulta acima.A consulta fará uma busca de índice para retornar apenas as linhas onde State='TX', e as colunas adicionais podem ser retiradas do índice não clusterizado, para que as buscas de índice clusterizado desapareçam.

Uma linha de índice em cluster busca que retorna 138 linhas não é o seu problema.

Tecnicamente, você pode melhorar o desempenho de busca, tornando o índice em cluster mais estreito:

Ambos podem ter um impacto bastante dramático no tempo de busca de alcance, pois reduzem o IO e a necessidade de atingir leituras físicas. Obviamente, como geralmente, o resultado varia de acordo com um grande número de outros fatores, como quais colunas você projeta (despejando uma coluna projetada na unidade de alocação de blob pode realmente ter efeitos adversos em determinadas consultas). Como nota lateral, geralmente a fragmentação terá apenas um impacto marginal em uma varredura tão curta. Novamente, depende.

Mas, como eu disse, duvido muito que esse seja o seu verdadeiro problema. Você apenas publicou partes selecionadas do plano e os resultados de sua própria análise. A verdadeira causa raiz pode estar completamente em outro lugar.

Pensamentos...

  • Por que o ix_stu está agrupado? Internamente, o SQL Server adiciona um "exclusivo" de 4 bytes a índices clusterados não únicos. Qual é a justificativa? Isso também incha seu PK também

  • Qual é a consulta real que você está executando?

  • Finalmente, por que preencher 80%?

Editar:

  • Um FillFactor "normal" seria 90%, mas esta é uma regra geral

  • Uma consulta de 11 de junção? Esse é provavelmente o seu problema. Quais são suas junções, onde cláusulas etc? Qual é o plano de texto completo?

Alguns conselhos gerais: quando tenho que fazer a otimização de consultas, começo escrevendo o que acho que o plano de execução deveria ser.

Depois de decidir o que acho que o plano de execução deveria ser, tento fazer com que a consulta real se encaixasse nesse plano. As técnicas para fazer isso são diferentes para cada DBMS e não necessariamente transferem de um para o outro, ou mesmo, às vezes, entre diferentes versões dos DBMs.

O problema a ter em mente é que o DBMS só pode executar uma união de cada vez: começa com duas tabelas iniciais, junta -se a elas e, em seguida, leva o resultado dessa operação e a une à próxima tabela. A meta em cada etapa é minimizar o número de linhas no conjunto de resultados intermediários (mais corretamente, para minimizar o número de blocos que precisam ser lidos para produzir os resultados intermediários, mas isso geralmente significa menos linhas).

Você já tentou alguma manutenção neste índice? Como desfragê -lo? Parece realmente estranho que custe tanto (120.381). O índice Seek é a operação de índice mais rápida, não deve demorar tanto. Você pode postar a consulta?

O que acontece se você codificar seu codificar seu ONDE Critérios, como este:

SELECT StuCertKey, StuKey FROM stu 
WHERE stuKey in (/* list 50 values of StuKey here */)

Se ainda estiver muito lento, você tem algum tipo de problema interno. Se for mais rápido, o índice não é o seu gargalo, é o Junta -se que você está fazendo para criar o ONDE filtro.

Observe que SELECT * pode ser muito lento se houver muitas colunas grandes, e especialmente se houver bolhas.

Verifique a estatística do índice.

A recalculação das estatísticas do índice clusterada resolverá o problema.

No meu caso, eu estava procurando 30 discos em 40m Recored. O plano de execução diz que está passando pelo índice em cluster, mas levou cerca de 200 ms. E o índice não foi desfragmentado. Depois de recalcular suas estatísticas, está sendo feito com menos de 10ms!

Reconstruir o índice e calcular estatísticas?

A única outra maneira de pensar que acelera é particionar a tabela, o que pode ou não ser possível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top