quinta-feira, 13 de fevereiro de 2014

Uso excessivo de distinct em banco de dados

Pra que usar distinct 

O comando distinct serve para eliminar linhas duplicadas em uma select. É um comando muito útil quando queremos remover linhas duplicadas quando todas as colunas resultam a mesma coisa.

O resultado final sera uma select com os dados já filtrados.

Eu particularmente não gosto, não recomendo e acho que o distinct é um comando utilizado para programadores preguiçosos. Nossa, não me matar por isso.

Veja, essa é minha opinião.

Em um sistema de padaria feito em casa com poucos registros é até válido. Mas vamos pensar em um ambiente compartilhado com um grande volume de informações e leituras em massa. O fato do banco retornar sua consulta em alguns segundos não quer dizer que esta consulta esta otimizada.

Dentro do banco de dados, muita coisa acontece somente para trazer esses registros filtrados.

Os problemas de performance ficam piores quando a base começa a crescer. Mas não deixe para otimizar suas querys somente após o problema começar, comece desde o primeiro registro pensando como essa informação sera resgatada posteriormente.

Mais da metade de problemas de lentidão no banco é devido as instruções SQL mal escritas.
O restante são ajustes, infra, sistema operacional e configurações diversas.

Como o banco de dados trata o distinct

Ao montar uma consulta, o banco de dados primeiramente procura um plano de execução que ja foi montado previamente.
Quando ele não encontra, ele ira fazer um hard parse. Isto é, ele vai verificar diversas coisas antes de retornar sua consulta. Exemplo : O usuário logado tem acesso ao banco, essa tabela existe, a select esta certa, quais são as colunas dessa tabela, as instruções estão na memória do servidor, os dados estão na memória, como vou buscar esses dados ?.
Feito isso, o banco ira retornar os dados.
Olha o tempo que perdemos com isso ?. 1 segundo... Agora imagine 1000 pessoas consultando ao mesmo tempo ?.

O distinct é mais um complicador.

Mas vamos dar um exemplo.

Tenho uma consulta que ira me trazer 5 milhões de registros, mas, eu preciso somente de 100 registros porque o resto é duplicação.

Ai vai lá o desenvolvedor e tem a brilhante ideia...DISTINCT nele.

O banco vai levar na memória 5 milhões de registros e utilizando CPU de forma desnecessária ele ira exibir somente os 100 registros que interessa.

Derrepentemente a base cresce de 5 milhões para 100 milhões de registros. Ai começa... o banco tá lento... o banco tá um lixo. Não... o banco não tá um lixo... A sua query é que é um lixo.

Ai chega o DBA e descobre o problema cobrando uma fortuna.

Quando for fazer uma query e precise filtrar registros duplicados, tenho duas técnicas que pode ser substituída pelo o Discinct 

1) Utilize GROUP BY

2) Faça todas as amarrações entre as tabelas utilizando preferencialmente os índices entre elas

Entenda primeiramente as tabelas, suas amarrações e principalmente, estude normalização de banco de dados.

Em breve irei postar um artigo sobre normalização de banco de dados.


terça-feira, 4 de fevereiro de 2014

Configurando o Top Connect para o Oracle

Configurando o Top Connect para o Oracle

O Protheus como muitos sabem, pode trabalhar com diversos bancos.
Sua configuração para o Top Connect é um pouco complicada e requer experiência. Mas com o procedimento abaixo, qualquer um conseguira fazer.

Vamos lá então.

Configurando o Oracle

Antes de qualquer coisa, é necessário configurar o Net Manager. 
Neste caso, já estou imaginando que o Top Connect foi instalado em um servidor / estação onde já existe o client do Oracle instalado.


Faça o teste 



Instalando o Top Connect

A primeira coisa que devemos identificar, é se o sistema operacional é 32 ou 64 bits.
Neste exemplo, a configuração é para Windows 64 bits, e em breve irei postar como fazer a mesma instalação pelo Linux.
Note que o banco pode estar em Linux ou Windows, a configuração que estou me referindo, é para o local em que o Top Connect sera instalado.

