Импорт базы ФМС. тоже не медленно.
Сохранить в файлеОбсудить в форуме
Описание
Посмотрел как работает импорт файла list_of_expired_passports.csv и стало мне грустно. Долго и на планировщик не повесишь. Пользовать альтернативные варианты тоже не хотелось, для сохранения совместимости с RS. В результате родилась такая технология. Первый этап происходит на Unix машине, которая имеет выход в интернет. Код скрипта не привожу, думаю каждый напишет его под свою конфигурацию сам, опишу лишь основные моменты.
1) получаем файл при помощи
wget http://www.fms.gov.ru/upload/expired-passports/list_of_expired_passports.csv.bz2
2) распаковываем
bzip2 -d list_of_expired_passports.csv.bz2
3) сортируем и добавляем дату в имя при помощи
sort list_of_expired_passports.csv >list_of_expired_passports.$y$m$d.csv
4) сравниваем с предыдущим при помощи
comm -3 list_of_expired_passports.$y$m$d.csv list_of_expired_passports.$old_y$old_m$old_d.csv >fms_diff_$y$m$d.txt
Далее, уже машина с АБС забирает файл fms_diff_yyyymmdd.txt из буферной зоны и можно грузить в RS. Ниже код функции импорта.
Всё это можно организовать и на машине с RS-ом через GnuUtils, но sort отожрёт пару гигов оперативки минут на десять.
PS. Стоит подчеркнуть, что после "comm -3" получается файл, в котором нет строк, существующих и в предыдущем и в текущем файле. Новые данные начинаются с начала строки, а данные отсутствующие в новой версии файла (подлежащие удалению) начинаются с табулятора.
Первый раз грузится весь файл штатной процедурой RS. Затем грузятся только обновления, полученные приведённым алгоритмом. Обновления грузятся кодом примера. При остутствии данных в кэше загрузка занимает около минуты времени.
1) получаем файл при помощи
wget http://www.fms.gov.ru/upload/expired-passports/list_of_expired_passports.csv.bz2
2) распаковываем
bzip2 -d list_of_expired_passports.csv.bz2
3) сортируем и добавляем дату в имя при помощи
sort list_of_expired_passports.csv >list_of_expired_passports.$y$m$d.csv
4) сравниваем с предыдущим при помощи
comm -3 list_of_expired_passports.$y$m$d.csv list_of_expired_passports.$old_y$old_m$old_d.csv >fms_diff_$y$m$d.txt
Далее, уже машина с АБС забирает файл fms_diff_yyyymmdd.txt из буферной зоны и можно грузить в RS. Ниже код функции импорта.
Всё это можно организовать и на машине с RS-ом через GnuUtils, но sort отожрёт пару гигов оперативки минут на десять.
PS. Стоит подчеркнуть, что после "comm -3" получается файл, в котором нет строк, существующих и в предыдущем и в текущем файле. Новые данные начинаются с начала строки, а данные отсутствующие в новой версии файла (подлежащие удалению) начинаются с табулятора.
Первый раз грузится весь файл штатной процедурой RS. Затем грузятся только обновления, полученные приведённым алгоритмом. Обновления грузятся кодом примера. При остутствии данных в кэше загрузка занимает около минуты времени.
Текст примера
macro ImportFmsDiff(d) var tmStart=Time(); var afInvalp=TArray(); var iStr:Integer=0; var iInserted:Integer=0; var iInsErr:Integer=0; var iDeleted:Integer=0; var iDelErr:Integer=0; var iIgnoreAdd:Integer=0; var iIgnoreDel:Integer=0; var str:String; var strSer, strNum; var iComa, iStart; var strAction; var cFile:String, iFile:Integer; macro GetFileName var strDate=String(d); /* 12.45.7890 */ return "fms_diff_"+SubStr(strDate,7)+SubStr(strDate,4,2)+SubStr(strDate,1,2)+".txt"; end; /* macro GetFileName */ Macro OpenFiles() var i:Integer; var strC:String; var strName; for(i,0,10,1) if (i<10) strC=String(i); else strC="x"; end; strName="invalp"+strC+".dbt"; afInvalp[i]=TBFile(strName,"W",0,strName,"fm.def"); end; end; /* Macro OpenFiles() */ var strFileName:String= GetFileName(); var f=TStreamDoc (strFileName, "R"); OpenFiles(); while (f.ReadLine(str)) iStr=iStr+1; if (SubStr(str,1,1)=="\t") iStart=1; strAction="del"; else iStart=0; strAction="add"; end; iComa=Index (str, ",", iStart+1); strSer=SubStr(str,iStart+1,iComa-1-iStart); strNum=SubStr(str,iComa+1); if ((StrLen(strSer)==4) and (StrLen(strNum)==6) and StrIsNumber(strSer) and StrIsNumber(strNum)) /* PrintLn(strAction+" "+strSer +" "+strNum); */ cFile=SubStr(strSer,1,1); iFile=Int(cFile); afInvalp[iFile].rec.Series=Int(strSer); afInvalp[iFile].rec.Number=Int(strNum); if (afInvalp[iFile].GetEQ) /* есть запись */ if (iStart==0) /* надо добавить, всё хорошо она уже есть */ iIgnoreAdd=iIgnoreAdd+1; else /* надо удалить */ if (afInvalp[iFile].Delete) iDeleted=iDeleted+1; else iDelErr=iDelErr+1; end; end; else /* нет записи */ if (iStart==0) /* надо добавить, добавляем */ if (afInvalp[iFile].Insert) iInserted=iInserted+1; else iInsErr=iInsErr+1; end; else /* надо удалить, всё хорошо её и так нет */ iIgnoreDel=iIgnoreDel+1; end; end; else PrintLN("Ошибка формата. Строка "+iStr+" "+str); end; end; [Строк в файле ######](iStr); [ ]; [Записей добавлено ######](iInserted); [Ошибок добавления ######](iInsErr); [Пропущено добалений ######](iIgnoreAdd); [ ]; [Записей удалено ######](iDeleted); [Ошибок удаления ######](iDelErr); [Пропущено удалений ######](iIgnoreDel); [ ]; var tmEnd=Time(); PrintLn("Время: "+String(tmEnd-tmStart)+" "+tmStart+"-"+tmEnd); end; /* macro ImportFmsDiff */