Как стать автором
Обновить

Импорт полной базы ФИАС за 9 часов, How To

Время на прочтение12 мин
Количество просмотров6.8K

Введение

Год назад ФНС прекратила выкладывать базу ФИАС в формате DBF, теперь база доступна только в формате XML. Данные из DBF можно было вставлять в базу как есть, с XML так не получается, перед вставкой в базу, XML надо парсить, и это занимает время. Полная база ФИАС занимает 290 GB, парсинг такого объёма занимает значительное время.

Это время можно сократить, если парсинг распараллелить. Для этого надо разделить файлы на группы и каждую группу обрабатывать отдельно, но одновременно (процессоры давно многоядерные, надо не забывать этим пользоваться). Кроме того, конечно, надо использовать потоковый парсер, чтобы не ждать полной загрузки файла в оперативную память.

Я разработал несколько скриптов для создания и импорта базы. Эта статья будет о том как с помощью этих скриптов развернуть базу ФИАС за 9 часов на 6-ти ядерном процессоре.

Итоги

Странно начинать с итогов, но это интересней чем вникать в подробности, поэтому сначала кратко, а потом всё более и более подробно.

Алгоритм

  1. Скачать с сервера ФНС полную версию БД (https://fias.nalog.ru/Updates) 36 GB

  2. Развернуть архив, файлы с данными займут 300 GB

  3. Установить пакет для создания таблиц БД

  4. Установить пакет для импорта файлов

  5. Скопировать скрипты из исходников пакетов в отдельную директорию

  6. Разбить директории с данными регионов на равные по весу группы (каждая группа регионов будет импортироваться отдельным процессом PHP)

  7. Для каждой группы сделать копию скрипта импорта, в скрипте отредактировать список регионов в соответствии с группой

  8. Выполнить скрипт создания таблиц

  9. Запустить копии скриптов импорта в отдельных окнах терминала (параллельное выполнение)

  10. Выполнить скрипт создания индексов

  11. Have fun

Затраченное время

  1. 01-22 регионы, 54 GB - Rows was read is 301 929 373 duration is 08:20:06

  2. 23-36, 59 GB - Rows was read is 326 217 126 duration is 08:51:45

  3. 37-52, 63 GB - Rows was read is 342 339 705 duration is 09:15:50

  4. 53-67, 57 GB - Rows was read is 315 815 574 duration is 08:36:36

  5. 68-99, 55 GB - Rows was read is 285 073 083 duration is 07:53:59

Дополнительно к этому, создание индексов, ещё час - Creation index duration is 01:05:17. Запускать создание индексов параллельно особого смысла не имеет, потому что загрузка диска была 100% пополам с промежутками загрузки на 5%, чтобы совсем не было простоя диска, можно запустить два обработчика на создание индексов. Это сэкономит минут 20.

Использованное аппаратное обеспечение

Жёсткий диск

WDC WD40PURX-64AKYY0

Capacity:	3.6 TB
Type:	HDD

Не самый медленный диск, во время импорта его скорости вполне хватало, загрузка не превышала 50%. Когда я развернул базу на "быстром" NVMe диске, импорт занял 40 часов, на этот "медленный" диск база развернулась за 42:58:16, + 1 час на индексы, вместе 44 часа, это на четыре часа дольше, да, разница есть, но не драматичная.

База без индексов занимает 190 GB, с индексами весит столько же сколько исходные файлы: 231 GB (248,504,378,147 bytes), надо сказать, что у меня сделан всего 1 индекс в каждой таблице, для работы с базой, мне кажется, надо минимум пять индексов.

Процессор

Intel(R) Core(TM) i5-9400 CPU @ 2.90GHz

Base speed:	2.90 GHz
Sockets:	1
Cores:	6
Logical processors:	6
Virtualization:	Enabled
L1 cache:	384 KB
L2 cache:	1.5 MB
L3 cache:	9.0 MB

Загрузка процессора для пяти обработчиков упёрлась в потолок 100%, для четырёх - так же 100%, 3 - 85%, 2 - 55%, 1 - 35%. Памяти потребовалось: 8 Mb на процесс PHP и 4 Mb на процесс PostreSql, чтение с диска PHP - 2 Mb/s, PostreSql - 1.5 Mb/s.

В следующий раз я разобью файлы (регионы) на 4 группы, и импорт буду делать в 4 потока, пять это перебор для моей машины.

Про оперативную память нет смысла писать, потому что как видите, её объём не значителен.

How To

Настало время рассказать в подробностях.

Ставим пакеты

composer require sbwerewolf/fias-gar-schema-deploy-tool
composer require sbwerewolf/fias-gar-data-import-tool

Устанавливаем пакет для журналирования, на свой вкус.

composer require monolog/monolog

Логи можно вообще не писать, тогда в скрипте в качестве логера надо использовать \Psr\Log\NullLogger .

Копируем скрипты и SQL шаблоны создания таблиц

cp ./vendor/sbwerewolf/fias-gar-data-import-tool/test/* ./
cp ./vendor/sbwerewolf/fias-gar-schema-deploy-tool/test/* ./
cp ./config.env.example ./config.env

Копирование гладко не пройдёт, потому что в исходниках совпадают и файлы и директории, если будет предложено перезаписать файлы, то надо отказаться.

Файл "config.env.example" нужен из исходников "fias-gar-data-import-tool".

Проверьте, что директории скопировались вместе с файлами, в директории templates должно быть 28 директорий, и в каждой директории 2-4 файла.

Правим конфиг

Открываем config.env, правим настройки.

LOGIN PASSWORD DSN меняем под СУБД, в выбранной БД создаём схему для ФИАС, название схемы пишем в SCHEMA. У меня СУБД - Постгрес 14.

СУБД должна поддерживать секционирование. Может быть MySQL тоже умеет, но я не уверен за правильность синтаксиса. Синтаксис придётся править в шаблонах, для каждой из 28-ми таблиц.

В моих скриптах не используется ORM, поэтому извините, под вашу СУБД придётся поработать руками.

DO_IMPORT_WITH_CHECK присваиваем FALSE - чтобы перед вставкой не проверять существование записи, это будет лишний SELECT. При импорте значение FALSE , при обновлении базы - TRUE .

XML_FILES_PATH записываем путь к развёрнутому архиву ФИАС.

BATCH_SIZE это количество записей до выполненияCOMMIT, устанавливаем на свой вкус, по умолчанию 100 000. Я ставил 1 000 000, в этом случае, пауза между камитами просто увеличилась в 10 раз, ускорения не заметил.

Настраиваем скрипты

install-storage.php

Скрипт создания таблиц.

Настраиваем журналирование

Ниже создаётся логгер, запись будет и в файл и в консоль.

$logger = new Logger('common');

$pathComposer = new Path(__DIR__);
$logsPath = $pathComposer->make(
    [
        'logs',
        pathinfo(__FILE__, PATHINFO_FILENAME) . '-' . time() . '.log',
    ]
);

$writeHandler = new StreamHandler($logsPath);
$logger->pushHandler($writeHandler);

$logger->pushProcessor(function ($record) {
    /** @var LogRecord $record */
    echo "{$record->datetime} {$record->message}" . PHP_EOL;

    return $record;
});

