Lentezza utilizzo BE mdb multipli su rete LAN

di il
5 risposte

Lentezza utilizzo BE mdb multipli su rete LAN

Ciao a tutti,
con un progetto sviluppato in Access 2003, front-end mde che si collega a più Back-end mdb su LAN aziendale, sto riscontrando una lentezza insostenibile nell'utilizzo dell'applicativo. In pratica le query sono lentissime.
Ho letto questa discussione: https://www.iprogrammatori.it/forum-programmazione/access/access-lento-lan-t48946.html#p8685080 ma il link di accessgroup non è più disponibile per poter scaricare l'esempio e fare dei test.
E' possibile recuperare l'esempio da un altro sito?
Il fatto è che un altro progetto, sviluppato nella stesso identico modo, con il back-end situato nello stesso server e stesso percorso (cambia solo la cartella che contiene il file mdb) funziona benissimo con una velocità quasi pari a quella riscontrabile se mi collego al back-end di test che ho in locale.
L'unica differenza tra i due progetti, almeno credo, è che il FE mde veloce si collega ad un unico BE mdb con poche tabelle, il FE mde lento si collega a più BE mdb, 15 per la precisione, con 176 tabelle collegate.
In entrambi i progetti, all'avvio viene aperta una maschera nascosta che ha l'origine record impostato con una tabella collegata e relazionata, in modo da mantenere aperto il BE. Ho inoltre indicizzato tutti i campi con join, i campi chiavi esterne e che sono oggetto di filtro.
Le query sono quasi tutte di selezione, niente di complesso, pochissime sono di raggruppamento, ho evitato dove possibile di utilizzare IFF, trim ecc..
Le relazioni tra le tabelle dei vari BE sono tutte uno a molti, l'opzione "Aggiorna campi correlati a catena" del join è deselezionata, mentre "Applica integrità referenziale" e "Elimina record correlati a catena" sono selezionate.
Qualcuno ha dei consigli/suggerimenti da darmi per velocizzare il FE lento?
Grazie a tutti.

