Como melhorar o desempenho na tabela SQL Server com campos de imagem?
-
20-09-2019 - |
Pergunta
Estou tendo um problema de desempenho muito particular no trabalho!
No sistema que estamos usando, há uma tabela que contém informações sobre o processo atual de fluxo de trabalho. Um dos campos segura uma planilha que contém metadados sobre o processo (não me pergunte por que !! e não, eu não posso mudar !!)
O problema é que essa planilha é armazenada em um campo de imagem em um SQL Server 2005 (dentro de um banco de dados definido com compatibilidade SQL 2000).
Atualmente, esta tabela possui linhas de 22k+ e até mesmo uma consulta simples como esta:
SELECT TOP 100 *
FROM OFFENDING_TABLE
Leva 30 segundos para recuperar os dados no analisador de consultas.
Estou pensando em atualizar a compatibilidade com o SQL 2005 (uma vez que fui informado de que o aplicativo pode lidar com isso).
A segunda coisa que estou pensando é mudar o tipo de dados da coluna para varbinary(max)
Mas não sei se isso afetará o aplicativo.
Outra coisa que estou considerando é usar sp_tableoption
Para definir o large value types out of row
para 1
Como é atualmente 0
, mas não tenho informações se isso melhorará o desempenho.
Alguém sabe como melhorar o desempenho em esse cenário?
Editado para esclarecer
Meu problema é que não tenho controle sobre o que o aplicativo pede ao servidor SQL e fiz alguma reflexão sobre ele (o aplicativo é um site .NET 1.1) e ele usa o campo ofensivo para algumas coisas internas que eu não tenho ideia o que é isso.
Preciso melhorar o desempenho geral desta tabela.
Solução
Eu recomendo que você veja a saúde do layout da mesa ofensiva:
select * from sys.dm_db_index_physical_stats(
db_id(), object_id('offending_table'), null, null, detailed);
As coisas também procuram. Dicas como alta fragmentação, ou um alto número de registros fantasmas, ou uma página baixa usada, indicam problemas e as coisas podem ser melhoradas um pouco apenas reconstruindo o índice (ou seja, a tabela) do zero:
ALTER INDEX ALL ON offending_table REBUILD;
Estou dizendo isso, considerando que você não pode alterar a tabela nem o aplicativo. Se você puder alterar a tabela e o aplicativo, o conselho que você já recebeu é um bom conselho (não use '*', não 'selecione W/OA Condition, use o tipo varbinário mais recente (max) etc etc) .
Eu também examinaria a vida útil média da página em contadores de desempenho para entender se o sistema está faminto pela memória. A partir da sua descrição dos sintomáticos, o sistema parece encadernado, o que me leva a pensar que há pouco cache de páginas acontecendo, e mais RAM pode ajudar, além de um subsistema mais rápido de IO. Em um sistema SQL 2008, eu também sugeriria ativar a compactação da página, mas em 2005 você não pode.
E, apenas para ter certeza, verifique se as consultas não estão bloqueadas pela disputa do próprio aplicativo, ou seja. A consulta não gasta 90% desses 30 segundos aguardando uma trava de linha. Olhe para sys.dm_exec_requests Enquanto a consulta estiver em execução, consulte Wait_time, Wait_Type e Wait_Resource. É Pageiolatch_xx? Ou é uma fechadura? Além disso, como está o sys.dm_os_wait_stats No seu servidor, quais são os principais motivos de espera?
Outras dicas
Em primeiro lugar - Nunca faça um SELECT *
no código de produção - relatórios ou não.
Você tem três opções básicas:
Mova esse campo de blob para uma tabela separada, se nem sempre for necessária; Provavelmente não é prático, pois você menciona que não pode mudar o esquema
tenha mais cuidado com o seu
SELECT
Declarações para selecionar apenas os campos que você realmente precisa - e omitir o campo BLOBVeja se você pode limitar sua consulta para incluir um
WHERE
Cláusula e encontre uma maneira de otimizar o plano de consulta, por exemplo, adicionando um índice adequado à tabela (se puder)
Não há switch "Make This Faster That mais rápido" - mas você pode otimizar sua consulta ou otimizar o layout da tabela. Ambos ajudam. Se você não pode mudar nada - nem o layout da tabela, nem adicionar um índice, nem alterar as consultas, você terá dificuldade em otimizar qualquer coisa, tenho medo ....
Apenas alterar o campo para varbinário (Max) não mudará nada - nenhuma melhoria de desempenho é esperada apenas da alteração do tipo de dados.
Uma resposta curta é fazer apenas selecionar em várias linhas quando os campos retornados não incluem o campo de imagem ofensiva, ou seja, não seleção *. Se você deseja o valor do campo da imagem, recupere-o caso a caso.
Definir os grandes tipos de valor fora da opção de linha deve definitivamente ajudar o desempenho. O tamanho da linha será significativamente menor, o SQL Server pode fazer muito menos leituras físicas para passar pela tabela.