Логи можно вообще не писать, тогда в скрипте в качестве логера надо использовать \Psr\Log\NullLogger .

Настройку логгера надо повторить в каждом скрипте (три скрипта - три раза).

Задаём путь к шаблонам SQL скриптов создания таблиц, директории перечисляем как элементы массива.

$templatesPath = $pathComposer->make(['template']);

Корневая директория задаётся при создании экземпляра $pathComposer = new Path(__DIR__);

Задаём список таблиц (имена папок с шаблонами скриптов для конкретной таблицы)

$templatesKitList = [
    'ADDHOUSETYPES',
    'ADDR_OBJ_DIVISION',
    'ADDR_OBJ_PARAMS',
    'ADDRESSOBJECTS',
    'ADDRESSOBJECTTYPES',
    'ADM_HIERARCHY',
    'APARTMENTS',
    'APARTMENTS_PARAMS',
    'APARTMENTTYPES',
    'CARPLACES',
    'CARPLACES_PARAMS',
    'CHANGE_HISTORY',
    'HOUSES',
    'HOUSES_PARAMS',
    'HOUSETYPES',
    'MUN_HIERARCHY',
    'NDOCKINDS',
    'NDOCTYPES',
    'NORMDOCS',
    'OBJECTLEVELS',
    'OPERATIONTYPES',
    'PARAMTYPES',
    'REESTR_OBJECTS',
    'ROOMS',
    'ROOMS_PARAMS',
    'ROOMTYPES',
    'STEADS',
    'STEADS_PARAMS',
];
$command->run($templatesKitList, 'create-table.php')

В зависимости от того как вы собираетесь использовать базу, можно удалить создание каких то таблиц, например "*_PARAMS", "NORMDOCS", "CARPLACES", "ROOMS", "STEADS".

Задаём таблицы для которых нужно сделать секционирование по региону (таблицы с колонкой REGION), файлы этих таблиц лежат в директории региона.

$templatesKitList = [
    'ADDR_OBJ_DIVISION',
    'ADDR_OBJ_PARAMS',
    'ADDRESSOBJECTS',
    'ADM_HIERARCHY',
    'APARTMENTS',
    'APARTMENTS_PARAMS',
    'CARPLACES',
    'CARPLACES_PARAMS',
    'CHANGE_HISTORY',
    'HOUSES',
    'HOUSES_PARAMS',
    'MUN_HIERARCHY',
    'NORMDOCS',
    'REESTR_OBJECTS',
    'ROOMS',
    'ROOMS_PARAMS',
    'STEADS',
    'STEADS_PARAMS',
];
$command->run(
    $templatesKitList,
    'create-partition.php',
    false,
    99,
    1

);

Соответственно, удаляем таблицы которые были удалены из первого списка.

data-import.php

Скрипт для импорта XML файлов в БД.

Делаем пять копий (для параллельной обработки в пять потоков).

cp ./data-import.php ./data-import-1.php
cp ./data-import.php ./data-import-2.php
cp ./data-import.php ./data-import-3.php
cp ./data-import.php ./data-import-4.php
cp ./data-import.php ./data-import-5.php

В каждой копии скрипта импорта, настраиваем параметры выполнения команды импорта (класс $options = new ImportOptions()).

