Проблема увеличения размера файла MS Access

У меня есть большое приложение MS Access с большим количеством вычислений в коде VBA. Когда я запускаю его, он в конечном итоге вылетает из-за чрезмерного размера файла. Создается множество промежуточных таблиц и запросов, которые впоследствии удаляются, но Access не освобождает пространство. Я старательно закрыл все промежуточные наборы записей и установил все временные объекты в ничто, но ничего не помогает. Единственный способ запустить свой код - запустить его часть, остановить и восстановить / сжать файл, а затем перезапустить код.

Нет лучшего способа?

Спасибо

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
7
0
29 335
9

Ответы 9

К сожалению, у MS Access возникают проблемы, когда вы становитесь слишком большими - я думаю, что максимальный размер составляет 2 ГБ для доступа к базе данных.

Вы можете подумать о переходе на Sql Express, VistaDB и т. д.

Ограничение в 2 ГБ имеет смысл, но, скорее всего, это не ограничение доступа, а ограничение ОС. То есть, поскольку доступ хранит свои данные в одном файле, ограничение на размер файла в 2 ГБ в ОС может стать точкой отказа.

JohnFx 16.01.2009 19:53

Я не знаю ни одной последней версии Windows, в которой было бы ограничение на размер файла 2 ГБ. Это правда, что это не ограничение Доступ - это ограничение Jet, и оно жестко встроено в Jet.

David-W-Fenton 17.01.2009 00:51

Позднее добавление: некоторые файловые системы, такие как FAT32, имеют ограничение на размер файла 2 ГБ. Но никто больше не использует FAT32 в Windows - это исчезло со смертью семейства Win9x версий Windows.

David-W-Fenton 16.04.2010 00:05

С какими размерами вы имеете дело? Какой код ошибки при сбое? Я был бы удивлен, если бы это произошло просто потому, что файл стал «слишком большим», но я полагаю, что есть предел. Судя по вашему описанию всего временного, могут быть улучшения в дизайне, которые могут помочь.

Обновлено: Я ожидаю, что вы понимаете, что заменить базу данных чем-то еще нетривиально - даже если вы попытаетесь сохранить все, что есть в mdb, кроме таблиц. Определения запросов доступа уникальны, Access SQL нестандартен, и вам придется начинать заново.

Большинство приложений Access, которые я видел, имеют много возможностей для рефакторинга; и обычно это не так сложно, если: а) вы понимаете логику и бизнес-правила и б) хорошо разбираетесь в программировании в Access. Но это было бы более или менее верно для любых альтернатив. Если бы я был на вашем месте, и вам немного не хватило бы ни в одной области, возможно, вы могли бы получить некоторую помощь. Но сначала я бы попытался спасти приложение Access.

Также есть предложение от другого автора о перемещении таблиц в один или несколько прикрепленных MDB. В целом это надежная, хорошо зарекомендовавшая себя техника. Но сначала я должен понять, в чем настоящая причина проблемы.

Я не согласен с вами. Я переместил довольно большие базы данных MS Access в MS SQL без особых проблем (нет, это не тривиально); но подавляющее большинство определений запросов и т. д. работают без изменений (особенно если они связаны с таблицами SQL в базе данных Access). Вы не начинаете заново,

BIBD 16.01.2009 20:38

Вы должны иметь возможность запускать компактную функцию из кода VBA.

У меня был приведенный ниже фрагмент, который был добавлен в закладки давным-давно, когда я выполнял работу с доступом.

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

Вы можете поместить это в свой код, чтобы обойти это.

ПРИМЕЧАНИЕ: вы также можете рассмотреть возможность перехода на более крупную систему БД, если у вас возникают проблемы с масштабированием такого типа.

Замечу, что инструмент «Сжатие и восстановление» иногда создает поврежденную базу данных (нечитаемую). Рекомендуется ВСЕГДА делать резервную копию своей базы данных перед запуском на ней инструмента. Мне кажется, что автоматический запуск из кода - очень рискованная операция.

BIBD 03.10.2014 01:13

Как бы это было реализовано, если у вас есть разделенная база данных и серверная часть растет?

rohrl77 20.11.2019 16:51

Согласно http://office.microsoft.com/en-us/access/HP051868081033.aspx, Access 2003 и 2007 имеют ограничение в 2 ГБ. Однако легко переместить некоторые или все таблицы в отдельный файл .mdb, а затем связать их с этими таблицами. В любом случае рекомендуется иметь два файла: один для ваших данных, а другой для всех макросов, запросов и т. д. У вас даже может быть несколько файлов, если ваш файл таблицы приближается к пределу в 2 ГБ.

