Импорт базы ФМС. тоже не медленно.

Автор:tema
Дата:20.11.2014
Просмотров:3314
Скачиваний:2069
Оценка:, Оценок - 1
Сохранить в файле

Обсудить в форуме

Описание

Посмотрел как работает импорт файла 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. Затем грузятся только обновления, полученные приведённым алгоритмом. Обновления грузятся кодом примера. При остутствии данных в кэше загрузка занимает около минуты времени.

Текст примера

 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 */