...
- Desfragmentação Arquivo .DB. Este é um passo que deve ser executado no Sistema operacional, isto é, após uma análise dos fragmentos no arquivo .db, deve-se utilizar um desfragmentador via sistema operacional para diminuir o número de fragmentos do arquivo .db. Para saber quantos fragmentos ele possui, existe uma propriedade do banco chamada DbFileFragments.
Bloco de código SELECT DB_PROPERTY('DBFILEFRAGMENTS');
Nota Alguns desfragmentadores trabalham melhor com arquivos criados do que com espaço livre, isto é, ao executar o desfragmentador antes de se criar o banco, o banco acaba fragmentado desnecessariamente. Assim, a ordem correta é criar o banco e depois desfragmentar o disco rígido.
- Aumentar espaço *DBSPACE antes do banco fazer isso automaticamente*. Pode-se programar uma tarefa noturna que verifique o espaço livre (pages free) do banco e, caso atinja um limite mínimo (por exemplo, 10%), aumente em 20% (por exemplo) o número de páginas livre. É importante fazer isso antes do banco fazer automaticamente pois podemos programar este crescimento num horário fora do pico de uso. Além disso, podemos automatizar a execução da desfragmentação do SO em seguida.
Bloco de código ALTER DBSPACE SYSTEM ADD 100MB;
- Fragmentação Tabelas. Existe uma instrução para se verificar a fragmentação das tabelas dentro do banco.
Bloco de código CALL sa_table_fragments;
Um valor 1,5 no campo Segs_per_Row por exemplo significa que 50% das linhas estão fragmentadas. O número ideal é 1.
Para reorganizar uma tabela desfragmentando-a, existe o comando REORGANIZE TABLE.Bloco de código REORGANIZE TABLE <nome_tabela>;
- Fragmentação Índices. Os índices podem ser reorganizados utilizando-se o mesmo comando acima (REORGANIZE TABLE) especificando-se o nome do índice. Para saber quais índices podem ser otimizados, utilize o seguinte comando.
O ideal é termos o campo Level igual a 1 ou 2. Pode ocorrer que este campo seja maior que 2 o que pode significar que o índice é grande ou que o mesmo está fragmentado. Utilizando o comando abaixo nos certificamos que o índice foi otimizado (mesmo que o nível não diminua).Bloco de código SELECT * FROM SA_INDEX_LEVELS() ORDER BY SA_INDEX_LEVELS.TABLENAME, SA_INDEX_LEVELS.INDEXNAME;
Bloco de código REORGANIZE TABLE <nome_tabela> INDEX <nome_indice>;
- Executar UNLOAD/RELOAD. Este procedimento faz com que o banco fique no estado ótimo, com suas tabelas e índices desfragmentados. É um comando que, num banco de produção de 30Gb, leva em torno de 2-5h para ser executado completamente portanto não é um procedimento que possa ser executado diaria ou semanalmente. O ideal é realizarmos este procedimento semestral ou anualmente.
- Usar cache. Não existe um número mágico. Alguns recomendam 10% do tamanho do banco, outros a maior quantidade de memória disponível no servidor. Sugerimos iniciar com 10% do tamanho do banco ou a maior quantidade disponível (o que for menor) e verificar (através dos parâmetros de performance descritos acima) como o banco se comporta. Em seguida, ir aumentando (se possível) o tamanho do cache voltando a verificar os parâmetros para ver como eles se comportam a fim de obter o valor ótimo.
- Sempre utilizar o arquivo .log. Conforme foi descrito (tópico: como o dado é gravado), quando um dado é gravado no banco, o custo disso ao banco é mínimo pois ele grava o dado sequencialmente no log de transações (arquivo .log) deixando para o evento CHECKPOINT salvar o dado no local correto. Quando não trabalhamos com o arquivo .log, o banco é obrigado a executar o CHECKPOINT a cada transação dispendendo um esforço enorme quando o número de COMMITS é alto.
- Colocar o arquivo .db e .log em discos distintos.
- Utilizar RAID 1+0.
Usuário está travado. O que fazer?
Um usuário pode estar com seu computador aparentemente travado e isto tem, obviamente, várias causas que podem estar ou não relacionadas ao banco de dados. Vamos assumir então que todas as outras causas (computador com defeito em algum de seus componentes, rede intermitente, problema no Sistema Operacional, lentidão no servidor causada por algum outro processo sendo executado, etc) foram analisadas e estão em ordem.
Devemos, então, formular algumas perguntas:
- Em que tela o usuário está travado?
- Que ação foi executada nesta tela para o travamento?
- A quanto tempo está parado?
- Consegue fazer outras coisas no computador?
- Isso ocorre com frequencia? Cuidado com esta pergunta pois é uma pergunta muito aberta e todos os usuários têm a tendência a dizer sim porém não sabem responder a próxima pergunta.
- Qual é a frequência? A que horas isso ocorre? Quantas vezes ao dia? Existe algum padrão?
- Normalmente, esperando um pouco mais o computador "destrava"? Qual é normalmente a ação tomada?
- O que ocorre depois disso? O usuário consegue trabalhar normalmente ou é necessário resetar o computador completamente?
- Isso ocorre somente com este usuário ou quando ocorre com ele acaba ocorrendo com outros usuários?
Todas as informações são importantes independente do que está ocorrendo pois, mesmo que seja um travamento por culpa de algum outro usuário atualizando a mesma tabela que este usuário, podemos identificar e simular mais rapidamente o problema.
Vamos supor então que o usuário está lá parado e você deseja ajudá-lo identificando qual o problema. Podem existir duas situações típicas: - Lentidão. Parece que o usuário está travado porém o processo que ele está executando está sendo executado só que mais lentamente do que ele presumira inicialmente.
- Travamento. O usuário está parado esperando a liberação de algum registro em outra tabela.
Lentidão
Podemos identificar se um usuário está ou não executando algo no servidor através de dois procedimentos (depende se o FoxHound está disponível ou não). Caso você não tenha o FoxHound, execute o comando abaixo.
O resultado segue abaixo.Bloco de código select connection_property('ReqStatus', sci.Number) as ReqStatus, usu.usuario, sci.* from sa_conn_info() sci INNER JOIN usuarioConexaoBanco usu on (sci.number = usu.IdConexao) WHERE USUARIO = <NOME USUARIO INVESTIGADO>
Note que, como não existe nenhuma informação nas informações vindas da conexão (pois todas se logam como DBA), o Sispetro registra, quando o usuário faz o login, na tabela UsuarioConexaoBanco o número da conexão (Number) juntamente com o nome do usuário sempre sobreescrevendo o último valor apresentado.
Podemos ver acima que o usuário Futura não está realizando nenhum trabalho no banco (pois a coluna ReqStatus está com o valor Idle e a coluna LastReqTime está com uma data/hora muito distante de quando foi executado o comando). Além disso, ele não está travado por nenhuma outra conexão (apareceria o número da conexão na coluna BlockedOn).
Uma outra alternativa é utilizar o FoxHound sendo que antes devemos pesquisar o número da conexão (ou números pois o Sispetro utiliza 2 conexões ativas).