База данных MS-Access становится очень большой во время вставок - PullRequest
1 голос
/ 30 октября 2009

У меня есть база данных, в которую мне регулярно требуется импортировать большие объемы данных с помощью некоторых сценариев Python. В сжатом виде данные для импорта за один месяц занимают около 280 МБ, но при импорте размер файла увеличивается до более 1 ГБ.

Учитывая ограничение размера 2 ГБ для файлов MDB, это немного беспокоит. Есть ли какие-либо методы, позволяющие избежать увеличения размера файла, кроме разбиения вставок на куски и сжатия между ними?

Обратите внимание, что никакие временные таблицы не создаются / удаляются во время процесса: просто вставляются в существующие таблицы.

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

Если бы это могло помочь, я мог бы предварительно обработать в sqlite.

Edit:

Просто чтобы добавить дополнительную информацию (некоторые уже перечислены в моих комментариях):

  • Данные генерируются в Python для каждой таблицы, а затем все записи для этого пакета таблиц вставляются через odbc
  • Вся обработка происходит в Python: все, что делает файл mdb - это хранение данных
  • Все вставляемые поля являются действительными (ни одно из них не исключено из-за нарушений уникального ключа и т. Д.)

Учитывая вышесказанное, я буду изучать, как отключить блокировку на уровне строк через odbc и рассмотреть возможность предварительной сортировки данных и / или удаления, а затем восстановления индексов. Спасибо за предложения.

Любые дальнейшие предложения все еще приветствуются.

Ответы [ 6 ]

4 голосов
/ 30 октября 2009

Вы уверены, что блокировка строки отключена? В моем случае отключение блокировки строк уменьшило раздувание более чем на 100 мегабайт при работе с 5-мегабайтным файлом. (другими словами, файл ячменя вырос после отключения блокировки строк примерно до 6 мегабайт). При включенной блокировке строки эта же операция приводит к получению файла размером более 100 мегабайт.

Блокировка строк является ОГРОМНЫМ источником раздувания во время операций с набором записей, так как она увеличивает размер каждой записи до размера страницы.

У вас здесь установлен ms-доступ или вы просто используете JET (JET - это механизм данных, который использует ms-access. Вы можете использовать JET без доступа).

Откройте базу данных в ms-access и перейдите:

Инструменты-> Параметры На вкладке «Дополнительно» снимите флажок: [] Открытие баз данных с использованием блокировки на уровне записи.

Это не только сделает ОГРОМНУЮ разницу в увеличении размера файла (bloat), но и ускорит процесс в 10 раз.

Здесь также есть параметр реестра, который вы можете использовать здесь.

И, Вы используете odbc или соединение oleDB?

Вы можете попробовать:

Set rs = Новый ADODB.Recordset С rs .ActiveConnection = RsCnn .Properties ("Jet OLEDB: гранулярность блокировки") = 1

Попробуйте настройку из доступа (измените настройку), выйдите, введите заново, а затем уплотните и восстановите. Затем запустите тестовый импорт ... проблема с раздуванием должна исчезнуть.

Вероятно, нет необходимости открывать базу данных с помощью блокировки строк. Если вы отключите эту функцию, то сможете уменьшить размер файла до минимума.

Подробнее об этом читайте здесь: Поддерживает ли ACEDAO блокировку на уровне строк?

3 голосов
/ 30 октября 2009

Следует обратить внимание на записи, которые присутствуют в запросах на добавление, но не вставлены в данные из-за дублированных значений ключа, пустых обязательных полей и т. Д. Access будет выделять пространство, занимаемое записями, которые не ' t вставлено.

О единственной важной вещи, которую я знаю, является обеспечение эксклюзивного доступа к файлу базы данных. Что может быть невозможно, если делать это в течение дня. Я заметил изменение в поведении с Jet 3.51 (используется в Access 97) на Jet 4.0 (используется в Access 2000), когда MDB-компоненты Access стали намного больше при добавлении записей. Я думаю, что если MDB используется несколькими людьми, то записи вставляются один раз на страницу 4k, а не столько, сколько может быть вставлено в страницу. Вероятно, потому что это ускорило операции вставки / обновления индекса.