Я бы перенес данные в MS SQL (постоянные данные и промежуточные таблицы); и вы можете пока оставить часть кода в MS Access.

Это решает две большие проблемы:

  1. Данные будут по своей сути более стабильными / надежными (я не могу сказать вам, сколько раз у меня была поврежденная база данных MS Access).
  2. Ваша база данных Access не будет сильно расти / меняться (она должна достичь равновесия после того, как весь код будет запущен и скомпилирован).

Оба эти фактора означают, что больше не нужно сжимать / восстанавливать базу данных; вы можете получить бесплатную версию (Express Edition) MS SQL, и это не так уж и сложно.

Если вы не хотите переключаться на SQL Express или аналогичный, вы можете копать следующие идеи:

  • Откройте другую «внешнюю» базу данных доступа (файл mdb) для всех временных таблиц, чтобы вы могли поместить все временные данные во внешний файл, выбрасывая файл mdb при закрытии приложения. Затем вы будете манипулировать в своем коде объектом 'currentDb' и другой базой данных, которую вы создаете при запуске и подключаетесь через соединение jet, OLEDB или ODBC.
  • Отделите постоянные таблицы от кода и, при необходимости, перенесите данные в локальный клиентский интерфейс для создания временных таблиц. Это можно сделать, например, связав внешнюю базу данных с локальным / клиентским файлом с помощью «DoCmd.transferDatabase acLink». Это также можно сделать, подключившись к постоянным данным через соединение OLEDB, открыв необходимые наборы записей и сохранив их локально в виде файлов XML. Здесь можно реализовать множество других решений.

Положение дел в отношении размеров файлов Jet для меня бесконечно проблематично.

В настоящее время я наблюдаю за частью моего собственного кода VBA из базы данных Access A, поскольку он выполняет серию полей с одной записью обновления с использованием ADO для таблицы в базе данных Access B (через ссылку на обновляемый запрос в базе данных A). Единственное поле - это СИМВОЛ (8). После каждых 4 обновлений база данных B увеличивается примерно на 8 Кбайт. Этому нет оправдания. Увеличение размера файла сильно снижает производительность; при каждом росте файла обновление происходит медленно, примерно от одной записи в секунду (в таблице, содержащей около 30-40 тысяч записей, использующих поиск по одной записи SQL без каких-либо индексов) до одного за 5-10 секунд. Я признаю, что я сжал / восстановил базу данных B перед запуском этого кода обновления; возможно, если бы я этого не сделал, спектакль не был бы таким плохим. Если бы целевое поле для обновления было, скажем, типа Memo, я бы этого ожидал. Но выполнять обновление поля CHAR () и получить такой результат просто неразумно.

Большая часть из вышеперечисленного (без особой критики в отношении какого-либо одного задуманного решения) кажутся допустимыми решениями для приложений, которые используют относительно постоянную структуру бизнес-приложений (постоянно обращаются к одним и тем же целевым базам данных). У меня не так. . . Я не могу изменить целевую базу данных (база данных B), поскольку она создается и используется инструментом поставщика, который мы используем для экспорта и импорта данных из их приложения.

Я понимаю и благодарю вышеупомянутых авторов за решения проблем пользователей. Однако я не могу допустить, чтобы дизайн / реализация программного обеспечения бедные мешали пользователям, использующим продукт, поскольку пользователи ожидают, что он будет работать.

Для меня допущение обновления одной записи за раз - это красный флаг. Вы уверены, что это невозможно сделать с помощью пакетного ОБНОВЛЕНИЯ SQL? Во-вторых, здесь нет ничего удивительного. Jet / ACE хранит записи в полях переменной длины. Изменение данных в поле нефиксированной длины приведет к изменению длины записи и потребует перезаписи ее на другой странице данных. Все это сделано по дизайну и на самом деле не сильно отличается от любого механизма базы данных, который когда-либо существовал (кроме тех, что были в те дни, когда дисковое пространство было гораздо более ограниченным, чем это было, когда Jet был разработан в начале 90-х).

David-W-Fenton 16.04.2010 00:03

Я столкнулся с аналогичной проблемой, когда моя база данных раздувалась при импорте необработанных данных. Вместо обычного разделения базы данных и сжатия серверной части я решил использовать объект базы данных (DAO) для создания временной базы данных, импорта данных, запроса / изменения данных в этой временной базе данных, перетаскивания их в исходную базу данных через SQL и затем удалите его. Код YBase показан ниже:

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

Другие вопросы по теме