CONSULTA SQL MUITO LENTA NA REDE

ANDRESNOXI 08/01/2014 22:51:17
#432836
Olá!

Tenho numa pequena rede um micro que funciona como servidor. Nele encontra-se um banco de dados de CEP.

Uso VB6 com ADO.

Preencho uma ComboBox com todas UFs (estados) e, ao selecionar determinado estado, outra ComboBox é carregada com as cidades desse estado.

Quando a consulta é realizada no micro do BD tudo é rápido, mas quando é realizada noutro micro, demora muito pra carregar o ComboBox com as cidades.

Existe como otimizar o código abaixo?


      Dim strCaminhoBD As String
Dim con As ADODB.Connection
Dim rs As ADODB.Recordset

Set con = New ADODB.Connection

[ô] strCaminhoBD é o local do BD na rede
con.Open [Ô]Provider=Microsoft.Jet.OLEDB.4.0;[Ô] & [Ô]Data Source=[Ô] & strCaminhoBD
Set rs = New ADODB.Recordset

rs.Open [Ô]SELECT DISTINCT Cidade FROM TabCEP WHERE UF=[ô][Ô] & strUF & [Ô][ô][Ô], con, adOpenKeyset, adLockReadOnly

Do While Not rs.EOF
cbo.AddItem rs.Fields([Ô]Cidade[Ô])
rs.MoveNext
Loop

rs.Close
Set rs = Nothing
con.Close
Set con = Nothing
FILMAN 09/01/2014 00:33:48
#432839
Coloque na sua string de conexão o seguinte parâmetro a mais

con.CursorLocation = adUseClient
con.Open [Ô]Provider=Microsoft.Jet.OLEDB.4.0;Data Source=[Ô] & strCaminhoBD & [Ô];Persist Security Info=False[Ô]

Outra coisa na tabela que esta sendo consultada exclua os itens duplicados

veja se dá certo e optimiza o desempenho
ANDRESNOXI 09/01/2014 08:18:08
#432840
Filman:
Obrigado pela ajuda, mas (sou novato) qual a diferença entre:
con.CursorLocation = adUseClient
con.CursorLocation = adUseServer

Quando usar cada um deles? E no meu código, qual é o mais rápido?
ANDRESNOXI 09/01/2014 08:32:50
#432844
No site http://www.macoratti.net/ado_fast.htm encontrei:

Citação:

[Ô]Se você não precisa fazer atualizações nem se mover para frente e para trás em seu Recordset , não tenha dúvidas utilize o padrão ADO : adUseServer , adOPenForwardOnly e adLockReadOnly. Isto lhe dará um melhor desempenho.

Se você precisar se mover por todo o seu Recordset , o cenário muda , prefira usar o Cursor do lado do cliente - adUseClient , e neste caso utilize adLockReadOnly como tipo de bloqueio (a não ser que você realmente precisa de outro tipo de bloqueio).

Já se você precisar de um Recordset atualizável o Cursor do lado do cliente - adUseClient - irá onerar mais o seu sistema. Utilize AdUseServer.[Ô]



Fala do Recordset. é válido para o Connection (con.CursorLocation)???
MARCELO.TREZE 09/01/2014 09:06:16
#432848
Resposta escolhida
Andresnoxi veja bem um solução praticamente definitiva para o seu problema

A consulta é rápida, a conexão com o banco que é um pouco mais demorada, e pelo que vejo você quando vai fazer a consulta realiza a conexão na hora, isso toma um pouco de tempo.

qual o ideal, o ideal é você fazer a conexão ao abrir seu programa, e mante-lo conectado e fechar somente quando sair do programa.

bom esta parte do seu código:

 Dim con As ADODB.Connection
Set con = New ADODB.Connection

[ô] strCaminhoBD é o local do BD na rede
con.Open [Ô]Provider=Microsoft.Jet.OLEDB.4.0;[Ô] & [Ô]Data Source=[Ô] & strCaminhoBD


pode ser posta em um módulo com uma função chamada de CONECTAR, depois é só chamar a função no load e um load do form principal.

veja a pequena alteração sugerida

em um módulo cole:

Global con As ADODB.Connection