5 Risposte

  • Re: Lentezza utilizzo BE mdb multipli su rete LAN

    Quel demo, magari lo metto disponibile sul mio OneDrive personale dal momebto che lo feci io, ma quando avrò tempo.

    In ogni caso quello è solo una piccola parte dei problemi... vale a dire se hai sviluppato bene puoi ottenere qualche miglioramento con quel sistema.

    Se tuttavia hai commesso i classici errori tecnici nello strutturare il sistema beh... devi riflettere prima sulle cose di base.

    TABELLE
    Ben strutturate nel rispetto della Normalizzazione base, con PK, FK ed Indici.

    QUERIES
    nefficienti, e solo questo richiederebbe sapere e capire come non si scrivono query malfatte... con riferimenti impliciti nel predicto SQL oppure criteri inutili che poi valorizzi con il jolly... assenza di indici nelle tabelle.. ecc...
    Le queries le scrivono tutti... ma da lì acapire se sono ottimizzate ne passa tanta di acqua.
    A prescindere dall'esperienza si usa il tool di analisi dei piani di esecuzione per capire quanti giri fa una query per ogni record... AND e OR ad esempio provocano 2 risultati differenti... ecc..

    FORMS
    Non si riempiono di controlli DataBound...
    Non si mettono 35 subform con 45 subsubform...

    VBA
    Questo sconosciuto... chi ha poca esperienza non capisce quando ha senso scrivere codice e quando no... enscrive cose inutili.

    Ecc...
  • Re: Lentezza utilizzo BE mdb multipli su rete LAN

    Grazie Alex per la risposta.
    Per le forms ho cercato di applicare tutti gli accorgimenti da me conosciuti per ottimizzarle, tutte le forms di inserimento e modifica dei record sono unbound, i controlli vengono compilati tramite codice con una funzione dedicata al caricamento della maschera, poi tramite un pulsante "salva" viene effettivamente salvato o modificato il record nella tabella.
    Ho evitato di sovrapporre le eventuali caselle di testo nascoste presenti nella maschera.
    Se ho la necessità di avere più subform in una maschera, raramente sono più di due, cerco di gestirle con un controllo scheda, in modo da visualizzare e caricare i dati della subform solo all'evento modifica, quando seleziono la scheda.
    Controllando le query ho notato che su quasi tutte ho impostato un criterio di ordinamento crescente, non ci avevo mai fatto caso.
    Proverò a rimuovere il criterio di ordinamento su tutte le query, domani in ufficio proverò a fare dei test.
    Se su qualche maschera o report ho la necessità di ordinare i record, proverò a gestire la cosa nella maschera, tramite OrderBy e OrderByOn.
    Controllerò di nuovo gli indici delle tabelle.
  • Re: Lentezza utilizzo BE mdb multipli su rete LAN

    Sicuramente le mie domande poco centrano con la risoluzione del problema, ma:
    Da quando hai questo problema?
    C e sempre stato oppure è peggiorato con il tempo?
    Hai provato ad accedere con una sola postazione e le altre disconnesse?

    Hai provato ad accedere direttamente con un frontend installato sul server, o con le maschere direttamente integrate nel database (intendo fai una copia della fonte dati e le importi).
    Quanto è diventato pesante il database?
    Hai degli allegati in qualche tabella.
    Hai provato a fare una copia vergine del database, popolarlo con pochi record e testarne i tempi di risposta?
    Anche perché, almeno secondo i miei standard, 176 tabelle iniziano ad essere un po tantine da gestire.
  • Re: Lentezza utilizzo BE mdb multipli su rete LAN

    Il criterio di ordinamento non c'entra i criteri sono la WHERE CONDITION.
    Le form con Access devono essere bound per sfruttare Access, sono i controlli DaraBound come le Combo/Listbox che qualcuno carica con migliaia di dati da evitare...
    Una visualizzazione Master/Detail è normale...

    Le QUERY scritte così sono assurde:
    
    SELECT * FTOM T1
    WHERE IIF(IsNull(FORMS!Nomefor!nomeControllo1);'*';FORMS!NomeForm!NomeControllo1) AND
    IIF(IsNull(FORMS!Nomefor!nomeControllo2);'*';FORMS!NomeForm!NomeControllo2) AND
    ECC...
    
    Buon lavoro
  • Re: Lentezza utilizzo BE mdb multipli su rete LAN

    fratac ha scritto:


    Sicuramente le mie domande poco centrano con la risoluzione del problema, ma:
    Da quando hai questo problema?
    C e sempre stato oppure è peggiorato con il tempo?
    Hai provato ad accedere con una sola postazione e le altre disconnesse?

    Hai provato ad accedere direttamente con un frontend installato sul server, o con le maschere direttamente integrate nel database (intendo fai una copia della fonte dati e le importi).
    Quanto è diventato pesante il database?
    Hai degli allegati in qualche tabella.
    Hai provato a fare una copia vergine del database, popolarlo con pochi record e testarne i tempi di risposta?
    Anche perché, almeno secondo i miei standard, 176 tabelle iniziano ad essere un po tantine da gestire.
    Ciao fratac,
    il problema è sempre stato presente, nel senso che il FE diventa lento se utilizzato in una sede periferica, dove il collegamento al server è più lento, rispetto alla sede centrale. I colleghi che utilizzano l'applicativo hanno sempre inserito i dati presso la sede centrale, quindi il problema della lentezza non è così grave. Vorrei però rendere il FE sempre utilizzabile, anche nelle sedi periferiche, dove l'accesso al percorso dove risiedono i BE è più lento, credo volutamente.
    Il n. di dati elaborati sono veramente bassi, la tabella che ha più record arriverà forse a 20000 righe.
    Se apro un BE direttamente dalla cartella dove risiede, Access ci impiega un bel pò per aprirlo, quindi credo che una bella fetta di colpa ce l'abbia la rete, ripeto volutamente castrata per scelte aziendali.

    Oggi, dopo ripetuti test riguardanti modifiche sugli indici e query, tutti infruttuosi, ho ripreso in mano la seguente funzione:
    Declare Function GetShortPathName Lib "kernel32" _
                Alias "GetShortPathNameA" (ByVal lpszLongPath As String, _
               ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
    
    Function RefreshLinks()
        On Error GoTo ErrorHandler
        
        'Define the ADOX Catalog object.
        Dim objCat As New ADOX.Catalog
        'Define the ADOX Table object.
        Dim objTbl As ADOX.Table
    
        'Database name of the linked table.
        Dim strFilename As String
        'Path and database name of the linked table.
        Dim strFullName As String
    
        Dim blnIsMapi As Boolean
        Dim blnIsImex As Boolean
        Dim blnIsTemp As Boolean
        Dim blnLongFileName As Boolean
        Dim blnFailedLink As Boolean
        Const srtImex = "IMEX"
        Const strMapi = "MAPILEVEL="
        
        'Open the catalog.
        objCat.ActiveConnection = CurrentProject.Connection
    
        'Loop through the table collection and update the linked tables.
        For Each objTbl In objCat.Tables
            'Verify that the table is a linked table.
            If objTbl.Type = "LINK" = True Then
                blnIsTemp = objTbl.Properties("Temporary Table") Or Left(objTbl.Name, 1) = "~"
                blnIsImex = (InStr(1, objTbl.Properties("Jet OLEDB:Link Provider String"), srtImex, vbTextCompare) > 0)
                blnIsMapi = (InStr(1, objTbl.Properties("Jet OLEDB:Link Provider String"), strMapi, vbTextCompare) > 0)
    
                If Not blnIsTemp And Not blnIsImex And Not blnIsMapi Then
                    'Verify that the table is a Jet table.
                    strFullName = objTbl.Properties("Jet OLEDB:Link Datasource")
                    strFilename = Mid(strFullName, InStrRev(strFullName, "\", _
                                Len(strFullName)) + 1, Len(strFullName))
                    'Determine whether the database exists.
                    If DoesFileExist(strFullName) = True Then
                        objTbl.Properties("Jet OLEDB:Link Datasource") = GetShortName(strFullName)
                    'Update the link by using the short path name.
                    Else
                        MsgBox "Cannot update: '" & objTbl.Name & "'" & String(2, vbCrLf) & "File not found: " & vbCrLf & strFullName
                        blnFailedLink = True
                        Exit For
                    End If
                    If InStr(strFilename, ".") > 9 Then blnLongFileName = True
                End If
            End If
        Next
       
        If blnFailedLink = False Then
            If blnLongFileName = True Then
                MsgBox "The table links were successfully updated, but the name of the backend database file does not follow 8.3" & _
                vbCrLf & "Please rename the file, relink the tables, and then run the procedure again.", vbExclamation
            Else
                MsgBox "The links were successfully updated!!! ", vbInformation
            End If
        Else
            MsgBox "The links were not successfully updated." & vbCrLf & "Please verify you table links.", vbExclamation
        End If
    
    ExitHandler:
         Exit Function
    
    ErrorHandler:
        MsgBox Err.Description & " " & Err.Number
        Resume ExitHandler
        
    End Function
    Function GetShortName(ByVal sLongFileName As String) As String
               Dim lRetVal As Long, sShortPathName As String, iLen As Integer
               'Set up a buffer area for the API function call return.
               sShortPathName = Space(255)
               iLen = Len(sShortPathName)
        
               'Call the function.
               lRetVal = GetShortPathName(sLongFileName, sShortPathName, iLen)
               'Remove unwanted characters.
               GetShortName = Left(sShortPathName, lRetVal)
     End Function
    
    Function DoesFileExist(strFileSpec As String) As Boolean
        'Return True if the file that is specified in the
        'strFilespec argument exists.
        'Return False if strFileSpec is not a valid
        'file or if strFileSpec is a directory.
        Const INVALID_ARGUMENT As Long = 53
        On Error GoTo DoesfileExist_Err
        If (GetAttr(strFileSpec) And vbDirectory) <> vbDirectory Then
            DoesFileExist = CBool(Len(Dir(strFileSpec)) > 0)
        Else
            DoesFileExist = False
        End If
    DoesfileExist_End:
        Exit Function
    DoesfileExist_Err:
        DoesFileExist = False
        Resume DoesfileExist_End
    End Function
    Il codice fa parte di un articolo pubblicato sul sito della Microsoft, il link originale non riesco più a trovarlo, ma ho trovato questo link: https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/891176
    Nel codice postato io ho solo aggiunto l'exit for, per non avere un messaggio per ogni tabella collegata.
    Ho aggiornato i link delle tabelle collegate con la funzione RefreshLinks e magicamente il FE gira veloce come fosse collegato ai BE in locale. Tempo fa avevo già provato ad utilizzare questa procedura, infatti tutti i BE hanno un nome lungo al massimo 8 caratteri, ma mi ero accorto che non sempre venivano aggiornati i percorsi delle tabelle e avevo lasciato perdere, anche perchè non conosco ADO, ho sempre utilizzato DAO. Oggi però mi sono reso conto che la procedura funziona quando viene effettivamente cambiato il percorso del BE durante il relink delle tabelle, se la utilizzo senza cambiare il percorso, a volte non funziona. Inoltre al lavoro utilizziamo tutti Windows 10 e avevo ritenuto l'articolo vecchio e valido solo per XP e Windows 2000, roba ormai preistorica. Eppure funziona, forse perchè utilizzo ancora Access 2003.
    Devo ancora fare ulteriori test, soprattutto a casa e con un pc diverso da quello che utilizzo in ufficio, tuttavia oggi in ufficio sono rimasto sbalordito dalla velocità del FE.
    L'apertura del FE rimane comunque lenta, la maschera nascosta, che serve per mantenere i BE sempre aperti, ci impiega quasi 30 secondi ad aprirsi, poi il FE acquista velocità.
    Anche la procedura del relink delle tabelle collegate rimane molto lenta, per questo sono costretto a non rimuovere le tabelle collegate alla chiusura del FE, come invece si dovrebbe fare.
    Preciso che non posso modificare i nomi delle cartelle del percorso dove risiedono i BE, causa restrizioni imposte dall'azienda.
    I pc che utilizziamo sono praticamente blindati.
    Spero di aver risolto il problema con questa funzione.
Devi accedere o registrarti per scrivere nel forum
5 risposte