Теперь сжатие действительно помещает столько же записей на одной странице 4k, сколько возможно, но это вам не поможет.

3 голосов
/ 30 октября 2009

Обычный прием, если это возможно в отношении схемы и семантики приложения, состоит в том, чтобы иметь несколько файлов MDB со связанными таблицами .

Кроме того, порядок выполнения вставок имеет значение в отношении способа увеличения размера файла ... Например: пакетные, по сравнению с одной / несколькими записями за один раз, отсортированные (относительно конкретного index (es)), количество индексов (как вы уже упоминали, некоторые из них легко удаляются на этапе вставки) ...

Ориентировочно предварительная обработка с сохранением, скажем, новых строк в отдельной связанной таблице, модой кучи (без индексов), затем сортировка / индексация этих данных является минимальной модой и "массовой загрузкой" это к своему реальному месту назначения. Подобная предварительная обработка в SQLite (намекала на вопрос) будет служить цели. Сохранить его "ВСЕ MDB", возможно, проще (меньше языков / процессов для изучения, меньше проблем взаимодействия [надеюсь, -)] ...)

РЕДАКТИРОВАТЬ : почему вставка записей в отсортированном / массовом режиме может замедлить рост файла MDB (вопрос от Tony Toews)
Одна из причин склонности файлов MDB к росту быстрее, чем скорость, с которой текст / данные добавляются к ним (и их аналогичная способность легко сжиматься), заключается в том, что при добавлении информации некоторые из узлов, составляющих индексы должны быть переупорядочены (для переполнения / перебалансировки и т. д.). Такое управление узлами, по-видимому, реализовано таким образом, который способствует скорости по сравнению с дисковым пространством и гармонией, и этот подход обычно довольно хорошо обслуживает простые приложения / небольшие данные. Я не знаю конкретной логики, используемой для такого управления, но я подозреваю, что в некоторых случаях операции узла приводят к тому, что определенный узел (или большая его часть) копируется заново, а старое местоположение просто помечается как свободное / неиспользуемое, но не удален / уплотненный / повторно. У меня есть «клинические» (хотя и немного устаревшие) доказательства того, что, выполняя массовые вставки, мы существенно ограничиваем количество возможностей для такого дублирования и, следовательно, замедляем рост.

Снова отредактируйте : После прочтения и обсуждения вещей от Тони Тоуэса и Альберта Каллала выясняется, что, возможно, более значительным источником вздутия , в частности в Jet Engine 4.0, является способ реализации блокировки . Поэтому важно установить базу данных в однопользовательском режиме, чтобы избежать этого. (Подробнее читайте в ответе Тони и Альберта.

1 голос
/ 31 октября 2009

Ваш скрипт выполняет один оператор INSERT на строку данных? Если это так, предварительная обработка данных в текстовый файл из многих строк, которые затем могут быть вставлены с помощью одного оператора INSERT, может повысить эффективность и сократить накопившийся временный код, который вызывает его раздувание.

Вы также можете убедиться, что INSERT выполняется без транзакций. То, произойдет ли это неявно, зависит от версии Jet и библиотеки интерфейса данных, которую вы используете для выполнения задачи. Убедившись, что он выключен, вы можете улучшить ситуацию.

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

0 голосов
/ 25 июня 2015

Файл -> Параметры -> Текущая база данных -> Проверить параметры ниже * Используйте формат кэша, совместимый с Microsoft Access 2010 и более поздними версиями. * Очистить кэш при закрытии

Затем ваш файл будет сохранен путем сжатия до исходного размера.

0 голосов
/ 30 октября 2009

Я могу подключиться из Access к Sqlite и выполнить запрос make table для импорта данных. Я использовал этот драйвер ODBC: http://www.ch -werner.de / sqliteodbc / и создал DNS пользователя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...