Após baixar e instalar o top connect, acessar o monitor do Top e digitar o nome do servidor em que o programa foi instalado


Configurar o Top Connect. Alterar conforme as configurações do seu banco de dados.



Salve

Agora, vá até o local do executável do Top Connect, e faça algumas alterações no arquivo INI 

[General]

Port=7890
LicenseServer=SERVER01
LicensePort=5555 ;Local da instalação do Hard Lock
ByYouProc=0

Adicionar as linhas em vermelho

[ORACLE] ;Nome daquele ambiente que disse que iria dizer depois pra que servia
OCIVersion=8 ; Manter se for Oracle acima da versão 8
ORACLE_HOME=C:\ORACLE\sistema\product\11.2.0\dbhome_1 ; Local da instalação do aplicativo do Client do Oracle

Feito isso, vamos testar



Feito isso, agora é necessário configurar o serviço do Protheus.
A configuração relacionada ao Top Connect para o Oracle termina aqui.

segunda-feira, 3 de fevereiro de 2014

ADVPL-Dicas de uso racional do banco de dados com o Protheus

Utilizando o banco de forma racional

Muitas vezes contratamos um DBA, uma consultoria mas notamos que a performance do Protheus não é boa. Mas porque isso acontece, como resolver esse problema ?.

Primeiramente, é necessário deixar claro que não existe uma formula magica, onde ao apertar um simples botão, todos os seus problemas serão solucionados.

Se existe uma fórmula magina, na minha opinião é entender o problema. Entender o que esta acontecendo com o Protheus e minha base de dados. Geralmente não é um único problema mas um conjunto de problemas que deixam a base / Protheus cada vez mais lento.

Identificando o problema

Geralmente se a base estava normal e derre pente o banco ficou extremamente lento, é importante pensar em algumas possibilidades :
  • Foi feita alguma atualização do ERP ou banco de dados ?
  • Foi feito alguma atualização do sistema operacional ?
  • O servidor possui espaço livre em disco ?
  • Alguma coisa foi feita no banco de dados ?
Provavelmente, se você respondeu sim para qualquer uma das alternativas acima, isso significa que a atualização não foi bem planejada. É por este motivo que é necessário contratar um profissional especializado.

Melhorando as consultas de querys

Com o Protheus, não é possível utilizar planamente todos os recursos do banco de dados, mas é possível chegar bem próximo do usável.

Utilize corretamente os índices da tabela

Abaixo, vou extrair as informações de um cadastro de clientes da maneira mais chula que existe. Veja o quanto custa para o banco de dados

SELECT * FROM SA1010 SA1010
WHERE SA1010.A1_COD = '009144'

Figura 1

Veja o custo para a CPU para o banco de dados. Agora vamos melhorar a consulta para minha necessidade mas utilizando corretamente os índices do Protheus.

SELECT SA1010.A1_COD, SA1010.A1_NOME
  FROM SA1010 SA1010
 WHERE SA1010.A1_COD = '009144'
   AND SA1010.A1_LOJA = '01'
   AND SA1010.A1_FILIAL = '  '
   AND SA1010.D_E_L_E_T_ = ' '

Figura 2

Observe na figura acima e comparando com a primeira figura, que o resultado sera o mesmo mas o custo para o banco de dados foi muito menor.

Mas porque isso aconteceu ?.

Isso aconteceu porque utilizamos corretamente todos os índices para aquela tabela.
Note também que ao invés de mandar exibir todas as colunas, listei somente as colunas que realmente havia a necessidade de trazer.
Sempre que for construir uma nova consulta, é importantíssimo verificar os índices que o Protheus criou.

Geralmente ao utilizar uma busca por DBSEEK, ja estamos utilizando o recurso dos índices devido ao comando DBSETORDER.
O DBSETORDER ao receber qual é o número do índice, faz o Protheus montar a query utilizando dos índices cadastrados na tabela SIX.

Crie índices para melhorar a performance mas cuidado para não exagerar.