Public Function Conectar(valor As Boolean)
If valor = True Then
If con.State = 1 Then Con.Close[txt-color=#007100] [ô] aqui é verificado se a conexão ja está aberta para evitar erro[/txt-color]
con.CursorLocation = adUseClient
con.Open = [Ô]Provider=Microsoft.Jet.OLEDB.4.0;Data Source=[Ô] & strCaminhoBD & [Ô];Persist Security Info=False[Ô]
Else
Con.Close
End If


End Function


com o modulo acima fica mais fácil de você usar seu programa, basta que você no load do form principal, ou pode ser no load do form de consulta mesmo, coloque

Conectar True


depois na sua consulta basta declarar o recordset assim

Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset

rs.Open [Ô]SELECT DISTINCT Cidade FROM TabCEP WHERE UF=[ô][Ô] & strUF & [Ô][ô][Ô], con, adOpenKeyset, adLockReadOnly

Do While Not rs.EOF
cbo.AddItem rs.Fields([Ô]Cidade[Ô])
rs.MoveNext
Loop


a consulta ficara rapida.

lembre-se apenas de fechar a conexão ao sair do form

ou seja no Unload do form coloque

Conecta False


teste ai e diga como ficou





ANDRESNOXI 09/01/2014 12:06:17
#432871
Oi, Marcelo:

Obrigado pela dica. Realmente, acho que funcionará.

Mas eu tenho 3 BDs a conectar. é possível assim?
Ou seja, 3 funções diferentes, uma pra cada BD?
Posso abri-las simultaneamente ao carregar o form?
Como o BD de CEP é grande, e os outros também serão após receber os dados, isso não pesará no desempenho geral do sistema? ou a conexão funciona como um link que não tem peso significativo?
O peso da conexão pode variar de acordo com o tamanho do BD?

Como veem, estou cheio de dúvidas (aprendendo a cada resposta de vocês) - Obrigado!
MARCELO.TREZE 09/01/2014 20:29:09
#432878
você pode fazer tres funções diferentes, a conexão com o banco não vai ser afetada pelo seu tamanho, porém ai sim poderá afetar o desempenho da consulta, mas não tanto quanto abrir a conexão na consulta.
ANDRESNOXI 11/01/2014 14:44:55
#432940
Marcelo:

Obrigadíssimo!!! Mudei em todo programa e ficou muito mais rápido em diversos pontos.

Mas quando é no BD de CEP (o maior!), mesmo com algumas alterações que trouxeram melhorias, continua lento quando na rede:
[txt-size=3]
     
Dim fldCidade
Dim rs As ADODB.Recordset


Set rs = New ADODB.Recordset

rs.Open [Ô]SELECT DISTINCT Cidade FROM TabCEP WHERE UF=[ô][Ô] & strUF & [Ô][ô][Ô], con, adUseServer, adOpenKeyset, adLockReadOnly [ô]


Set fldCidade = rs.Fields([Ô]Cidade[Ô])

While Not rs.EOF
cbo.AddItem fldCidade
rs.MoveNext
Wend
[/txt-size]
Existe como otimizar essa consulta na rede? Pois dura cerca de 30 segs para carregar o cbo.

Obrigado.
MARCELO.TREZE 11/01/2014 17:34:51
#432943
Faça um teste

isto

rs.Open [Ô]SELECT DISTINCT Cidade FROM TabCEP WHERE UF=[ô][Ô] & strUF & [Ô][ô][Ô], con, adUseServer, adOpenKeyset


por isto

rs.Open [Ô]SELECT DISTINCT Cidade FROM TabCEP WHERE UF=[ô][Ô] & strUF & [Ô][ô][Ô], con, adOpenKeyset, adLockBatchOptimistic
NILSONTRES 11/01/2014 19:44:34
#432945
Veja a possibilidade de trabalhar consultando o site dos correios através de um web browser, alem de vc não precisar
de uma base enorme, ainda tem consultas mais precisas, pois essas bases alteram sempre.
Em vb.net sei que da, em vb6 não sei, mas basta vc identificar os nomes dos controles nas paginas do correios, carrega seus valores nessa pagina, e da o comando no botão da pagina, em seguida recupera a resposta para seu sistema.
ANDRESNOXI 11/01/2014 20:06:03
#432946
Marcelo:

Desta vez deu errado no meu programa:

resultou
erro número: -2147217900
descrição: Expected query name after EXECUTE

Pesquisei no Google, mas não encontrei como associar os possíveis motivos do erro a alteração realizada.
Página 1 de 2 [12 registro(s)]
Tópico encerrado , respostas não são mais permitidas