$options = new ImportOptions(
    $doAddNewWithCheck,
    [
        AddHouseTypes::class =>
            'AS_ADDHOUSE_TYPES_20*.{x,X}{m,M}{l,L}',
        AddressObjectTypes::class =>
            'AS_ADDR_OBJ_TYPES_20*.{x,X}{m,M}{l,L}',
        ApartmentTypes::class =>
            'AS_APARTMENT_TYPES_20*.{x,X}{m,M}{l,L}',
        HouseTypes::class =>
            'AS_HOUSE_TYPES_20*.{x,X}{m,M}{l,L}',
        NormativeDocumentsKinds::class =>
            'AS_NORMATIVE_DOCS_KINDS_20*.{x,X}{m,M}{l,L}',
        NormativeDocumentsTypes::class =>
            'AS_NORMATIVE_DOCS_TYPES_20*.{x,X}{m,M}{l,L}',
        ObjectLevels::class =>
            'AS_OBJECT_LEVELS_20*.{x,X}{m,M}{l,L}',
        OperationTypes::class =>
            'AS_OPERATION_TYPES_20*.{x,X}{m,M}{l,L}',
        ParamTypes::class =>
            'AS_PARAM_TYPES_20*.{x,X}{m,M}{l,L}',
        RoomTypes::class =>
            'AS_ROOM_TYPES_20*.{x,X}{m,M}{l,L}',
    ],
    '{1,2,3,4,5,6,7,8,9,0}{1,2,3,4,5,6,7,8,9,0}',
    [
        AddressObjects::class =>
            'AS_ADDR_OBJ_20*.{x,X}{m,M}{l,L}',
        AddressObjectDivision::class =>
            'AS_ADDR_OBJ_DIVISION_20*.{x,X}{m,M}{l,L}',
        AddressObjectParams::class =>
            'AS_ADDR_OBJ_PARAMS_20*.{x,X}{m,M}{l,L}',
        AdministrativeHierarchy::class =>
            'AS_ADM_HIERARCHY_20*.{x,X}{m,M}{l,L}',
        Apartments::class =>
            'AS_APARTMENTS_20*.{x,X}{m,M}{l,L}',
        ApartmentsParams::class =>
            'AS_APARTMENTS_PARAMS_20*.{x,X}{m,M}{l,L}',
        CarPlaces::class =>
            'AS_CARPLACES_20*.{x,X}{m,M}{l,L}',
        CarPlacesParams::class =>
            'AS_CARPLACES_PARAMS_20*.{x,X}{m,M}{l,L}',
        ChangeHistory::class =>
            'AS_CHANGE_HISTORY_20*.{x,X}{m,M}{l,L}',
        Houses::class =>
            'AS_HOUSES_20*.{x,X}{m,M}{l,L}',
        HousesParams::class =>
            'AS_HOUSES_PARAMS_20*.{x,X}{m,M}{l,L}',
        MunicipalHierarchy::class =>
            'AS_MUN_HIERARCHY_20*.{x,X}{m,M}{l,L}',
        NormativeDocuments::class =>
            'AS_NORMATIVE_DOCS_20*.{x,X}{m,M}{l,L}',
        ReestrObjects::class =>
            'AS_REESTR_OBJECTS_20*.{x,X}{m,M}{l,L}',
        Rooms::class =>
            'AS_ROOMS_20*.{x,X}{m,M}{l,L}',
        RoomsParams::class =>
            'AS_ROOMS_PARAMS_20*.{x,X}{m,M}{l,L}',
        Steads::class =>
            'AS_STEADS_20*.{x,X}{m,M}{l,L}',
        SteadsParams::class =>
            'AS_STEADS_PARAMS_20*.{x,X}{m,M}{l,L}',
    ],
);

Первый аргумент (логическая переменная) отвечает за выполнение проверки существования записи перед её добавлением. В скрипте значение этого аргумента задаётся переменной окружения DO_IMPORT_WITH_CHECK.

$doAddNewWithCheck,

Соответственно при разворачивании базы нам эта проверка не нужна, передаём значение false. При обновлении базы, значение должно быть true.

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

    [
        AddHouseTypes::class =>
            'AS_ADDHOUSE_TYPES_20*.{x,X}{m,M}{l,L}',
        AddressObjectTypes::class =>
            'AS_ADDR_OBJ_TYPES_20*.{x,X}{m,M}{l,L}',
        ApartmentTypes::class =>
            'AS_APARTMENT_TYPES_20*.{x,X}{m,M}{l,L}',
        HouseTypes::class =>
            'AS_HOUSE_TYPES_20*.{x,X}{m,M}{l,L}',
        NormativeDocumentsKinds::class =>
            'AS_NORMATIVE_DOCS_KINDS_20*.{x,X}{m,M}{l,L}',
        NormativeDocumentsTypes::class =>
            'AS_NORMATIVE_DOCS_TYPES_20*.{x,X}{m,M}{l,L}',
        ObjectLevels::class =>
            'AS_OBJECT_LEVELS_20*.{x,X}{m,M}{l,L}',
        OperationTypes::class =>
            'AS_OPERATION_TYPES_20*.{x,X}{m,M}{l,L}',
        ParamTypes::class =>
            'AS_PARAM_TYPES_20*.{x,X}{m,M}{l,L}',
        RoomTypes::class =>
            'AS_ROOM_TYPES_20*.{x,X}{m,M}{l,L}',
    ],

Таблицы справочников надо импортировать только один раз, их импортировать должен только один скрипт, в других скриптах этот список должен быть пустым.

Третий аргумент (строка) определяет маску для выбора директорий с регионами. Соответственно делаем копии этого скрипта по количеству потоков обработки.

'{1,2,3,4,5,6,7,8,9,0}{1,2,3,4,5,6,7,8,9,0}',

У меня было пять копий, с такими значениями:

'{01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22}',
'{23,24,25,26,27,28,29,30,31,32,33,34,35,36}',
'{37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52}',
'{53,54,55,56,57,58,59,60,61,62,63,64,65,66,67}',
'{99,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95}',

Четвёртый аргумент (массив), это список таблиц для каждого региона, лишние можно удалить, для каждого региона в этих таблицах будут созданы партиции.

    [
        AddressObjects::class =>
            'AS_ADDR_OBJ_20*.{x,X}{m,M}{l,L}',
        AddressObjectDivision::class =>
            'AS_ADDR_OBJ_DIVISION_20*.{x,X}{m,M}{l,L}',
        AddressObjectParams::class =>
            'AS_ADDR_OBJ_PARAMS_20*.{x,X}{m,M}{l,L}',
        AdministrativeHierarchy::class =>
            'AS_ADM_HIERARCHY_20*.{x,X}{m,M}{l,L}',
        Apartments::class =>
            'AS_APARTMENTS_20*.{x,X}{m,M}{l,L}',
        ApartmentsParams::class =>
            'AS_APARTMENTS_PARAMS_20*.{x,X}{m,M}{l,L}',
        CarPlaces::class =>
            'AS_CARPLACES_20*.{x,X}{m,M}{l,L}',
        CarPlacesParams::class =>
            'AS_CARPLACES_PARAMS_20*.{x,X}{m,M}{l,L}',
        ChangeHistory::class =>
            'AS_CHANGE_HISTORY_20*.{x,X}{m,M}{l,L}',
        Houses::class =>
            'AS_HOUSES_20*.{x,X}{m,M}{l,L}',
        HousesParams::class =>
            'AS_HOUSES_PARAMS_20*.{x,X}{m,M}{l,L}',
        MunicipalHierarchy::class =>
            'AS_MUN_HIERARCHY_20*.{x,X}{m,M}{l,L}',
        NormativeDocuments::class =>
            'AS_NORMATIVE_DOCS_20*.{x,X}{m,M}{l,L}',
        ReestrObjects::class =>
            'AS_REESTR_OBJECTS_20*.{x,X}{m,M}{l,L}',
        Rooms::class =>
            'AS_ROOMS_20*.{x,X}{m,M}{l,L}',
        RoomsParams::class =>
            'AS_ROOMS_PARAMS_20*.{x,X}{m,M}{l,L}',
        Steads::class =>
            'AS_STEADS_20*.{x,X}{m,M}{l,L}',
        SteadsParams::class =>
            'AS_STEADS_PARAMS_20*.{x,X}{m,M}{l,L}',
    ],

Разбить регионы на группы можно любым образом, с учётом количества ядер у вашего сервера.

create-indexes.php

Скрипт создания индексов.

Снова редактируем список таблиц для которых будем создавать индексы.

$templatesKitList = [
    'ADDHOUSETYPES',
    'ADDRESSOBJECTTYPES',
    'APARTMENTTYPES',
    'HOUSETYPES',
    'NDOCKINDS',
    'NDOCTYPES',
    'OBJECTLEVELS',
    'OPERATIONTYPES',
    'PARAMTYPES',
    'ROOMTYPES',
    'ADDR_OBJ_DIVISION',
    'ADDR_OBJ_PARAMS',
    'ADDRESSOBJECTS',
    'ADM_HIERARCHY',
    'APARTMENTS',
    'APARTMENTS_PARAMS',
    'CARPLACES',
    'CARPLACES_PARAMS',
    'CHANGE_HISTORY',
    'HOUSES',
    'HOUSES_PARAMS',
    'MUN_HIERARCHY',
    'NORMDOCS',
    'REESTR_OBJECTS',
    'ROOMS',
    'ROOMS_PARAMS',
    'STEADS',
    'STEADS_PARAMS',
];
$command->run($templatesKitList, 'create-index.php');