Um índice no banco de dados, é uma tabela com as colunas indexadas com o endereço físico da informação que deseja pesquisar.
Se você sair criando índices para todas as colunas, este índice passa a ser uma tabela. Índice aumenta o tamanho de seu banco de dados, deixa mais lento a gravação. No exemplo da figura 2 note que o A1_FILIAL esta com dois espaços em branco. Isto ocorre porque minha tabela SA1 é uma tabela compartilhada. Como o A1_FILIAL faz parte do índice eu utilizei dois espaços em branco para o Oracle não ter que varrer o índice.

Se conseguir, desapareça com os filtros personalizados

Usuário é um artista. Quando você pensa que ele já fez de tudo, sempre aparece uma coisa nova.

Conforme havia falado do comando DBSETORDER, ao definir o número do índice, o Protheus vai montar a query utilizando todas as colunas que foram indexadas.
O Problema do FILTRO PERSONALIZADO, é que ele pode não utilizar o índice do banco.
Mas... porque ?

Porque o usuário vai montando o índice do jeito que ele quer.
Exemplo :

O usuário recebe um depósito no banco tal. Mas ele não sabe quem depositou porque era para ter sido pago por um boleto bancário.
Então ele faz oque !. Ele monta um filtro personalizado e digita o valor do título. Valor não esta indexado, então o banco faz oque ?. Sai varrendo todo o banco de dados até encontrar o valor.
Toda essa tabela vai ficar na memória do banco do servidor, esvaziando tudo o que estava em cache para carregar a consulta do tal usuário.
Esta operação, deixa por algum tempo o banco de dados lento.

Para quem não sabe qual é o filtro personalizado, é aqui :

Figura 3
Este tipo de filtro eu chamo de destruidor de banco de dados.

Tente entender porque o usuário precisa disto. Onde isso vai ser útil no dia a dia.

Muitas vezes a lentidão da contabilidade, foi causada por um filtro incorreto lá do módulo financeiro.

Padronize o suas querys


O banco de dados monta um plano de execução para retornar a informação desejada.
Para o banco de dados, um SELECT * FROM é diferente de um select * from.
O banco de dados ira montar um hard parser, isso quer dizer, que o banco ira verificar novamente toda a query como : O usuário tem acesso nesta tabela ?. Esta tabela existe ?. As colunas estão corretas ?. A tabela esta na memória do servidor ?. Não... então vou carregar.
Se tiver mais de um analista, converse com ele para esta padronização.

Rode as estatísticas


Quando uma atualização do banco de dados é feita, o Protheus geralmente adiciona novos índices. Ao criar estes índices, o banco automaticamente já faz a estatísticas para aquele índice mas isso não quer dizer que outras coisas precisam ser corrigidas.
Procure um DBA que ele pode fazer uma análise melhor do que esta ocorrendo.

Para resumir, existem muitas coisas que podem e devem ser feitas no banco de dados e eu poderia ficar escrevendo muitas páginas sobre este assunto.

A melhor forma de melhorar a performance do Protheus, é Procure um Dba qualificado no banco de dados que esta instado na sua empresa, e que principalmente Entenda o Protheus.


Não de voltas atoa. Cuidado com a cardinalidade


(Pra que retornar um milhão de linhas se somente uma única linha sera aproveitada)

Já vi cada coisa maluca por ai. Fui em uma empresa que o analista criou um relatório que fazia o seguinte :

A query fazia um select no banco de dados inteiro e depois no final, existia um ROWNUM =1. Ai fiquei pensando, pra que isso ?. Quando questionei o analista, ele me disse que era porque ele precisava somente de um único registro, ou seja o primeiro que vier.
Para o analista que montou, parece um preciosismo achar que o ROWNUM vai deixar o banco lento. Não é o ROWNUM que vai deixar lento, é a volta.

Não fique no acho que ta bom, tenha uma métrica, não quer dizer que porque a consulta retornou um certo dado em 1 segundo que a consulta esta boa.

Cuidado com o Distinct


Na minha opinião, distinct é coisa de quem não sabe o que esta fazendo ou de analista preguiçoso.
Muitas vezes é melhor fazer diversas consultas pequenas do que uma consulta muito complexa. Se você sabe o que esta procurando, não tem a necessidade de utilizar o distinct.