Главная | Контакты



Главная > Программы > Microsoft Access

Microsoft Access: сжатие данных

Q1. Из-за чего растет размер файла БД?

1.1. При удалении данных в таблицах БД записи из файла БД не удаляются, а просто помечается как удаленные (удаляются логически). Т.е. стертые данные так и лежат в базе, в результате файл по мере работы постепенно растет;

1.2. При внесении изменений в формы, отчеты, запросы и т.п. прежние копии редактируемых объектов, по аналогии с записями в таблицах (см. выше), удаляются логически, но не физически, что так же приводит к "распуханию" файла БД;

1.3. Access во время выполнения Проекта активно пользуется Скрытыми таблицами Проекта (БД), поэтому рост размеров файла БД может наблюдаться даже в MDE/ADE-файлах (редактировать формы, отчеты и т.п. в которых невозможно), не содержащих таблицы с данными пользователя;

1.4. Распухание БД возможно, если при выполнении каких-либо задач создаются временные таблицы (например, при формировании сложных отчетов), а затем данные временные таблицы уничтожаются. Уничтожаются они так же логически (просто помечаются как удаленные).

Q2. За счет чего размер файла БД уменьшается при сжатии?

При сжатии из файла БД физически удаляются записи и объекты БД, помеченные как "удаленные" (логически удаленные).

Q3. Зачем необходимо сжимать БД?

3.1. Для повышения производительности Проекта (быстродействия БД). Во время сжатия Access не только физически удаляет логически удаленные записи, что само по себе увеличивает производительность (отпадает необходимость фильтровать действительные данные от логически удаленных данных), но и дефрагментирует таблицы, в результате чего увеличивается скорость доступа к данным;

3.2. Для повышения надежности БД. На основе эмпирических данных замечено, что регулярное сжатие (и соответственно, восстановление) БД повышает "иммунитет" Проекта к глюкам;

3.3. В некоторых случаях сжатие/восстановление БД просто необходимо. Если БД "упала", то первым делом необходимо сделать ее (уже упавшей) резервную копию и вторым шагом произвести сжатие/восстановление;

3.4. В качестве профилактических мер после неких форс-мажорных обстоятельств. Например, если во время работы БД был выключен свет, либо пользователь сам выключил компьютер, не закрыв БД, либо произошло "падение" сети в момент работы БД и т.п.

3.5. Заново создается статистика по таблицам (количество записей в таблицах, наличие и типы связей, присутствие индексов и т.п.), которая в дальнейшем будет использована Оптимизатором выполнения запросов. Кроме того, сбрасывается флаг компиляции запросов, что приводит при первом следующем выполнении запроса к новому построению плана выполнения запроса, но уже с учетом обновленной статистики, что увеличивает скорость выполнения запросов. Этот пункт можно считать единственным минусом сжатия/восстановления БД, так как на построение плана запроса требуется некоторое время (небольшое).

Q4. Как часто необходимо сжимать БД?

Теоретически, сжимать БД необходимо при каждом закрытии БД. Практически это не всегда целесообразно, т.к. занимает определенное время и в некоторых случаях отрицательно сказывается на производительности БД в момент первого выполнения запросов (см. Пункт 3.5).
Оптимальным вариантом является некий график сжатия БД: раз в день, раз в два дня, раз в неделю и т.п., который определяется исходя из: 1) Количества одновременно работающих с БД пользователей, 2) размеров БД, 3) из частоты обновления данных в БД (удаление, добавление, редактирование записей) и т.п.

Q5. Как сжимать БД?

5.1. Через меню: Сервис/Служебные программы/Сжать и восстановить базу данных;

5.2. Через меню: Сервис/Параметры/Вкладка "ОБЩИЕ"/Флаг "Сжимать при закрытии". С помощью данной настройки можно организовать автоматическое сжатие БД при каждом ее закрытии. Действие данного флажка относится только к открытой базе данных, при этом подключенные (прилинкованные) базы данных сжаты не будут. Как сжать прилинкованную БД см. Вопрос/Ответ Q6;

