Fórum Otimização de pesquisa (Banco de dados) #212226
06/02/2004
0
O texto é um pouco grande (Procurei detalhar), mas POR FAVOR.... alguem me ajude!!! :D
Normalmente fico aqui quebrando a cabeça sozinho, até pq é um excelente aprendizado, acabamos pesquisando e descobrindo muito mais do que procurávamos, mas ocorre que ela já está doendo demais e não estou conseguindo elucidar o crime! Bem deixa de bobagens e vamos aos fatos.
Estou desenvolvendo um pequeno sistema para uma empresa de eventos. Este sistema ficará na portaria dos eventos (feiras) para verificar os dados das pessoas que entram (em função de um prévio cadastro).
A tabela clientes (que é a que está me deixando louko) é bem simples, composta apenas dos seguintes campos:
1)ID_Cliente (Int)
2)cd_Ficha (Int)
3)Nome (Text 60)
4)RG (Text 18)
5)CPF (Text 18)
Todos os campos indexados!!!
Indexei todos os campos, pq todos serão utilizados pela pesquisa (menos o de chave primária, ID_Cliente). A telinha é bem simples:
F3 = Pesquisa pelo código da ficha
F4 = Pesquisa pelo nome
F5 = Pesquisa pelo RG
F6 = Pesquisa pelo CPF
F9 = Mostra ficha de inscrição digitalizada (escaneada) que é lido de um jpg
Para cada uma das pesquisas o referido campo é indexado.
Agora vem o problema!
Minha base de testes tinha 25000 registros... em access... não era a coisa mais rápida do mundo, mas respondia em tempo satisfatório...
Peguei o banco de dados real... e ... surpresa!!! Tem 140000 registros...
Ficou simplesmente (perdoem-me pela sinceridade) ´a mosca do cocô do cavalo do bandido´. Simplesmente uuuummmmaaaaa ccccaaaarrroooçççaaa.... Impossível de se fazer qualquer pesquisa! Lentidão na inicialização, tudo bem, mas na operação não dá!
Para ajudar, todas as máquinas não ajudam... são todas AMD K6 II 500 com 64mb... não são máquinas muito rápidas, mas também não são nenhum XT!
A questão é que eu já tentei inclusive migrar o banco para Interbase e a resposta foi POUQUISSIMA melhor... É claro que eu devo estar fazendo alguma besteira... eu na realidade voltei a programar em delphi há 3 meses depois de ter ficado 6 anos sem programar nesta linguagem. Faz 6 anos que só programo em ColdFusion e fiz um teste com esta liguagem que usa ODBC e é interpretada em servidor, e ainda por cima com resultado em HTML interpretado em Browser e o resultado foi MUITO mais rápido!
Então, percebo que:
1) Não sei qual tipo de conexão é a mais adequada!
2) Que componentes utilizar.
3) O modo como eles se relacionam (a sequencia)
4) To fazendo mer.. !!! :oops:
Alguma luz no fim do tunel?
Agradeço antecipadamente qualquer tipo de ajuda e colaboração dos amigos....
[b:8de7b70444][color=red:8de7b70444]Título editado pelo Moderador (AZ) - Removido: ´Nem com reza braba! ´[/color:8de7b70444][/b:8de7b70444]
Fabdeg
Curtir tópico
+ 0Posts
07/02/2004
Ildefonso
Que tipo de conexão com o banco de dados vocês está usando?
O ADO é o mais indicado para tabelas do Access.
Além disso, seu banco de dados deveria ficar ´preparado´... Use o próprio Access, por questão de particidade, para indexar os campos e, em seguida, faça uma compactação. Isso fará o BD ficar organizado da maneira mais prática e rápida para o Engine do Access procurar os dados.
Para as pesquisa, use a propriedade Filter + o método FindFirst...
Presumindo que sua tabela chama-se Clientes e um Edit chamado txtValor tem o valor a ser buscado (logicamente, você deve implementar variáveis e opções para decidir qual campo procurar):
var expr: String; begin expr := ´´´´ + txtValor.Text + ´´´´; //aqui você colocaria seus teste de campos //neste exemplo, apenas o campo RG expr := ´[RG] = ´ + expr; Clientes.Filtered := False; Clientes.Filter := expr; if Clientes.FindFirst then //ações se achou else //ações se não achou ;
O primeiro comando coloca seu argumento entre apóstrofos para satisfazer a sintaxe da expressão (algo como: [RG] = ´1234´).
Note que o DataSet não fica ´filtrado´. Na propriedade Filter coloca-se uma expressão - que segue a sintaxe de uma cláusula WHERE - que será interpretada pelo Engine. Como não deve filtrar, ele apenas desloca para o registro caso o FindFirst encontre algo que satisfaça a condição.
Além do FindFirst, há a possibilidade de FindNext, FindLast, FindPrevious. A expressão pode ser incrementada com o LIKE ´¬algo-a-procurar¬´, que é mais lento (principalmente em seu caso), mas algumas vezes, indispensável.
Já trabalhei com grandes bases de dados no Access e não tive grandes problemas. Acho que você consiguirá uma boa solução.
Bom trabalho. 8)
Gostei + 0
07/02/2004
Alexdias
USE UM RADIOGROUP, UM BUTTON E 3 EDITs TODOS DA GUIA STANDARD .
USE TB UM MASKEDIT DA GUIA ADDITIONAL.
RENOMEIE PARA CONNECT1,QCLIENTE,DSCLIENTE;
RENOMEIE PARA RG1,BITCONSULTAR,MKDADOS,EDNOME,EDCPF,EDRG;
NO RG1 NA PROPRIEDADE ITEMS DIGITE NOME CPF RG UM PARA CADA LINHA E CLARO ...
AINDA NO RG1 NA PROPRIEDADE ITEMINDEX MARQUE 0 ;
AGORA CRIE UMA VARIAVEL GLOBAL DE NOME V_TEXTO DO TIPO STRING ( ESTA VARIAVEL E QUE INFORMARA AO SISTEMA POR QUAL CAMPO CONSULTAR ( NOME, CPF,RG ...);
O MKDADOS E ONDE DIGITAREMOS OS DADOS A SEREM CONSULTADOS E OS EDNOME,EDCPF,EDRG ONDE SERAO MOSTRADOS OS RESULTADOS DA CONSULTA CASO POSITIVO;
ALTERE A PROPRIEDADE DEFAULT DO BUTTON PARA TRUE E A PROPRIEDADE READONLY DO EDRESULT PARA TRUE;
OBS : VAMOS SIMULAR QUE A CONSULTA SERIA APENAS POR NOME CPF E RG.
mkdados
VAMOS AO CODIGO ...
NO EVENTO ONACTIVETE DO FORM V_TEXTO:=´NOME´;
NO EVENTO RG1.CLICK
IF rg1.itemindex=0 THEN BEGIN v_texto:=´NOME´; mkdados.MaxLength:=30; mkdados.Width:=400; mkdados.editmask:=´´; END ELSE BEGIN IF RG2.itemindex=1 THEN BEGIN v_texto:=´CPF´; mkdados.MaxLength:=11; mkdados.Width:=200; mkdados.editmask:=´999.999.999/99;1;_´; END ELSE BEGIN v_texto:=´RG´; mkdados.MaxLength:=18; mkdados.Width:=200; mkdados.editmask:=´´; END; END; mkdados.Clear; mkdados.setfocus;
NO EVENTO BITCONSULTAR.CLICK
IF mkdados.text=´´ THEN
BEGIN
messagedlg (´NOME , CPF OU RG DEVEM SER PREENCHIDOS PARA REALIZAR ESTA CONSULTA !!!´,MTWARNING, [MBOK], 0);
mkdados.setfocus;
exit;
END;
bitconsultar.enabled:=false;
IF NOT (dm.qcliente.locate(V_texto,mkdados.text,[loPartialKey])) then
BEGIN
Messagedlg( ´NÃO FORAM ENCONTRADOS REGISTROS PARA ESTA CONSULTA !´,mtwarning,{mbok],0);
END
ELSE
BEGIN
ednome.text:=dm.qcliente.fieldbyname(´nome´).asstring;
edcpf.text:=dm.qcliente.fieldbyname(´cpf´).asstring;
edrg.text:=dm.qcliente.fieldbyname(´rg´).asstring;
END;
bitconsultar.enabled:=true;OBS NO INICIO DO CODIGO DO FORM NO FINAL DE USES DEVE SER INCLUIDO ‘ DB ‘ EXEMPLO
unit Ucliente; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, DBCtrls, Mask, ComCtrls, Grids, DBGrids,db; type TFM_CLIENTE = class(TForm)
ESPERO TER AJUDADO ...
ALEX DIAS
alexdiastec@ig.com.br
Gostei + 0
07/02/2004
Alexdias
A PALAVRA DM CASO ESTEJA USANDO UM DATA MODULE.
IF NOT (dm.qcliente.locate(V_texto,mkdados.text,[loPartialKey])) then
CASO NÃO ESTEJA USANDO UM DATAMODULE USE
IF NOT (qcliente.locate(V_texto,mkdados.text,[loPartialKey])) then
FUIIIIIIIIIIIIIIIIIIIIII !!!! :D
Gostei + 0
09/02/2004
Fabdeg
Obrigado pela explicações. Tentei várias coisas... com o access, eu usei o ADO mesmo... com o Interbase eu usei o componentes da guia IB.... tentei usar os da guia DBExpress, mas ao compilar o programa ele dá erro dentro de um dos componentes.
COmo não havia testado algumas das sugestões que me foram dadas, farei alguns testes e depois posto aqui os resultados.
Obrigado a todos
Gostei + 0
12/02/2004
Fabdeg
Fiz aqui meus testes... De fato, as sugestões mostradas pelo amigo Ildefonso tiveram a melhor performance.... mas, se eu tentar ordenar a lista....xiiiiiiiiiiiiiiiii.... não dá... a caisa leva 3minutos para ordenar a coluna desejada... então pensei em ter 4 Datasets...cadaum ordenado pelo campo desejado e então fico apenas ´chaveando´ no DS entre um Dataset e outro. Isso me causaria uma lentidão maior na inicialização, mas resolveria meu problema de ordenação, entretanto, ainda continuaria com o problema de atualização de dados... uma das máquinas vai ficar fazendo inscrições de última hora, e depois a pessoa vai para a fila de impressão de crachas como outra qualquer... ganhei mais um problema! Alguém digita os dados do cidadão, mas depois estes dados não são listados automatiamente.... coisas da informática!!!
Outra coisa : Para que serve o ´Prepared´?
Eu até deixei em true como sugerido pelo amigo Ildefonso, mas não entendí o que ele faz...
as alguma sugestão?
Obrigado a todos mais uma vez!!!
Gostei + 0
13/02/2004
Ildefonso
Minha sugestão sobre compactar e corrigir o banco de dados é para ser usada apenas em um momento do dia. Tenho visto que meus clientes, alguns com dezenas de milhares de registros, organizam o BD apenas uma ou duas vezes por semana.
O atuais BDs sabem usar o índice melhor para cada pesquisa, baseado nos próprios campos incluídos nas expressões de pesquisa que você envia. Isto dispensaria a necessidade de você fragmentar ou separar em arquivos diferentes dados e índices.
Teoricamente, um banco de dados Access pode ter até 2 gigabytes de tamanho. Um banco de dados InterBase de ir a casa dos TeraBytes, então você não está no limite de capacidade deles.
Acho que você está próximo de encontrar o equilíbiro para a velocidade ideal.
Gostei + 0
16/02/2004
Davidbezerra
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)