Как ускорить массовый «упор» в Microsoft Access - PullRequest
0 голосов
/ 03 января 2019

Я выполняю 'upsert' в Access, используя словарь VBA.Я зацикливаю ключи моего словаря, и если ключ существует в таблице Access, я обновляю его.Если нет, он вставляет его.Однако моя таблица содержит более 200 тыс. Строк, и это заставляет код работать невероятно медленно (например, 5 минут, а не 5%), поскольку итерация требует, чтобы во всей таблице был найден «LOC» (мой ключ).

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

Sub UpdateDatabase(dict As Object)

Dim db As Database
Dim rs As DAO.Recordset

Set db = OpenDatabase("C:\XXX\myDB.accdb")
Set rs = db.OpenRecordset("MyTable", dbOpenDynaset)


For Each varKey In dict.Keys()

    'Table is searched for key
    rs.FindFirst "[LOCID] = '" & varKey & "'"
    If rs.NoMatch Then
        'If the key was not found, insert it
        rs.AddNew
        rs!LOCID = varKey
        rs![Status] = "To Start"
        rs.Update
    Else
        'If the key was found, update its status
        rs.Edit
        rs![Status] = "Done"
        rs.Update
    End If
Next

rs.Close
db.Close

Application.StatusBar = False
End Sub

РЕДАКТИРОВАТЬ:

Я нашел узкое место в приведенном выше коде.Это строка:

rs.FindFirst "[LOCID] = '" & varKey & "'"

Используется для определения, находится ли ключ в базе данных или нет.Удаление этого (и простая вставка новых данных) ускоряет процесс, и это делается за считанные секунды.Есть ли быстрый способ определить, находится ли значение уже в таблице?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

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

это наиболее часто встречающееся различие между «программистом» и «разработчиком базы данных» ......

0 голосов
/ 03 января 2019

Сначала: насколько велика коллекция диктов.(5, 10 или 1000 ???).

Далее, LOCID - индексированный столбец в этой таблице «MyTable».

Если LOCID уже является индексированным столбцом, вы можете использовать следующий код.Это должно ускорить процесс примерно в 100 или более раз:

Предполагается, что таблица НЕ является связанной таблицей, но фактически является таблицей в базе данных.

Обратите внимание, что вы должныоткройте таблицу как «действующую» - это значение по умолчанию, поэтому я удалил dbOpenDynaset)

Этот код поможет:

Dim db        As DAO.Database
Dim rs        As DAO.Recordset


Set db = OpenDatabase("C:\XXX\myDB.accdb")
Set rs = db.OpenRecordset("MyTable")     ' <--- note this!!!

rs.Index = "LOCID"

For Each varKey In dict.Keys()

  'Table is searched for key
  rs.Seek "=", varKey
  If rs.NoMatch = True Then
      'If the key was not found, insert it
      rs.AddNew
      rs!LOCID = varKey
      rs![Status] = "To Start"
      rs.Update
  Else
      'If the key was found, update its status
      rs.Edit
      rs![Status] = "Done"
      rs.Update
  End If
Next

rs.Close
db.Close

Вам также необходимо определитьимя фактического индекса по столбцу LOCID.Я использовал LOCID выше, но вам лучше всего открыть базу данных с доступом, перевернуть таблицу в режиме конструктора, а затем нажать кнопку «индексы» на ленте.Если LOCID является первичным ключом, то хорошей возможностью является то, что индекс называется PrimaryKey.Таким образом, вам нужно имя индекса.

...