5.3. Через преобразование БД к предыдущей версии БД (Сервис/Служебные программы/Преобразовать базу данных:) с последующим преобразованием полученного файла к текущей версии БД. Данный способ наиболее эффективен для сжатия БД после внесения изменений в его интерфейсную часть (редактирование форм, отчетов, кода и т.п.), так как иногда удается обнаружить ряд скрытых ошибок, зачастую возникших из-за сбоев самого Access, а так же физически удалить из файла БД логически удаленные объекты.

5.4. Через импорт в пустой (новый) файл БД. По преследуемым целям схож с предыдущим пунктом.

5.5. Через выполнение запуска Access в командной строке со специальными параметрами. Например:

"C:\Program Files\Microsoft Office\Office\Msaccess.exe" "С:\Мои документы\MyDB.mdb" /Excl /Compact

5.6. Через VBA-код, при этом можно использовать несколько различных технологий программного сжатия БД (См. ответы на вопросы Q6 и Q7).

5.7. C помощью утилиты [http://support.microsoft.com/default.aspx?scid=kb;en-us;295334 JetComp.exe], которая помимо сжатия умеет также восстанавливать некоторые повреждения .mdb-файлов, которые невозможно исправить средствами MS Access. Справку по параметрам командной строки jetcomp.exe можно получить с помощью

jetcomp.exe /?

Q6. Как сжать БД из VBA-кода моего Проекта?

6.1 - Вариант 1

Можно программно нажать кнопку "Сжать и восстановить базу данных" (меню Сервис/Служебные программы). Этот вариант является наиболее простым, но в то же время наименее гибким из предложенных далее, а также обладает рядом серьезных недостатков (см. ниже):

Public Function AutoCompact() 
  With CommandBars.Add(, 1, , True) 
    .Controls.Add 1, 2071, , , True 
    .Visible = True 
    .Controls(1).SetFocus 
    DoEvents 
    SendKeys "~" 
  End With
End Function

Достоинства:
  • Функция позволяет сжать текущую БД (базу данных, в которой выполняется VBA-код, вызывающий сжатие). Данный вариант является единственным вариантом, позволяющим сжимать текущую не закрытую БД. Не смотря на это, авторы FAQ настоятельно рекомендуют ознакомиться с пунктом 6.4, где рассмотрен более гибкий и надежный вариант реализации сжатия текущей БД;
  • Пример сообщает о наличии подобного варианта "программного сжатия БД" и раскрывает его недостатки.

    Недостатки:
  • Сжатие происходит только текущей БД (базы, в котором выполняется код), таким образом, если БД разделена на Интерфейсную часть и часть с Данными (см. Вопрос/Ответ Q8.3), то будет сжата только Интерфейсная часть в которой выполняется код, а часть с Данными останется несжатой;
  • БД после сжатия перезапускается (открывается повторно);
  • После последней строки в функции не должно быть никакого дополнительного кода, т.к. это может привести либо к невозможности выполнить сжатие, либо к невозможности выполнить данный дополнительный код;
  • Метод не дает программного контроля над выполняемым сжатием, т.е. невозможно отследить (перехватить) и обработать соответствующим способом ошибки, которые могут возникнуть в процессе сжатия БД.

    6.2. Вариант 2

    Сжатие через DAO-метод DBEngine.CompactDatabase.
    Данный метод сжатия наиболее предпочтителен для MDB/MDE форматов БД расположенных "настольно" (без сети) или для сетевых БД, организованных по технологии "Файл-Сервер". Основным условием является доступность (подключение) Библиотеки DAO.
    Метод не пригоден для сжатия текущей БД (базы данных, в которой выполняется процедура сжатия), но прекрасно подходит для разделенных БД (см. Пункт 8.3). Для сжатия базы данных, в которой выполняется программный код, инициирующий данное сжатие, можно воспользоваться Вариантом 1 (см пункт 6.1) или, что намного лучше, Отдельным процессом, который и произведет данное сжатие (см. пункт 6.4). Кроме того можно попытаться воспользоваться (на свой страх и риск) вариантом, приведенным в Пункте 7.2

    Сжатие производится следующим образом:

    - если к БД подключаются несколько пользователей, то перед сжатием БД необходимо убедиться, что ни один пользователь не подключен к базе. В противном случае система сгенерирует перехватываемую ошибку и сжатие БД выполнено не будет;

    - сформировать полный путь к сжимаемой БД и полный путь к новому (временному) файлу, в который сжатая БД будет записана;

    - сжать БД;

    - скопировать новый (появившийся в результате сжатия БД) файл на место старого (копирование под именем, которое принадлежало старому файлу);

    - удалить новый (временный) файл.

    В качестве примера можно привести два варианта реализации сжатия БД DAO-методом, отличающихся способами манипулирования файлами:

    6.2.1. Пример 1

    'ФУНКЦИЯ СЖАТИЯ БД DAO-Методом'
    '  gflngCompactDatabase(...)'
    '  ВХОДНЫЕ ПАРАМЕТРЫ ФУНКЦИИ:'
    '  CompactingDBPathAndName - строковый параметр, задающий ПОЛНЫЙ ПУТЬ (путь + имя файла)'
    '     к сжимаемой БД.'
    '  BackupBeforeCompactDB - необязательный логический параметр, указывающий на'
    '     необходимость сделать перед сжатием резервную копию сжимаемой БД (резервная'
    '     копия выкладывается в файл с именем "ИмяСжимаемогоФайла_Backup"). При'
    '     отсутствии параметра резервное копирование не производится.'
    
    'ВОЗВРАЩАЕМОЕ ФУНКЦИЕЙ ЗНАЧЕНИЕ:'
    '  = 0, если сжатие произведено;'
    '  = Номеру возникшей ошибки, если выполнить сжатие не удалось.'
    
    'ОСОБЕННОСТИ:'
    '  Для выполнения процедуры сжатия автоматически создается временный файл'
    '     с именем "ПолныйПуть\ИмяСжимаемогоФайла_Temp".'
    '  Резервное копирование, выполнение которого определяется параметром "BackupBeforeCompactDB",'
    
    '     производится в файл с именем "ПолныйПуть\ИмяСжимаемогоФайла_Backup"), при'
    '     этом старая копия резерва перезаписывается новой (фактически удаляется).'
    '  В случае, если сжимаемая БД открыта, то файл БД не будет скопирован (соответствующая'
    '     ошибка появится в момент копирования БД).'
    
    Public Function  gflngCompactDatabase( _
    CompactingDBPathAndName As String, _
    Optional BackupBeforeCompactDB As Boolean = False) As Long
    
    Dim strTempFile As String
    On Error GoTo ErrHandler
    'Формируем имя для временного ("принимающего") файла'
    
      strTempFile = Left(CompactingDBPathAndName, (Len(CompactingDBPathAndName) - 4)) & _
      "_Temp" & Right(CompactingDBPathAndName, 4)
    'Создаем (если надо) резервную копию файла БД перед сжатием'
      If BackupBeforeCompactDB = True _
      Then FileCopy CompactingDBPathAndName, _
      Left(CompactingDBPathAndName, (Len(CompactingDBPathAndName) - 4)) & _
      "_Backup" & Right(CompactingDBPathAndName, 4)
    
    'Сжимаем файл БД (с перезаписью сжатого файла в новый файл)'
      DBEngine.CompactDatabase CompactingDBPathAndName, strTempFile, dbLangCyrillic
    'Перезаписываем сжатый (временный файл) на место несжатого (старого файла)'
      FileCopy strTempFile, CompactingDBPathAndName
    'Удаляем временный файл'
      Kill strTempFile
    Exit Function
    
    ErrHandler:
    'обрабатываем возможные ошибки'
      gflngCompactDatabase = Err.Number
      Err.Clear: Exit Function
    End Function

    Достоинства:
  • Для манипулирования файлами (получения имени для временного файла и копирование файла) функция использует стандартные команды Access и не требует наличия на компьютере библиотеки "Microsoft Scripting Runtime" (SCRRUN.DLL), которая (как показывает практика) может отсутствовать;

    Недостатки:
  • Для получения имени временного файла функция добавляет к имени сжимаемого файла суффикс "_Temp" ("ПолныйПуть\ИмяСжимаемойБД_Temp"), поэтому в случае, если имеется рабочая БД с подобным именем, то по окончании процесса сжатия она будет удалена. Данный недостаток удается избежать либо приняв правило "Не присваивать рабочим файлам БД имени, оканчивающегося на '_Temp'", либо изменив функцию (заменить добавление суффикса "_Temp" на путь и имя файла, специально отведенного для сжатия БД), либо воспользовавшись технологией, приведенной в следующем Примере:

    6.2.2. Пример 2

    'ФУНКЦИЯ СЖАТИЯ БД DAO-Методом с использованием FileSystemObject для манипулирования файлами '
    
    '  gflngCompactDatabaseFSO(...)'
    'ВХОДНЫЕ ПАРАМЕТРЫ ФУНКЦИИ:'
    '  CompactingDBPathAndName - строковый параметр, задающий ПОЛНЫЙ ПУТЬ (путь + имя файла)'
    '     к сжимаемой БД.'
    '  BackupBeforeCompactDB - необязательный логический параметр, указывающий на'
    '     необходимость сделать перед сжатием резервную копию сжимаемой БД (резервная'
    '     копия выкладывается в файл с именем "ИмяСжимаемогоФайла_Backup"). При'
    '     отсутствии параметра резервное копирование не производится.'
    
    'ВОЗВРАЩАЕМОЕ ФУНКЦИЕЙ ЗНАЧЕНИЕ:'
    '  = 0, если сжатие произведено;'
    '  = Номеру возникшей ошибки, если выполнить сжатие не удалось.'
    
    'ОСОБЕННОСТИ:'
    '  Резервное копирование, выполнение которого определяется параметром "BackupBeforeCompactDB",'
    '     производится в файл с именем "ПолныйПуть\ИмяСжимаемогоФайла_Backup"), при'
    
    '     этом старая копия резерва перезаписывается новой (фактически удаляется).'
    '  В случае, если сжимаемая БД открыта, то файл БД будет скопирован и соответствующая'
    '     ошибка появится только в момент сжатия БД.'
    
    Public Function gflngCompactDatabaseFSO( _
    CompactingDBPathAndName As String, _
    Optional BackupBeforeCompactDB As Boolean = False) As Long
    
    On Error GoTo ErrHandler
    Dim strTempFile As String
    Dim objFileSystem As Object
    
    'Создаем объект Файловой системы '
    
      Set objFileSystem = CreateObject("Scripting.FileSystemObject")
    'Создаем (если надо) резервную копию файла БД перед сжатием'
    
      If BackupBeforeCompactDB = True _
      Then objFileSystem.CopyFile CompactingDBPathAndName, _
      Left(CompactingDBPathAndName, (Len(CompactingDBPathAndName) - 4)) & _
      "_Backup" & Right(CompactingDBPathAndName, 4)
    
    'Получаем имя для временного ("принимающего") файла'
    
      strTempFile = objFileSystem.GetTempName
    'Сжимаем файл БД (с перезаписью сжатого файла в новый файл)'
    
      DBEngine.CompactDatabase CompactingDBPathAndName, strTempFile, dbLangCyrillic
    'Перезаписываем сжатый (временный файл) на место несжатого (старого файла)'
    
      objFileSystem.CopyFile strTempFile, CompactingDBPathAndName, True
    
    'Удаляем временный файл'
      Kill strTempFile
    'Уничтожаем объект Файловой системы'
      Set objFileSystem = Nothing
    Exit Function
    
    ErrHandler:
    'обрабатываем возможные ошибки'
    
      gflngCompactDatabaseFSO = Err.Number
      Err.Clear: Exit Function
    End Function
    

    Достоинства:
  • Для получения имени временного файла функция использует специальный метод объекта FileSystemObject, генерирующий уникальное имя для файла, что исключает возможность перезаписать (фактически удалить) какой-либо существующий файл.

    Недостатки:
  • Для манипулирования файлами (получения имени для временного файла и копирование файла) функция использует библиотеку "Microsoft Scripting Runtime" (SCRRUN.DLL), которая (как показывает практика) может отсутствовать на компьютере. Данный недостаток удается избежать воспользовавшись предыдущим примером DAO-реализации сжатия БД (пункт 6.2.1).

    6.3. Вариант 3

    Сжатие через JRO-метод ("расширение" ADO) JRO.JetEngine.
    Данный метод сжатия наиболее предпочтителен для ADP/ADE форматов БД, обычно не использующих DAO-библиотеку.

    Сжатие производится следующим образом:

    - Отключаем от базы данных клиента, с которого запускается процедура сжатия. На данном этапе отладки необходимо убедиться, что все соединения, рекордсеты и т.п. закрыты, т.е. ldb-файл базы данных отсутствует.

    - Проверяем, подключен ли кто-нибудь еще к базе данных, что можно сделать двумя вариантами:

    1) Проверить наличие .ldb файла
    If DIR(полный путь к ldb файлу)<>"" then ...

    2) Использовать метод ADO OpenSchema для получения информации о подключенных пользователях (если есть файл рабочей группы) или машинах (в данном примере именно так, где имя машины - 10 символов). Вариант более гибкий, т.к. можно узнать, кто именно блокирует файл (в данном примере проверяем подключен кто-то или нет, но из полученного рекордсета легко можно забрать и реальные имена пользователей/машин).
    Dim cnn As ADODB.Connection, rst As ADODB.Recordset
    
    Dim je As New JRO.JetEngine 
    Dim lngConnected As Long, strCurPCName As String, strBE As String, strBETemp As String
    
    Const adhcUsers = "{947bb102-5d43-11d1-bdbf-00c04fb92675}"
    strBE = "Полный путь к файлу БД"
    strBETemp = "Полный путь к новому (сжатому) файлу БД"
      Set cnn = New ADODB.Connection
      cnn.Provider = "Microsoft.Jet.OLEDB.4.0"
    
      cnn.Open "Data Source=" & strBE
      'Используем элемент Connection Control (Jet версии не младше 4.0) для'
      'запрета подключения новых пользователей.'
      cnn.Properties("Jet OLEDB:Connection Control") = 1
    
      Set rst = cnn.OpenSchema(Schema:=adSchemaProviderSpecific, SchemaID:=adhcUsers)
    ' strCurPCName - имя машины, с которой запускается процедура'
    
      strCurPCName = Environ("COMPUTERNAME")
          With rst
              Do Until .EOF
              ' Считаем кол-во подключенных машин, исключая машину, с которой
    
              ' запущена процедура. Наверняка вычленить реальное имя машины из
              ' этого поля можно более красивым и правильным способом, мне просто
              ' лень было, у меня и так работает:-)'
                  If Not strCurPCName = Left(.Fields(0), 10) Then lngConnected = lngConnected + 1
    
                  .MoveNext
              Loop
          End With
          If lngConnected > 0 Then
    
             ' База данных заблокирована другим пользователем->сжать не удастся
             ' -> выходим любым приемлемым способом, не забыв закрыть rst и cnn'
    
          End If
          ' База не заблокирована -> переходим к сжатию. Вариант с принудительным
    
          ' отключением пользователей здесь не рассматривается, т.к. лично я
          ' считаю его приемлемым только в аварийных случаях.'
    
      'Закрываем открытый ранее рекордсет'
    
      If Not rst Is Nothing Then rst.Close
    
      Set rst=nothing

    - Производим сжатие, при этом должна быть подключена библиотека Microsoft Jet and Replication Objects x.x Library (JRO)
    ' Проверяем наличие временного файла (возможно остался
        ' от предыдущей неудачной попытки сжатия) и удаляем его
    
        If Dir(strBETemp) <> "" Then Kill strBETemp
        ' Закрываем объект cnn, открытый в п.2, иначе сжать данные не получится'
    
        Set cnn=Nothing
        ' Сжимаем'
    
        je.CompactDatabase "Data Source=" & strBE & ";", _
            "Data Source=" & strBETemp & ";"
    
        ' Маловероятно, но гипотетически за время сжатия, 
        ' кто-нибудь мог подключиться к файлу БД, поэтому можно еще раз
        ' проверить наличие подключенных пользователей (см. пример выше),
        ' если никто не подключен, то удаляем старый файл и
        ' переименовываем новый сжатый файл. Если кто-то все-таки
        ' успел открыть БД, то просто выходим, оставляя временный
    
        ' сжатый файл. Добавить обработку такой ситуации по вкусу.
    
        Kill strBE
        Name strBETemp As strBE
        Set je = Nothing
    

    6.4. Вариант 4

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

    Как это работает:

    База данных, в которой выполняется код (Клиентская часть или Неразделенная БД), перед закрытием (возможно, не при каждом закрытии: См. Вопрос/Ответ Q4) вызывает другую программу, которая производит все необходимые действия по обслуживанию БД.
    В приведенном ниже примере в качестве обслуживающих действий выполняется сжатие Вызвавшей БД и Дополнительной БД, при этом в качестве Сервис-Провайдера используется Access.

    Для реализации описанного механизма:

    - Создайте новую базу данных с именем "DBServiceProvaider.mdb", в которой создайте форму. Скопируйте в модуль формы следующий код:
    Const TimeDelay As Long = 250     'задержка в миллисекундах между неудачными попытками сжатия'
    
    Const MaxIterations As Long = 10 'количество повторов сжатия при неудачных попытках сжатия'
    Dim mlngStep As Long              'номер текущего выполняемого шага'
    
    
    Private Sub Form_Load()
      Me.TimerInterval = 1            'запускаем таймер'
    End Sub
    
    Private Sub Form_Timer()
      Me.TimerInterval = 0  'останавливаем таймер (исключаем повторное событие в момент сжатия)'
      Select Case mlngStep
      Case 0    'Первый шаг "Обслуживания БД"'
    
        Call gsTryToCompactDB("C:\Тест\MyDB1.mdb")
      Case 1    'Второй шаг "Обслуживания БД"'
        Call gsTryToCompactDB("C:\Тест\MyDB2.mdb")
      'Case N    ''N-ный шаг "Обслуживания БД"'
    
        'Действия по обслуживанию БД...'
        'Приращиваем значение mlngStep для выполнения следующего шага обслуживания'
        'Запускаем таймер для выполнения следующего шага'
      Case 2    'заключительный шаг (N+1), заканчивающий выполнение Проекта "Обслуживания БД"'
    
        MsgBox "Обслуживание завершено!", vbInformation
        DoCmd.Quit
      End Select
    End Sub
    
    Private Function gsTryToCompactDB(CompactingDB As String)
    
    Dim lngUserAnswer As Long
    Static lngIterationCnt As Long
      If gflngCompactDatabase(CompactingDB) = 0 Then 'сжимаем БД и проверяем, получилось ли'
    
      'если сжатие произошло...'
        mlngStep = mlngStep + 1
        lngIterationCnt = 0
        Me.TimerInterval = 1
      Else
    
      'если сжатие не произошло (возникла ошибка)...'
        If lngIterationCnt <= MaxIterations Then
          lngIterationCnt = lngIterationCnt + 1
          Me.TimerInterval = TimeDelay
        Else
    
          lngIterationCnt = 0
          lngUserAnswer = MsgBox( _
          "В данный момент не получается сжать файл '" & _
          CompactingDB & "'." & vbNewLine & _
          "Попытаться сжать данный файл еще раз?", _
          vbExclamation + vbYesNoCancel, "Не удается сжать БД")
          Select Case lngUserAnswer
          Case vbYes
            Me.TimerInterval = TimeDelay
          Case vbNo
            mlngStep = mlngStep + 1
    
            Me.TimerInterval = 1
          Case vbCancel
            DoCmd.Quit 'Выход из Acces'
          End Select
        End If
    
      End If
    End Function
    Обратите внимание, что в процедуре Private Sub Form_Timer() указан путь к двум сжимаемым БД, который необходимо настроить в соответствии с именами и размещением сжимаемых БД на машине.

    - сохраните форму и укажите ее имя в качестве автоматически открываемой формы (Меню Сервис\Параметры запуска\Вывод формы или страницы);

    - создайте модуль и разместите в нем функцию, приведенную в Пункте 6.2.1 (можно воспользоваться и Примером из пункта 6.2.2, соответствующим образом откорректировав процедуру gsTryToCompactDB());

    - подключите DAO-библиотеку (в случае, если еще не подключена), откомпилируйте код и закройте созданную "DBServiceProvaider.mdb";

    - откройте базу, из которой будет вызываться созданный нами "Провайдер Обслуживания БД", и добавьте в соответствующее место (например, на кнопку "Выход", или на событие выгрузки главной формы проекта) код:
      Shell "C:\Program Files\Microsoft Office\Office\Msaccess.exe " & _
        """C:\Тест\DBServiceProvaider.mdb""", vbMaximizedFocus
      DoCmd.Quit
    Обратите внимание, что сначала указывается полный путь к исполнимому файлу Access, а затем полный путь к созданной "DBServiceProvaider.mdb", при этом как тот, так и другой необходимо указать в соответствии с расположением файлов на машине.

    Следует отметить, что процедура Private Sub Form_Timer() может содержать сколько угодно шагов, направленных на обслуживание БД.

    Код приведен в качестве упрощенного примера и призван показать в общих чертах пути реализации приведенной концепции.

    7. Что еще можно сделать и почему так делать не надо?

    7.1. Можно Программно нажать кнопку "Сжать и восстановить базу данных". Один из наиболее работоспособных вариантов подобного способа сжатия описан в Пункте 6.1. Здесь рассмотрен вариант выполнения аналогичных действий всего лишь одной командой (только для Access 200x):

    'Для Англоязычной версии Access'
    
    CommandBars("Menu Bar").Controls("Tools"). _ 
    Controls("Database utilities").Controls("Compact and repair database..."). _ 
    accDoDefaultAction
    
    'Для Русскоязычной версии Access'
    
    CommandBars("Menu Bar").Controls("С&ервис"). _ 
    Controls("&Служебные программы").Controls("С&жать и восстановить базу данных"). _ 
    accDoDefaultAction

    Из приведенного примера видно, что код должен соответствовать локализованной версии Access, именно поэтому использовать данный способ не рекомендуется.

    Здесь же можно привести несколько видоизмененную версию описываемого способа сжатия БД:

    'Обращение к панели инструментов через индексы'
    
    CommandBars(40).Controls(12). _ 
    Controls(7).Controls(2). _ 
    accDoDefaultAction
    Данный вариант не зависит от локализации Access и работает в версиях 2000 и XP, но гарантировать невозможно, что в следующих версиях индексы останутся прежними, а значит, что приложение использующее данный код в следующих версиях останется работоспособным.

    Кроме рассмотренных особенностей использования данного способа сюда можно отнести и все сказанное в пункте 6.1

    7.2. Попытаться сжать Текущую БД (базу данных, в которой выполняется код, инициирующий сжатие) можно на основе метода, описанного в Пункте 6.2.2, при этом следует внести изменения в алгоритм выполнения сжатия:

    - скопировать текущую (исполняемую) БД во временный файл;

    - сжать временный файл в другой временный файл;

    - полученный сжатый временный файл скопировать на место текущего (выполняемого) файла.

    Данная методика, так же как и методика, описанная в Пункте 7.1, приведена здесь с целью ознакомления со всеми возможными вариантами сжатия БД и настоятельно не рекомендуется к реальному применению! Причин несколько. Во-первых, не всегда получается подменить (перезаписать) файл открытой БД. Во-вторых, если подмена будет "удачной" (система позволит перезаписать файл открытой БД), то это может обернуться полным разрушением БД. В-третьих, читаем Help: "CompactDatabase Method: Copies and compacts a closed database...", т.е. сжимать можно только закрытую (не используемую) БД.

    8. Что еще следует иметь в виду по данному вопросу?

    8.1. Перед сжатием БД рекомендуется создавать резервную копию сжимаемого файла. В случае если сжатие производится после некой аварийной ситуации (см. Пункты 3.3 и 3.4), то данная рекомендация превращается в жесткое требование;

    8.2. Как уже было указано в пункте 6, во время сжатия к БД не должны быть подключены пользователи;

    8.3. К вопросу о сжатии БД, повышающем скорость выполнения и "глюкоустойчивость" Проекта, можно добавить рекомендацию разделять БД на несколько частей, ключевыми из которых являются "Интерфейсная часть" (формы, отчеты, запросы, модули и т.п.) и "Часть с Данными" (таблицы). Данная рекомендация основана на многих причинах, выходящих за рамки FAQ;

    8.4. Во время сжатия БД Автоматические Счетчики в таблицах, генерирующие Последовательные значения при добавлении записей, так же "сжимаются" - принимают значения равные Максимальному значению счетчика в столбце + 1;

    8.5. После сжатия БД рекомендуется выполнять дефрагментацию диска (по мере возможности), что положительно сказывается на производительности Проекта уже на системном уровне (скорость доступа к дефрагментированному файлу выше, нежели скорость доступа к файлу, разбросанному по диску).


    Главная > Программы > Microsoft Access