Clipper On Line • Ver Tópico - Otimizando SQL/etc

Otimizando SQL/etc

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

 

Otimizando SQL/etc

Mensagempor JoséQuintas » 28 Nov 2019 08:29

Uma coisa que tem gente que não entendeu: SQL é pra otimizar, não só pra trazer informação.
E quanto menos informação, mais rápido
Em DBF:

USE pedido
nTotal := 0
DO WHILE ! Eof()
   IF pedido->DatEmissao < dDatIni
      SKIP
      LOOP
   ENDIF
   IF pedido->DatEmissao > dDatFim
      SKIP
      LOOP
   ENDIF
   IF pedido->Cliente != mCliente
      SKIP
      LOOP
   ENDIF
   nTotal += pedido->Valor
   SKIP
ENDDO


Mesmo em DBF, o fonte acima poderia ser trocado para:

SUM pedido->Valor TO nTotal FOR .NOT. ( pedido->DatEmissao < dDatIni .OR. pedido->DatEmissao > dDatFim ) ;
   .AND. pedido->Cliente = mCliente


Em DBF isso pode ser um LIXO, pode ser mais demorado, mas.... a opção existe.

Em SQL devemos considerar quanta informação vém pela rede.
Trazer o mês inteiro de informação pra obter a soma.... isso é idiotice... isso é coisa de DBF.

Vamos as formas idiotas de fazer isso no SQL:

SELECT * FROM pedido


Esta é a forma mais idiota de todas. Pra que trazer TUDO? E isto é exatamente o que acontece com DBF

SELECT datEmissao, Cliente, Valor FROM pedido


Esta forma é um pouco menos idiota, trás só os campos que precisa

SELECT datEmissao, Valor FROM pedido WHERE Cliente = '12345'


Esta forma é um pouco menos idiota, trás só a informação do cliente

SELECT Valor FROM pedido WHERE cliente = '12345' AND DatEmissao BETWEEN '2019-10-01' AND '2019-10-31'


Esta forma é um pouco menos idiota, trás só os pedidos que interessam

SELECT SUM( VALOR ) FROM pedido WHERE cliente = '12345' AND DatEmissao BETWEEN '2019-10-01' AND '2019-10-31'


Esta seria a forma correta. trás pela rede apenas o valor total, que é o quer interessa, e vai ser digamos... 16 bytes pela rede (ou conexão), algo instantâneo.

Tem programador que não entende isso.
NÃO tem que trazer tudo pra processar local, pede pronto que o servidor manda pronto.

O servidor não é apenas pra guardar a base de dados, ele pode trabalhar.
Para o servidor a base é local, todo processamento é local, então o servidor vai trabalhar rápido.
Ainda mais se a conexão for lenta.... quanto menos informação vier, mais rápido vai chegar.

Se vai emitir uma listagem de pedidos, com números e valores, pede só os números e os valores, não precisa da informação completa dos pedidos.

Até mesmo um simples browse...
Por um lado, o browse do DBF trás somente os registros que cabem na tela.... parece bom
Por outro lado, pra fazer isso, vém o registro completo SEMPRE.

Digamos que o DBF tem 1000 campos de 10 caracteres, vai fazer um browse de 2 campos, 30 registros por vez...
Em DBF, para UMA PÁGINA do browse, vai trazer 300.000 caracteres
Em SQL, solicitando apenas os 2 campos, vão ser 600 caracteres para a mesma informação.
Ou seja... o tempo de rede que o DBF usa pra uma única página desse browse, é o mesmo do SQL pra trazer 500 páginas !!!

Achou exagerado? trazer 500 vezes mais informação no mesmo tempo?

Vamos a outro exemplo:
O DBF é acessado registro a registro, o registro completo SEMPRE. Com filtro, mesmo os registros filtrados são acessados, pra analisar se entram ou não no "browse".
Usando o mesmo exemplo: 1000 campos com 10 caracteres, vai filtrar 1 registro em cada 10, mostrar 2 campos na tela, 30 registros por vez.
Uma única tela teria processado 300 registros x 10.000 caracteres = 3 milhões de caracteres por tela.
Em SQL: 30 registros x 20 caracteres = 600 caracteres por tela
Dá pra trazer 5.000 páginas de browse, no tempo que o DBF demoraria pra trazer uma única página.

Tudo bem, é um exemplo exagerado, mas... nem está sendo considerada a pesquisa de DBF + CDX, ou um possível relacionamento com outros arquivos, ou outras coisas mais. Seria mais informação ainda pra DBF, que no SQL pode vir pronto.

No final das contas: dá pra agilizar DBF? sim... é acessar o mínimo de informação possível, usando índices pra isso, que é o recurso disponível pra DBF.
NÃO é criar índice na hora do processamento, é o índice já existir e tirar proveito dele.

Por exemplo, relatório de produtos em ordem de data....
Pode ter um índice por produtos + data
Ao começar a imprimir o produto: SEEK produto + datainicial SOFTSEEK
Terminou o produto, por exemplo, SEEK ( produto + 1 ) SOFTSEEK
Com essas duas pesquisas, vai pular todas as datas que não interessam.

E por aí vai... cada situação uma solução, ou um índice que pode agilizar.
SET FILTER nem pensar...
SKIP;LOOP.... de certa forma, idem...
Nos dois casos, mesmo que não use, vai estar trazendo o registro completo pela rede.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18007
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Otimizando SQL/etc

Mensagempor JoséQuintas » 28 Nov 2019 08:39

Voltando ao primeiro exemplo...
Se tem índice por cliente + data

SEEK mcliente + Dtos( ddatainicial ) SOFTSEEK
SUM VALOR TO nTotal WHILE cliente == mcliente .AND. data <= dDataFinal


Qual a agilização?
Vai trabalhar somente com os pedidos do cliente, com data no intervalo solicitado.
Os outros registros nem vão ser lidos, e não vão passar pela rede.
Se tiver um único pedido... vai ser instantâneo, mesmo com milhões de registros no arquivo
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18007
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Otimizando SQL/etc

Mensagempor JoséQuintas » 28 Nov 2019 08:49

E se fosse o total por cliente? uma combinação desse com agilizações:

DO WHILE ! Eof()
   mCliente := pedido->cliente
   SEEK mCliente + Dtos( dDataInicial ) SOFTSEEK
   SUM VALOR TO nTotal WHILE cliente==mCliente .AND. Data <= dDataFinal
   ? mCliente, nTotal
   SEEK ( mCliente + 1 ) SOFTSEEK
ENDDO


Qual a agilização?
Vai pular tudo que não interessa, de todos os clientes.
Isso significa que não vém lixo pela rede, só vém o que interessa.

Nota: é só um exemplo, lógico que o código do cliente precisaria StrZero() ou algo assim, mas é só pra passar a idéia, não o fonte pronto.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18007
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Otimizando SQL/etc

Mensagempor JoséQuintas » 28 Nov 2019 10:02

Nesse exemplo... e se fosse em ordem alfabética?

Provavelmente melhor criar um temporário (array ou não), contendo esse resultado, depois pegar o nome dos clientes e colocar em ordem alfabética.
Vai trabalhar só com a movimentação que existe, depois vai pegar só o nome dos clientes que tem movimentação, e só depois coloca em ordem alfabética.
Se fizer o caminho contrário, relacionar clientes por exemplo, só vai poluir mais ainda a rede com lixo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18007
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes




Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 20 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro