IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Access Discussion :

Base access se fragmente de facon incontrolable


Sujet :

Access

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut Base access se fragmente de facon incontrolable
    une base access 2000 accedée en DAO 3.6 augmente de taille de facon exagerée si vous augmenter la taille d'un champ long binary.
    par exemple une base vide qui fait 136 ko au depart passe a 412436 ko
    avec un malheureux champ long binary de 80 ko !!!
    ce champ ayant éte genérer par 10000 boucles qui augmente a chaque passage le champ de 8 octets.
    Cette base passe a 216 ko apres compactage.
    ce probleme ne se pose pas avec une base access 97 sous DAO 3.51 !!

    un close du recordset n'arrange rien
    le seul moyen qu'acces utilise les "trous" est de redemarrer l'application
    A l'aide !! , je ne peut pas fermer mon application pour la compacter !!
    merci :

    exemple sous VB6: avec une table contenant un champ long binary "bin"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    Private rs As Recordset
    Private db As Database
    Private Sub Command1_Click()
      Dim tb() As Byte
      Dim i as long
      Dim l as long
      rs.MoveFirst
      For i = 0 To 9999
        If IsNull(rs!bin) Then
          ReDim tb(0 To 7)
          l = 8
        Else
          tb = rs!bin
          l = UBound(tb()) + 8
          ReDim Preserve tb(0 To l)
        End If
        rs.Edit
        rs!bin = tb   'ou  rs!bin.AppendChunk tb
        rs.Update
      Next i
      Label1.Caption = l \ 1024
      Command1.Enabled = True
    End Sub
     
    Private Sub Form_Load()
      Set db = DBEngine.Workspaces(0).OpenDatabase("MaBase.mdb")
      Set rs = db.OpenRecordset("T1")
    end Sub

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Bonjour,
    Citation Envoyé par stouri Voir le message
    une base access 2000 accedée en DAO 3.6 augmente de taille de facon exagerée si vous augmenter la taille d'un champ long binary.
    par exemple une base vide qui fait 136 ko au depart passe a 412436 ko
    avec un malheureux champ long binary de 80 ko !!!
    ce champ ayant éte genérer par 10000 boucles qui augmente a chaque passage le champ de 8 octets.
    Cette base passe a 216 ko apres compactage.
    ce probleme ne se pose pas avec une base access 97 sous DAO 3.51 !!

    un close du recordset n'arrange rien
    le seul moyen qu'acces utilise les "trous" est de redemarrer l'application
    A l'aide !! , je ne peut pas fermer mon application pour la compacter !!
    merci :
    J'entrevois 2 solutions, sans doute imparfaites:

    (1) réserver de la place pour de futurs ajouts, par exemple en dimensionnant ton tableau en prévision du besoin et en complétant l'enregistrement avec une information sur la taille des données réellement "utiles" (par exemple un champ qui donne la taille). Ainsi le AppendChunk écraserait bien la même page de données (au lieu d'en créer une nouvelle et d'invalider la précédente).

    (2) utiliser un champ de type Binay permettant de stocker une valeur binaire dont la taille n'excèderait pas 255 octets.
    (mais apparemment tu veux aller jusqu'à 8*10000 octets)

    ============
    L'exemple que tu donnes c'est bien JUSTE UN EXEMPLE, ou alors ça te sert vraiment ???
    Parce que, à part pour faire des tests, je ne vois pas à quoi ça peut servir...

    Pour aider à comprendre ce qui ne va pas...
    En fait plusieurs AppendChunk entre Edit/Update ne pose pas de Pb.
    C'est la succession des Edit/Appendchunk/Update sur le même enregistrement qui ne convient pas.
    _

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut ca ne marche pas !
    le simple fait de re ecrire le champ binaire sans en augmenter la taille, fait augmenter la taille de la base !

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Bon, je vais tester ton code, par curiosité...
    _

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut a propos de l'exemple
    l'exemple provient d'une application reelle que j'ai simplifié a l'extreme pour exposé le probleme.
    l' application tourne depuis 10 ans , mais depuis le passage au format access 2000, j'ai ce probleme.
    le client est obligé d' arreter la ligne de production pour relancer le programme !!

  6. #6
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    J'ai testé plein de trucs...

    La solution 1 qui consiste à prédimensionner le champ Long Binary apporte une amélioration.

    Sans "prédimensionner" le champ bin, la taille de la BD passe de 16 Ko à plus de 450 Mo !
    Effectivement, à la longue ça peut faire tomber ton serveur...
    Sans compter le temps de compactage.

    Si on "prédimensionne" le champ bin, la taille de la BD passe de 16 Ko à 96 Mo.

    Dans tous les cas, le compactage ramène la BD à 16 Mo. Donc, même en prédimensionnant, il y a encore du "déchet" !

    Je te donne mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    Public Sub RemplirBinaryBig()
        Dim oDB As DAO.Database, oWS As DAO.Workspace
        Dim tb(1000 * 8) As Byte
        Dim i As Long
        Dim j As Long
     
        Set oWS = DBEngine.Workspaces(0)
        Set oDB = oWS.Databases(0)
     
        oDB.Execute "DELETE FROM T_BIN"
     
        DBEngine.Idle dbForceOSFlush
     
        Set rs = oDB.OpenRecordset("T_BIN")
     
        ' on crée une ligne unique, avec le champ bin dimensionné à 8000 octets
        rs.AddNew
        rs!bin = tb
        rs.Update
     
        rs.MoveFirst
        For i = 0 To 9999
     
            ' 10.000 réécritures du champ bin
     
    '        If IsNull(rs!bin) Then
    '            ReDim tb(0 To 7)
    '            j = 8
    '        Else
    '            tb = rs!bin
    '            j = UBound(tb()) + 8
    '
    '            ReDim Preserve tb(0 To j)
    '        End If
     
            rs.Edit
            rs!bin = tb 'ou rs!bin.AppendChunk tb
            rs.Update
        Next i
     
        rs.Close
        Set oDB = Nothing
    End Sub

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut je teste
    merci

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut resultat
    la base augmente de 80 MO a chaque passage (80 mo =10000x8ko)
    chaque fois que l'on reecrit les 8ko , on augmente la taille de la base de 8ko !!

  9. #9
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    OK. Avec Access 2000/Jet4.0/DAO 3.6, la taille de la BD augmente très fort, même en prédimensionnant.

    Voci une dernière proposition que je viens de tester, avec succés:

    - les tables sont stockées dans une BD dorsale au format Jet 3.x.

    - l'application reste dans une BD frontale au format Access 2000 (Jet 4.0) et les tables de la dorsale sont liées.

    J'ai effectué un test d'écriture en boucle avec le principe du prédimensionnement (4 boucle, de 10000 écritures avec open/close sur le recordset à chaque écriture).

    Dans ces conditions, la taille de la table est constante.

    C'est peut être vrai aussi sans prédimensionner le champ bin, mais je te laisse le plaisir de le vérifier.
    _

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut c'est compliqué
    Help !

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut Si la base est au format acces97
    Si la base est au format acces97 ca marche aussi Mal
    le probleme vient du moteur JET 4.0 (DAO 3.6)
    Help !

  12. #12
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Bonjour,

    Si la base est au format Access 97, la modification d'enregistrements existants dont le champ "bin" est prédimensionné (c-à-d les conditions de mes tests) ne fait pas grossir la base.

    Dans mon cas, la BD contient seulement une table T_BIN, avec un seul champ nommé "bin". La table comprend 2 enregistrements.

    Voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    Public Sub RemplirBinaryBigSansAjout()
        Dim oDB As DAO.Database, oWS As DAO.Workspace
        Dim tb(1000 * 8) As Byte
        Dim i As Long, j As Long
        
        Set oWS = DBEngine.Workspaces(0)
        Set oDB = oWS.Databases(0)
        
        For i = 0 To 9999
                
            Set rs = oDB.OpenRecordset("T_BIN")
            
            rs.MoveFirst
            Do Until rs.EOF
                rs.Edit
                rs!bin = tb
                rs.Update
                
                rs.MoveNext
            Loop
    
            rs.Close
            
        Next i
        
        Set oDB = Nothing
    End Sub

  13. #13
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Pour compléter mon précédent message, je constate comme toi que la BD grossit si toutes les 1000 écritures sont réalisées dans le même recordset.

    Cf. le code ci-dessous:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    Public Sub RemplirBinaryBigSansAjout()
        Dim oDB As DAO.Database, oWS As DAO.Workspace
        Dim tb(1000 * 8) As Byte
        Dim i As Long, j As Long
        
        Set oWS = DBEngine.Workspaces(0)
        Set oDB = oWS.Databases(0)
        
        Set rs = oDB.OpenRecordset("T_BIN")
            
        For i = 0 To 9999
                
            rs.MoveFirst
            Do Until rs.EOF
                rs.Edit
                rs!bin = tb
                rs.Update
                
                rs.MoveNext
            Loop
            
        Next i
    
        rs.Close
        
        Set oDB = Nothing
    End Sub
    Ce n'était pas le cas dans le code de mon message précédent où le recordset est ouvert avant chaque écriture et refermé juste après... on ne parcourt pas le même recordset.

    Qu'en penses-tu ?
    _

  14. #14
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut je ne peut pas fermer la base !!
    si la base reste ouverte ,la taille monte a l'infini .
    (il suffit d'une instance database sur la base)
    je ne peut pas fermer ma base.
    (sinon je pourrais la compacter dans le code!!)

    Help !

  15. #15
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Citation Envoyé par stouri Voir le message
    si la base reste ouverte ,la taille monte a l'infini .
    (il suffit d'une instance database sur la base)
    A travers les tests, j'ai plutôt compris que le Pb de la taille se pose si on maintient ouvert le Recordset sur lesquel les écritures sont réalisées.

    Je ne vois pas le rapport avec la base ouverte...

    Merci de m'éclairer.
    _

  16. #16
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut reponse
    le probleme persiste:

    meme si on ferme la recordset
    meme si on ferme la base de donnée
    par contre , si il n'y a plus aucune instance de la base,
    la taille se stabilise
    dans mon exemple il suffit de mettre en commentaire le code de Form_Load

    Help !
    #####################################
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    ' Mybase.mdb
    ' avec une table nommée "T1"
    '  dans T1 , un champ long binary ( OLE)  nommé "bin"
    Private db As Database
    Private Sub Command1_Click()
      Dim tb(0 To 7999) As Byte
      Dim i As Long
      Dim rs As Recordset
      Dim db2 As Database
     
      Set db2 = DBEngine.Workspaces(0).OpenDatabase("mybase.mdb")
      Set rs = db2.OpenRecordset("T1")
     
      rs.MoveFirst
      For i = 0 To 9999
        rs.Edit
        rs!bin = tb  'ou  rs!bin.AppendChunk tb
        rs.Update
      Next i
     
      rs.Close
      db2.Close 
     
    End Sub
     
    Private Sub Form_Load()
      'on cree une premiere instance sur la base
      Set db = DBEngine.Workspaces(0).OpenDatabase("MyBase.mdb")
    End Sub
    #####################################

  17. #17
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Effectivement, tu as raison...

    On ne peut rien faire car c'est un problème inhérent à Jet depuis la version 3.x...

    Explication:
    Des pages particulières de la BD stockent les valeurs des champs qui contiennent de gros objets (Memo, BLOB, etc.).
    Quand un de ces champs est "vidé" (mis à Null) ou modifié (avec une nouvelle valeur), la page concernée est invalidée pour être ensuite recyclée.
    Le problème c'est que ce recyclage n'est pas réalisé si la BD est ouverte par 2 utilisateurs ou plus: donc ta base grossit, surtout si tu écris des BLOB "en veux-tu en voilà" !
    Alors le recyclage ne se fera qu'au compactage de la BD.

    Il y a un paramétrage du moteur Jet pour autoriser ou non le recyclage de ces pages, (cf. dbRecycleLVs) mais de toute façon, le recyclage n'est pas effectif en cas d'ouverture de la BD par plus d'un utilisateur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ' Activer le recyclage des pages Long-Valued
    DBEngine.SetOption dbRecycleLVs, 1
    Alors, tu as quand même une sortie de secours, et là encore j'ai testé et c'est OK !!!

    Ma BD de test ne dépasse jamais 256 Ko, et pas de compactage !
    (j'ai utilisé le principe du prédimensionnement).

    Tu peux placer tes données dans une BD au format Jet 2.0 et là pas de souci, le recyclage fonctionne toujours bien.

    Donc une BD dorsale au format 2.0 avec tes données, et une BD applicative au format que tu voudras (ex celui utilisé par Access 2000) qui accède à la BD dorsale au moyen de tables attachées (liées).
    _

  18. #18
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut Merci JBO
    je vais tester ta solution.
    ayant un abonnement MSDN , j'ai essayé de leur communiquer mon probleme.
    ils ont oser me dire qu'ils ne supportait plus les bases access 2000,VB6. !!
    ils vont peut etre m'aider ??


    MERCI

  19. #19
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 11
    Points : 2
    Points
    2
    Par défaut ca marche
    la ligne
    DBEngine.SetOption dbRecycleLVs, 1
    semble resoudre le probleme

    ma base est effectivement ouverte par un poste distant, mais la liason n'est pas permanente .

    MERCI JBO pour ta patience
    stouri

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 27/05/2008, 02h15
  2. migration de base access vers postgres
    Par greg_ggl dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 09/03/2006, 10h33
  3. Crash Base Access
    Par Ronald G. dans le forum Access
    Réponses: 4
    Dernier message: 04/08/2003, 11h55
  4. Export base Access vers MySql
    Par jjn1er dans le forum Outils
    Réponses: 7
    Dernier message: 10/03/2003, 23h50
  5. [VB6] [ADO] Like sur base Access
    Par dlpxlid dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 24/01/2003, 11h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo