Précédent   Forum des professionnels en informatique > Logiciels > Microsoft Office > Access
Access Forum d'entraide sur Microsoft Access. Avant de poster -> La F.A.Q Access
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 06/02/2008, 22h40   #1
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 :
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
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 22h59   #2
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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.
_
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 23h07   #3
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 !
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 23h10   #4
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
Bon, je vais tester ton code, par curiosité...
_
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 23h12   #5
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 !!
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 23h43   #6
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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 :
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
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 23h50   #7
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
Par défaut je teste

merci
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2008, 23h57   #8
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 !!
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 00h54   #9
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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.
_
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 13h22   #10
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
Par défaut c'est compliqué

Help !
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 13h32   #11
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 !
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 14h23   #12
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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 :
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
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 14h37   #13
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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 :
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 ?
_
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 14h51   #14
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 !
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 15h17   #15
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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.
_
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 15h44   #16
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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 :
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
#####################################
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 20h04   #17
En attente de confirmation mail
 
Inscription : février 2005
Messages : 1 731
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : février 2005
Messages : 1 731
Points : 2 010
Points : 2 010
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 :
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).
_
=JBO= est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 20h38   #18
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2008, 20h54   #19
Invité de passage
 
Inscription : février 2008
Messages : 11
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 11
Points : 1
Points : 1
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
stouri est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 18h54.


 
 
 
 
Partenaires

Hébergement Web