segunda-feira, 14 de agosto de 2017

Dicas para agilizar a consulta de dados em uma DBGrid

A lentidão ao carregar dados em uma DBGrid pode ser causada por vários fatores que, muitas vezes, nos passam despercebidos. As seis orientações abaixo podem ser úteis para agilizar o carregamento de dados ou, talvez, para evitar futuras lentidões.
1) Revise a instrução Select que consulta os dados
Assim como mencionei no artigo sobre práticas de otimização em banco de dados, as consultas SQL devem trazer apenas os dados que são necessários na visão da DBGrid. Por exemplo, se existem 10 colunas em uma tabela e somente 4 são exibidas em uma DBGrid, as outras 6 podem (e devem) ser retiradas da consulta. Para isso, substitua o asterisco pelas colunas requisitadas, conforme a comparação abaixo:
-- Seleciona TODAS as colunas da tabela, desnecessário na maioria das consultas
SELECT * FROM PRODUTOS
 
-- Seleciona somente as colunas necessárias para exibir os dados
SELECT Codigo, Descricao, Valor, Qtde FROM PRODUTOS
Além disso, em alguns casos, há tabelas com colunas do tipo BLOB, que armazenam dados binários de imagens e documentos ou textos longos. Se essas colunas forem adicionadas na consulta, o tempo de retorno será ainda mais demorado. A minha recomendação é trazer estes dados sob demanda em uma instrução separada, como comentei no artigo sobre eventos de tela.

2) Evite abrir e fechar o DataSet repetidas vezes
Quando for necessário aplicar um filtro nos dados, como um intervalo de datas, procure utilizar as propriedades Filter e Filtered, ao invés de comandos que fazem acesso ao banco, como CommandText, Close/OpenExecSQL. A explicação é que a propriedade Filter trabalha com dados em memória, isto é, que já foram carregados.
Entrando mais em detalhes técnicos, o ideal é substituir esses tipos de consulta:
DataSet.Close;
DataSet.CommandText := 'Select * from CLIENTES where Nome like ' + QuotedStr(Edit1.Text + '%');
DataSet.Open;
Por filtros como esse:
DataSet.Filter := 'Nome like ' + QuotedStr(Edit1.Text + '%');
DataSet.Filtered := True;

3) Atente-se aos eventos do DataSet, dos Fields e de pintura da DBGrid
Por falar em eventos de tela, o desenvolvedor também deve ser prudente ao utilizá-los, já que podem impactar no tempo de carregamento dos dados. Por exemplo, você sabia que o evento OnDrawColumnCell do componente DBGrid é chamado para cada registro que é carregado? Insira um ShowMessage neste evento, abra o DataSet e observe a quantidade de vezes que a mensagem é exibida. Logo, se houver um processamento neste evento, é evidente que os dados levarão um tempo maior para serem carregados.
A mesma orientação é válida para eventos do DataSet conectado à DBGrid, como BeforeOpenAfterOpenBeforeGetRecords e AfterGetRecords. Embora sejam executados apenas uma vez ao consultar os dados, podem apresentar lentidões se os processamentos forem extensos.
Seguindo a mesma lógica, o evento OnGetText do TField (campo da tabela), como trata a exibição dos dados de uma coluna, também é executado para cada registro e deve ser observado.

4) Adicione filtros na tela para evitar a consulta de vários registros
Muitos desenvolvedores costumam executar a consulta de dados logo quando a tela é aberta. Sendo assim, se houverem 10 mil registros, todos eles serão consultados de uma vez só! Bom, nem preciso comentar que isso é uma falha de desempenho indiscutível, não é?
Além da demora, esse procedimento também não deixa de ser uma questão de usabilidade. Muitas vezes, o usuário entra na tela para visualizar os dados de apenas 1 registro, e precisa esperar, desnecessariamente, a consulta de todos os registros da tabela.
A recomendação é disponibilizar filtros na tela (como código, descrição, tipo, período, etc…), e realizar a consulta somente quando estes filtros forem informados. Com essa alteração, já consigo apontar 3 vantagens: 1) não haverá “gargalos” ao abrir a tela; 2) o usuário visualiza somente o(s) registro(s) desejado(s); 3) reduz o tráfego de dados em um ambiente cliente/servidor.

5) Ative a paginação de registros com a propriedade PacketRecords
Quem disse que não dá para fazer paginação com Delphi? A propriedade PacketRecords do DataSet permite definir a quantidade de registros que serão “paginados”, ou carregados por vez.
Faça um teste: preencha a propriedade PacketRecords com o valor 100 e abra um DataSet que tenha aproximadamente 1000 registros. Observe que apenas 100 registros serão exibidos inicialmente na DBGrid, porém, ao navegar até a última linha, os próximos 100 registros da tabela serão carregados e exibidos automaticamente.
Este recurso pode ser bastante útil quando a tela exige a consulta de milhares de registros, por uma questão técnica ou por solicitação do cliente, ou mesmo quando a terceira dica, sobre filtros na tela, é inviável.

6) Modere na utilização de componentes de terceiros
Às vezes precisamos de algum comportamento adicional, não existente no componente TDBGrid nativo do Delphi. Como solução, normalmente instalamos componentes de terceiros para atender a nossa necessidade. No entanto, vale ressaltar que estes componentes trazem vários outros comportamentos que, em sua maior parte, pode não nos interessar no momento. Por exemplo, suponha que um componente de terceiro monte toda uma estrutura de agrupamento dinâmico, ative campos Lookup ou faça uma indexação do conteúdo para buscas, quando, o que realmente precisamos, é só um totalizador de valores no rodapé. Por estarem acoplados ao componente, estes outros comportamentos “paralelos” também podem impactar indiretamente no carregamento dos dados.
A minha sugestão é criar um novo componente herdado da classe TDBGrid e adicionar os comportamentos desejados, mesmo que exija um pouco mais de tempo. Além de dispensar a instalação de componentes de terceiros, o desenvolvedor ganha a liberdade de customizar o componente de acordo com suas próprias necessidades.

Nenhum comentário:

Postar um comentário