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.