Подскажите, пожалуйста как оптимально по скорости/памяти решить следующую задачу:
Имеются ежемесячные выгрузки из внешней системы, на которую я никак повлиять не могу.
Выгрузки представляют из себя текстовые файлы с разделителямя (зачисления).
Размер файла 1,5 - 2 ГБ и количество строк более 10 млн. Каждая строка = 1 зачисление , около 30 полей, из которых мне нужно только 5. (ФИО, Сумма, Дата операции, Дата рождения, тип зачисления) . Для одного клиента может быть несколько зачислений (строчек).
Есть справочник клиентов (текстовый файл ~4 млн.записей), в котором хранятся только ФИО + Дата рождения
Мне необходимо из первого файла выбрать клиентов которые отсутствуют в справочнике и удовлетворяют определенным условиям. Таких ежемесячно бывает примерно 30-40 тыс. ФИО + ДР отобранных добавляем в справочник.
Соответственно, чтобы решить данную задачу мне сейчас необходимо понять следующее:
1. Как правильно с точки зрения скорости/памяти считать текстовый файл в массив если я не знаю количество строчек в нем.Мне нужно будет в какой-то момент менять размерность массива, как это сделать лучше?
2. Прежде чем сравнивать массивы, по-любому придется их сортировать по полю ФИО. Подскажите пожалуйста самый быстрый алгоритм, который не использует вспомогательные массивы. Не хочется делать дополнительные копии массива в памяти.
Реализовал свою идею через Словари. Скорость приемлемая, за исключением последнего шага. В котором я пытаюсь сохранить Словарь в файл. На меленьких файлах скорость приемлемая, но когда размер справочника 4 млн строк, а размер занимаемой памяти Excel около 1 Гб,
сохранение идет очень долго - в минуту не более 1000 строк :
Код |
Public Sub ClosePensSprav(FileName As String)
Dim txtFile As TextStream
Dim TmpString As String
Dim Ndx As Long
Dim lLowVal As Long
Dim lHighVal As Long
Dim lStep As Long
If Not (FSO.FileExists(FileName)) Then FSO.CreateTextFile (FileName)
Set txtFile = FSO.OpenTextFile(FileName, ForWriting)
lHighVal = PensSprav.Count
lStep = CLng(lHighVal / 100)
For Ndx = 0 To PensSprav.Count - 1
lLowVal = Ndx
If lLowVal Mod lStep = 0 Then Application.StatusBar = "Сохранение справочника:" & FSO.GetFileName(FileName) & ": " & sObrStr(lLowVal, lHighVal) & sSuff(CInt(lLowVal / lHighVal * 100))
TmpString = PensSprav.Keys(Ndx) & "|" & PensSprav.Items(Ndx)
txtFile.WriteLine (TmpString)
DoEvents
Next Ndx
txtFile.Close
Application.StatusBar = False
Set txtFile = Nothing
Set PensSprav = Nothing
End Sub |
| |