Velocizzare SUB Routine

di il
7 risposte

Velocizzare SUB Routine

Ciao a tutti.
Premesso che nella vita non utilizzo Access ma insegno il suo uso basilare, infatti faccio il docente di informatica.

Il problema:
Un caro amico mi ha chiesto di creare una qualcosa che:
1) legge un peso da una tabella (CHPLIB_STATSPED!TTPES)
2) lo compara con un range di peso in una seconda tabella (Fasce_Pesi!Peso_DA & Fasce_Pesi!Peso_A)
3) quando ha trovato il range prende un valore dalla tabella e lo scrive nella prima tabella (CHPLIB_STATSPED!FASCIA = Fasce_Pesi!Fascia)

Spulciando sulla rete ho trovato qualcosa che ho "accrocchiato" così:
'###############################################
Option Compare Database

Sub showQueryData()

Dim db As dao.Database
Dim rs As dao.Recordset
Dim rs1 As dao.Recordset
Dim rs2 As dao.Recordset
Dim sqlStr As String

Set db = CurrentDb

sqlStr = "SELECT * FROM CHPLIB_STATSPED"
Set rs = db.OpenRecordset(sqlStr)

sqlStr1 = "SELECT COUNT(*) FROM Fasce_Pesi"
Set rs1 = db.OpenRecordset(sqlStr1)
RecordCount = rs1.Fields(0)

sqlStr2 = "SELECT * FROM Fasce_Pesi"
Set rs2 = db.OpenRecordset(sqlStr2)

'
' rs.MoveFirst

  ' Do While Not rs.EOF
  ' MsgBox ("FASCIA " & rs!FASCIA & "  = Peso DA : " & rs!Peso_DA & " a Peso : " & rs!Peso_A)
  ' rs.MoveNext
' Loop

' MsgBox ("Fine Tabella Fasce_Prezzi")

rs.MoveLast
rs.MoveFirst

Do While Not rs.EOF
    
rs2.MoveLast
rs2.MoveFirst

RecordKey = rs!TTPRG

    For a_counter = 1 To RecordCount
    
        If (rs!TTPES >= rs2!Peso_DA And rs!TTPES <= rs2!Peso_A) Then
            FASCIA = rs2!FASCIA
        Else
            rs2.MoveNext
        End If
        
    Next a_counter
   
    ' Msg = "PESO " & rs!TTPES & vbCrLf _
          & "FASCIA " & FASCIA & vbCrLf _
            & " Continuo?"
    ' Msg_2 = "PESO " & rs!TTPES & " FASCIA " & FASCIA & " --> RecordKey = " & RecordKey
    
    Sql2 = "UPDATE CHPLIB_STATSPED SET FASCIA = '" & FASCIA & _
    "' WHERE TTPRG = " & RecordKey & ";"

    ' DoCmd.RunSQL Sql2, 0
    
    CurrentDb.Execute Sql2
     
    ' Style = vbYesNo + vbCritical + vbDefaultButton2
    ' Title = "MsgBox Demonstration"
    
    ' Response = MsgBox(Msg, Style, Title)
    
    ' If Response = vbYes Then
        
        ' Debug.Print Sql2
        
        rs.MoveNext
    ' Else
    '    Exit Do
    ' End If

Loop

MsgBox ("End of Table")
End Sub
'############################################################

Funzionare, funziona solo che su 1.047.000 record ci mette una vita.
Come posso modificare il tutto per renderlo più veloce?

Grazie inanticipo.
Max

7 Risposte

  • Re: Velocizzare SUB Routine

    A parte indicarti di usare i TAG per il Codice... è uno dei BUTTON sopra l'arera dell'Editor..., credo che potresti partire con lo spiegare cosa devi fare... magari capendo il fine si trova un metodo migliore...
  • Re: Velocizzare SUB Routine

    Deve fare solo questo:
    1) legge un campo in una tabella
    2) lo compara con un due campi in una seconda tabella
    3) quando ha trovato il corrispondente campo prende un valore dalla seconda tabella e lo scrive nella prima tabella

    Il problema è il numero dei record.

    Max
  • Re: Velocizzare SUB Routine

    In che senso il numero di record?

    Nel senso che se ci sono TANTI record nella SECONDA tabella (su cui fare la ricerca), il sistema e' lento?

    Attenzione, con TANTI intendo decine o centinaia DI MIGLIAIA NON decine o centinaia!

    Ovviamente, il numero di record nella tabella da scandire non e' un problema, nel senso che se la devi scandire sequenzialmente, non puoi ridurre i tempi:

    se sta T secondi per N record, stara' 2*T secondi per 2*N record!
  • Re: Velocizzare SUB Routine

    Il numero dei record (1.276.105) risiede sulla prima tabella (quella da aggiornare)
    Nella seconda tabella ci saranno 20/25 record.

    Per elaborare il tutto con la routine che ho fatto io (NON OTTIMIZZATA) ci metterebbe una settimana
    ipotizzando un secondo a elaborazione.

    Max
  • Re: Velocizzare SUB Routine

    Se fai una Query con l'autocompisizione di RICERCA DATI NON CORRISPONDENTI...? Ovviamente poi prendi gli altri... i NOT IN...
    Ottieni SOLO quelli che ti servono dovrebbe essere più semplice.

    Poi, questa non serve a NULLA
    
    sqlStr1 = "SELECT COUNT(*) FROM Fasce_Pesi"
    Nel momento in cui apri il secondo RS sai già quanti Record ci sono...
    
    sqlStr2 = "SELECT * FROM Fasce_Pesi"
    Set rs2 = db.OpenRecordset(sqlStr2)
    I Cicli sui Recordset poi si fanno iterando sui Record direttamente...

    Sincertamente non ho capito nulla di più...
  • Re: Velocizzare SUB Routine

    Il modo standard per rendere efficiente un'operazione e' quella di NON ESEGUIRE OPERAZIONI INUTILI.

    Quindi, la soluzione dipende: a te servono fin da subito TUTTI i 1.300.000 valori, oppure solo alcuni?

    Se te ne servono solo alcuni, allora implementa il codice che estrae il valore solo nel momento in cui tale valore serve.

    Altro metodo standard per rendere efficiente un'operazione e': MAI FARE DUE (o piu') VOLTE LA STESSA OPERAZIONE.

    Quindi, una volta calcolato il valore, se viene usato in continuazione, salvalo da qualche parte.

    Naturalmente, il termine in continuazione va inteso in modo intelligente: se lo usi una volta al giorno, non servono ottimizzazioni, ma se lo usi 100 volte al secondo, allora conviene farci un pensierino.

    Queste strategie sono generali.

    Nota: un secondo ad elaborazione?

    Se intendi, un secondo per record della tabella da 1.300.000 record, c'e' qualcosa di concettualmente sbagliato nel tuo codice!

    In un secondo dovrebbe macinare decine di migliaia di record!
  • Re: Velocizzare SUB Routine

    Purtroppo servono tutti i record.
    Comunque ho provato a far girare la routine e come tempo di esecuzione su tutti i record siamo nell'ordine di 45/50 minuti.
    Fortunatamente non deve girare ogni minuto ma penso una/due volte al giorno.
    Purtroppo non posso salvare nessun valore perchè varia da record a record.

    Per il momento va bene così, grazie a tutti.
Devi accedere o registrarti per scrivere nel forum
7 risposte