Удалите последовательные дубликаты: «Превышено число блокировок общего доступа к файлам» на 9 тыс. Записей из 1 млн. - PullRequest
0 голосов
/ 01 сентября 2018

Мне нужно удалить последовательные дубликаты записей из большой таблицы (она может содержать от 200 000 до 1 миллиона записей, и около половина записей будет удалена ).

DateTime уникален. Записи, где остальные поля соответствуют предыдущей записи, должны быть удалены, оставляя «первую» запись. (Непоследовательные дубликаты должны остаться.)

       DateTime        Field1   Field2   Field3  
 -------------------- -------- -------- -------- 
  2018-09-01 5:20:33      123      456      789  
  2018-09-01 5:20:34      123      456      789        ← delete
  2018-09-01 5:20:35      123      654      987  
  2018-09-01 5:20:36      234      567      890  
  2018-09-01 5:20:37      234      567      890        ← delete 
  2018-09-01 5:20:38      234      567      890        ← delete 
  2018-09-01 5:20:39      123      456      789                     

Я перебираю набор записей (упорядоченный по дате), чтобы удалить дубликаты, но когда я нажимаю около 9500 удалений, я получаю:

Error 3052: File sharing lock count exceeded.  
            Increase MaxLocksPerFile registry entry.

Согласно этим инструкциям , я мог бы увеличить значение в реестре или с помощью метода SetOption, однако Я не совсем понимаю, как это повлияет , поскольку Похоже, мне нужно увеличить значение с 9,500 по крайней мере 500,000 или более ... Я не уверен, но это кажется плохой идеей.


Упрощенная версия моего кода:

Sub example_DelDupes()
    Dim rs As Recordset, delCount As Long, rCount as long
    Dim thisRecord As String, prevRecord As String
    Set rs = CurrentDb.OpenRecordset("select * from myTable order by DateTime")
    With rs
        .MoveLast            'so I can get a recordcount...
        .MoveFirst
        rCount = .RecordCount '...required for progress bar (not shown)

        Do While Not .EOF
            thisRecord = !field1$ & !field2$ & !field3$ 'actually 
            If thisRecord = prevRecord Then
                .Delete                      'delete this record
                delCount = delCount + 1
            Else
                prevRecord = thisRecord
            End If
            .MoveNext
        Loop

        .Close
    End With
    Set rs = Nothing
End Sub

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


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

Мысли? Спасибо! img

1 Ответ

0 голосов
/ 01 сентября 2018

Я бы удалил все в одном запросе вместо того, чтобы перебирать набор записей.

Вы можете использовать вложенный подзапрос, чтобы проверить, удовлетворяет ли строка перед вашим условием:

DELETE o.*
FROM MyTable o
WHERE EXISTS(
    SELECT 1 
    FROM MyTable i 
    WHERE o.Field1 = i.Field1 And o.Field2 = i.Field2 AND o.Field3 = i.Field3 
    AND EXISTS (
        SELECT  1
        FROM MyTable i2 
        WHERE i2.DateTime < o.DateTime
        HAVING Max(i2.DateTime) = i.DateTime
    )
)
...