Melhorar o desempenho de um select com Inner Join
Boa tarde a todos.
Tenho duas tabelas distintas no Mysql com mais de 900.000 registros, onde faço o seguinte comando:
É meio brabo, mas acreditem, é necessário. :(
Quando efetuo uma busca, digamos do dia 01/05/07 a 20/06/07, o sistema demora cerca de 15 min, sem falar que gera uma inconsistência no servidor, deixando os outros PC´s lentos. Gostaria de saber se existe alguma forma de melhorar o desempenho dessa consulta.
Grato pela atenção.
Obs: Utilizo delphi 7 com o Zeos e Mysql 4.0.22
Tenho duas tabelas distintas no Mysql com mais de 900.000 registros, onde faço o seguinte comando:
Select * from tdcupant INNER JOIN finafim ON (tdcupant.numcupom = finafim.numcup and tdcupant.impcaixa = finafim.impcaixa and tdcupant.dtcompra = finafim.dtcomp) where dtcompra >=:inicio and dtcompra <=:fim order by dtcompra, hora
É meio brabo, mas acreditem, é necessário. :(
Quando efetuo uma busca, digamos do dia 01/05/07 a 20/06/07, o sistema demora cerca de 15 min, sem falar que gera uma inconsistência no servidor, deixando os outros PC´s lentos. Gostaria de saber se existe alguma forma de melhorar o desempenho dessa consulta.
Grato pela atenção.
Obs: Utilizo delphi 7 com o Zeos e Mysql 4.0.22
Turbo Drive
Curtidas 0
Respostas
Emerson Nascimento
22/08/2007
crie índices para os campos envolvidos no relacionamento, no [i:19c2cdec39]where[/i:19c2cdec39] e no [i:19c2cdec39]order by[/i:19c2cdec39].
GOSTEI 0
Adriano Santos
22/08/2007
Cara você pode levar em consideração no seu JOIN também o tamanho de registros de cada tabela e fazer o Join de acordo com isso, por exemplo:
TDCUPANT = 900.000 registros
FINAFIM = 300.000 registros
OUTRA_TABELA = 1.000 registros
O seu join deverá começar pelas tabelas menores, ou seja, por OUTRA_TABELA, depois FINAFIM e por ultimo TDCUPANT. Por que isso?
Bem, quando o banco chegar na última tabela do join, grande parte dos registros já estarão separados, filtrados levando menos tempo dentro da tabela com 900.000 registros.
Claro que no seu caso não ajuda muito, mas deve melhorar um pouco a performance.
Mas não esqueça o que o emerson.en dissse. Crie indices, não dá pra fazer mágina com esse volume de dados.
Abs
TDCUPANT = 900.000 registros
FINAFIM = 300.000 registros
OUTRA_TABELA = 1.000 registros
O seu join deverá começar pelas tabelas menores, ou seja, por OUTRA_TABELA, depois FINAFIM e por ultimo TDCUPANT. Por que isso?
Bem, quando o banco chegar na última tabela do join, grande parte dos registros já estarão separados, filtrados levando menos tempo dentro da tabela com 900.000 registros.
Claro que no seu caso não ajuda muito, mas deve melhorar um pouco a performance.
Mas não esqueça o que o emerson.en dissse. Crie indices, não dá pra fazer mágina com esse volume de dados.
Abs
GOSTEI 0
Turbo Drive
22/08/2007
Beleza galera. Desculpe a ignorância, mas o q seriam esses índices e como utilizá-los ?
GOSTEI 0
Adriano Santos
22/08/2007
[quote:b2b8d0c71d=´Turbo Drive´]Beleza galera. Desculpe a ignorância, mas o q seriam esses índices e como utilizá-los ?[/quote:b2b8d0c71d]
[b:b2b8d0c71d]Turbo Drive[/b:b2b8d0c71d] os índices são, grosseiramente falando, como o índice de um livro. É por ele que o banco de dados se orienta pra encontrar mais rapidamente os registros. Todo banco de dados tem este recurso.
Para se criar índice no Firebird por exemplo faça desta forma:
Aqui, estou criando um índice único com o nome [b:b2b8d0c71d]NOME_DO_INDEX[/b:b2b8d0c71d], na tabela [b:b2b8d0c71d]FORNECEDORES [/b:b2b8d0c71d]com os campoas [b:b2b8d0c71d]CNPJ, FANTASIA e RAZAO[/b:b2b8d0c71d]. Por ser único ([b:b2b8d0c71d]UNIQUE[/b:b2b8d0c71d]) não poderei incluir um fornecedore com o mesmo [b:b2b8d0c71d]CNPJ, FANTASIA e RAZAO[/b:b2b8d0c71d] que já exista na base de dados.
Você pode criar quantos índices forem necessários para o seu banco de dados. Mas índice não é só pra esta utilidade. Os índices ajudam a integridade de dados como Checks, Constraints e Foreign Keys. Ajudam na ordenação e etc.
Qualquer dúvida entre novamente em contato.
[b:b2b8d0c71d]Turbo Drive[/b:b2b8d0c71d] os índices são, grosseiramente falando, como o índice de um livro. É por ele que o banco de dados se orienta pra encontrar mais rapidamente os registros. Todo banco de dados tem este recurso.
Para se criar índice no Firebird por exemplo faça desta forma:
CREATE UNIQUE INDEX NOME_DO_INDEX ON FORNECEDORES (CNPJ,FANTASIA,RAZAO)
Aqui, estou criando um índice único com o nome [b:b2b8d0c71d]NOME_DO_INDEX[/b:b2b8d0c71d], na tabela [b:b2b8d0c71d]FORNECEDORES [/b:b2b8d0c71d]com os campoas [b:b2b8d0c71d]CNPJ, FANTASIA e RAZAO[/b:b2b8d0c71d]. Por ser único ([b:b2b8d0c71d]UNIQUE[/b:b2b8d0c71d]) não poderei incluir um fornecedore com o mesmo [b:b2b8d0c71d]CNPJ, FANTASIA e RAZAO[/b:b2b8d0c71d] que já exista na base de dados.
Você pode criar quantos índices forem necessários para o seu banco de dados. Mas índice não é só pra esta utilidade. Os índices ajudam a integridade de dados como Checks, Constraints e Foreign Keys. Ajudam na ordenação e etc.
Qualquer dúvida entre novamente em contato.
GOSTEI 0
Rodrigobertero
22/08/2007
Importante a criação de Indice para performance da consulta SQL
Não utilize *, informe os campos que deseja carregar
Utilize o between no lugar do >= e <=
Conforme abaixo:
Select campo1, campo2, campo3 from tdcupant
INNER JOIN finafim ON
(tdcupant.numcupom = finafim.numcup and
tdcupant.impcaixa = finafim.impcaixa and
tdcupant.dtcompra = finafim.dtcomp)
where dtcompra between :inicio and :fim
order by dtcompra, hora
Não utilize *, informe os campos que deseja carregar
Utilize o between no lugar do >= e <=
Conforme abaixo:
Select campo1, campo2, campo3 from tdcupant
INNER JOIN finafim ON
(tdcupant.numcupom = finafim.numcup and
tdcupant.impcaixa = finafim.impcaixa and
tdcupant.dtcompra = finafim.dtcomp)
where dtcompra between :inicio and :fim
order by dtcompra, hora
GOSTEI 0