Какие индексы будут созданы можно посмотреть и переделать под себя в шаблонах.

Запускаем скрипты

Сначала создаём таблицы. Перед этим, конечно, включаем OPCache и отключаем дебагер (у меня xDebug), всё это делается в php.ini.

[opcache]
; Determines if Zend OPCache is enabled
opcache.enable=1
[xDebug]
;zend_extension = xdebug

Создаём таблицы

Запускам скрипт

php ./install-storage.php

Через минуту схема БД будет готова

Creation tables duration is 00:01:10

Запускам импорт

Теперь в отдельных окнах терминала запускаем собственно импорт

php ./data-import1.php

Аналогичным образом запускаем остальные копии скрипта импорта базы.

Скрипт начнёт работу, в консоли будет написано:

Script is starting
2023-02-03T05:06:58.107703+05:00 Script is starting
2023-02-03T05:06:58.198173+05:00 Run import FIAS GAR files from `D:\WORK\fias-gar\gar_xml`, with commit each `100 000` operations
2023-02-03T05:06:58.198461+05:00 Import starting
2023-02-03T05:06:58.218593+05:00 Starting common reference import
2023-02-03T05:06:58.218764+05:00 Start import files of pattern AS_ADDHOUSE_TYPES_20*.{x,X}{m,M}{l,L}
2023-02-03T05:06:58.431129+05:00 Starting import file D:\WORK\fias-gar\gar_xml\AS_ADDHOUSE_TYPES_20221222_86d52a97-cf6d-4329-8f55-0723b3feda90.XML
2023-02-03T05:06:58.460446+05:00 Rows read `4`, success Operations `4`, success Inserts `4`, insert Affected `4`, failure Inserts `0`, success Updates `0`, update Affected `0`, failure Updates `0`
2023-02-03T05:06:58.461465+05:00 Finish import files of pattern AS_ADDHOUSE_TYPES_20*.{x,X}{m,M}{l,L}

Каждые 100 000 (BATCH_SIZE) записей будет выводиться статистика:

2023-02-03T05:08:04.095876+05:00 Rows read `500 000`, success Operations `500000`, success Inserts `500000`, insert Affected `500000`, failure Inserts `0`, success Updates `0`, update Affected `0`, failure Updates `0`
2023-02-03T05:08:04.123922+05:00 Batch duration is 00:00:12 795 ms 521 mcs 500 ns, rows was read is `500 000`, mem allocated is `2`Mb, import processing with `500000` success Operations

Ждём 8 часов :)) По завершению работы скрипта будет подведена статистика:

2023-02-03T13:27:01.834772+05:00 Rows read `301 900 000`, success Operations `301900000`, success Inserts `301900000`, insert Affected `301900000`, failure Inserts `0`, success Updates `0`, update Affected `0`, failure Updates `0`
2023-02-03T13:27:01.835855+05:00 Batch duration is 00:00:08 723 ms 752 mcs 100 ns, rows was read is `301 900 000`, mem allocated is `2`Mb, import processing with `301900000` success Operations
2023-02-03T13:27:04.426001+05:00 Rows read `301 929 373`, success Operations `301929373`, success Inserts `301929373`, insert Affected `301929373`, failure Inserts `0`, success Updates `0`, update Affected `0`, failure Updates `0`
2023-02-03T13:27:04.426257+05:00 Finish import files of pattern AS_STEADS_PARAMS_20*.{x,X}{m,M}{l,L}
2023-02-03T13:27:04.426419+05:00 Finish region data import
2023-02-03T13:27:04.427513+05:00 Batch duration is 00:00:02 591 ms 510 mcs 900 ns, rows was read is `301 929 373`, mem allocated is `2`Mb, import processing with `301929373` success Operations
2023-02-03T13:27:04.427642+05:00 Rows was read is `301 929 373`, import was processed with `301929373` success operations, max mem allocated is `2`Mb
2023-02-03T13:27:04.427753+05:00 Import duration is 08:20:06 469 ms 147 mcs 400 ns
2023-02-03T13:27:04.427842+05:00 Script is finished

