Growing MS Access File Size problem

后端 未结 9 475
庸人自扰
庸人自扰 2021-01-12 08:41

I have a large MS Access application with a lot of computations in VBA code. When I run it it eventually crashes due to excessive file size. There are a lot of intermediat

相关标签:
9条回答
  • 2021-01-12 09:09

    I'd push the data over to MS SQL (the permanent data and the intermediate tables); and you can leave the code portion in MS Access for the time being.

    This solves two big issues:

    1. The data will be inherently more stable/dependable (I can't tell you how many times I've had a corrupt MS Access database).
    2. Your Access database won't grow/change very much (it should reach an equilibrium once all the code in has been run and compiled).

    Both of these mean no more having to compress/repair the database; you can get a free version (the Express Edition) of MS SQL and it is not that hard to do.

    0 讨论(0)
  • 2021-01-12 09:10

    You should be able to run the compact function from within your VBA code.

    I had the below snippet bookmarked from a long time ago when I was doing access work.

    Public Sub CompactDB() 
        CommandBars("Menu Bar").Controls("Tools").Controls("Database utilities").Controls("Compact and repair database...").accDoDefaultAction 
    End Sub 
    

    You can put that in your code to get around it.

    NOTE: you might also consider growing to a larger db system if you are having these types of scaling issues.

    0 讨论(0)
  • 2021-01-12 09:22

    The state of affairs with regard to Jet file sizes is interminably problematic for me.

    I am currently watching a piece of my own VBA code from Access database A as it does a series of single-record field updates using ADO to a table on Access database B (via a updateable-query reference in database A). The single field is a CHAR(8). With every 4 updates that go by, database B grows by about 8 Kbytes. No good excuse for that. The addition to the file size slows performance on this severely; with each file growth, updates slow from about one per second (in a table of about 30-40K records using single-record SQL lookups and no indexes anywhere) to one per 5-10 seconds. Now, I admit, I did compact/repair database B prior to running this update code; perhaps if I had not done that, the performance would not have been this bad. Had the target field for update been of, say, type Memo, then I would have expected this. But to carry out an update on a CHAR() field and get this result is simply not reasonable.

    Most of the above (no particular criticism for any one solution intended) appear to be valid solutions for applications that use a relatively permanent business application arrangement (talk to the same target databases all of the time). Mine is not so . . . I cannot alter the target database (database B), as it is generated and consumed by a vendor's tool that we use to export and import data from their application.

    I understand and commend the above writers for coming up with solutions to users' problems. However, I cannot let it stand when poor software design/implementation gets in the way of users using a product as the users expect it to function.

    0 讨论(0)
  • Unfortunately, MS Access has problems when you get too large - I think the max size is 2GB for an access DB.

    You may consider moving to Sql Express, VistaDB, etc.

    0 讨论(0)
  • 2021-01-12 09:28

    If you do not want to switch to SQL Express or similar, you could dig the following ideas:

    • Open another 'external' access database (mdb file) for all temporary tables, so you could put all temp data in the external file, throwing away the mdb file when you close your app. You will then manipulate in your code the 'currentDb' object and another database that you build at startup and connect to through jet, OLEDB or ODBC connection
    • Separate your permanent tables from your code and, when needed, bring the data into your local client interface to build your temporary tables. This can be done for example by linking the external database to the local/client file using "DoCmd.transferDatabase acLink". This can also be done by connecting to the permanent data through OLEDB connection, opening the needed recordset(s) and saving them locally as XML files. There are many other solutions that can be implemented here.
    0 讨论(0)
  • 2021-01-12 09:30

    I have encountered a similar issue where my database was bloating on raw data import. Instead of splitting the database and compacting the backend routinely, I decided to use the database object (DAO) to create a temp database, import the data, query/modify data in that temp database, pull it over to your original database via SQL and then delete it. YBase code shown below:

    Sub tempAccessDatabaseImport()
        Dim mySQL As String
        Dim tempDBPath As String
        Dim myWrk As DAO.Workspace
        Dim tempDB As DAO.Database
        Dim myObject
    
        'Define temp access database path
        tempPathArr = Split(Application.CurrentProject.Path, "\")
        For i = LBound(tempPathArr) To UBound(tempPathArr)
            tempDBPath = tempDBPath + tempPathArr(i) + "\"
        Next i
        tempDBPath = tempDBPath + "tempDB.accdb"
    
        'Delete temp access database if exists
        Set myObject = CreateObject("Scripting.FileSystemObject")
        If myObject.FileExists(tempDBPath) Then
            myObject.deleteFile (tempDBPath)
        End If
    
        'Open default workspace
        Set myWrk = DBEngine.Workspaces(0)
    
        'DAO Create database
        Set tempDB = myWrk.CreateDatabase(tempDBPath, dbLangGeneral)
    
        'DAO - Import temp xlsx into temp Access table
        mySQL = "SELECT * INTO tempTable FROM (SELECT vXLSX.*FROM [Excel 12.0;HDR=YES;DATABASE=" & RAWDATAPATH & "].[" & WORKSHEETNAME & "$] As vXLSX)"
    
        'DAO Execute SQL
        Debug.Print mySQL
        Debug.Print
        tempDB.Execute mySQL, dbSeeChanges
    
        'Do Something Else
    
        'Close DAO Database object
        tempDB.Close
        Set tempDB = Nothing
    
        myWrk.Close
        Set myWrk = Nothing
    
        'Delete temp access database if exists
        If myObject.FileExists(tempDBPath) Then
            'myObject.deleteFile (tempDBPath)
        End If
    End Sub
    
    0 讨论(0)
提交回复
热议问题