Создаём индексы

Для ускорения можно создать две копии скрипта создания индексов.

Как разделить список таблиц не подскажу, для этого надо из логов выписать время создания индексов для каждой из 28-ми таблиц, а потом разбить их на две примерно равные группы.

Вы может попросить у меня логи, я с радостью поделюсь.

Запускаем скрипт.

php ./create-indexes.php

Ждём час.

Creation index duration is 01:05:17

Вот и сказочке конец, а кто слушал, молодец !

Обновление базы

Обновление происходит аналогичным образом. В конфиге (config.env), в XML_FILES_PATH записываем путь к файлам обновления, меняем значение DO_IMPORT_WITH_CHECK на TRUE, запускаем скрипт, ждём, пользуемся.

Заключение

Импорт написан в декларативном стиле, каждая таблица объявлена как набор колонок. Для колонок определёно их поведение, при присвоении значения, при вставке новой записи, при обновлении ранее добавленной записи.

Это позволяет на базе этого кода писать произвольные импорты, в любые таблицы, любых данных. Одно условие - значения для импорта, надо передавать как массив [имя колонки => значение колонки].

Пространство имён SbWereWolf\FiasGarDataImport\Import\Composition\Column содержит примеры классов колонок, SbWereWolf\FiasGarDataImport\Import\Processor - примеры таблиц.

Изучайте, копируйте, распространяйте :)

Бонус

PgAdmin, загрузка по транзакциям, 5 скриптов импорта.

PgAdmin, загрузка по транзакциям, 5 скриптов импорта
PgAdmin, загрузка по транзакциям, 5 скриптов импорта

Загрузка HDD, 5 скриптов импорта.

Загрузка HDD, 5 скриптов импорта.
Загрузка HDD, 5 скриптов импорта.

Метрики процессов, 5 скриптов импорта.

Метрики процессов, 5 скриптов импорта.
Метрики процессов, 5 скриптов импорта.

Загрузка HDD, 4 скрипта импорта.

Загрузка HDD, 4 скрипта импорта.
Загрузка HDD, 4 скрипта импорта.

Метрики процессов, 3 скрипта импорта.

Метрики процессов, 3 скрипта импорта.
Метрики процессов, 3 скрипта импорта.

Загрузка HDD, 3 скрипта импорта.

Загрузка HDD, 3 скрипта импорта.
Загрузка HDD, 3 скрипта импорта.

Загрузка CPU, 3 скрипта импорта.

Загрузка CPU, 3 скрипта импорта.
Загрузка CPU, 3 скрипта импорта.

Метрики процессов, 2 скрипта импорта.

Метрики процессов, 2 скрипта импорта.
Метрики процессов, 2 скрипта импорта.

Метрики процессов, 1 скрипт импорта.

Метрики процессов, 1 скрипт импорта
Метрики процессов, 1 скрипт импорта

Загрузка CPU, 1 скрипт импорта.

Загрузка CPU, 1 скрипт импорта.
Загрузка CPU, 1 скрипт импорта.

Загрузка HDD, работает скрипт создания индексов в один поток.

Загрузка HDD, работает скрипт создания индексов в один поток
Загрузка HDD, работает скрипт создания индексов в один поток

Учитывая белые провалы, можно запустить создание индексов в два потока, в два скрипта. CPU при этом не сильно нагружен. Что интересно, при создании индексов, сначала идёт чтение на скорости 100 MB/s, потом запись на той же скорости 100 MB/s.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Чем вы импортируете и обновляете ФИАС?
7.14% liquetsoft/fias-component1
7.14% сторонний софт хороших людей (напишу об этом в коментах)1
35.71% собственная inhouse разработка5
7.14% можно попробовать эти скрипты1
42.86% мне не нужен ФИАС6
Проголосовали 14 пользователей. Воздержались 4 пользователя.
Теги:
Хабы:
Всего голосов 9: ↑6 и ↓3+3
Комментарии15

Публикации

Истории

Работа

PHP программист
147 вакансий

Ближайшие события