Быстрый поиск разницы файлов

Ну собственно это история одной маленькой победы, которые происходят обычно у ИТишников каждый день 😉

Предыстория: при работе скрипта по заливке данных в БД из файла произошло зависание сервера. Скрипт работал в несколько потоков с одним файлом. Потому определить на каком именно месте файла произошла остановка не представлялось возможным. Удалять уже залитое в БД и стартовать скрипт заново — не вариант, скрипт и так работал двое суток, и терять их снова — ну так себе решение.

Решение №1. «В лоб». Ну думаю доработаю скрипт так, что если данные уже есть, то просто пропускаем. Т.е. перед вставкой выполняем проверку функцией вида:

function lsYet($period,$ls){
    global $db;
  $res=false;
  $sql="select posting_addresses.id from posting_addresses
    inner join ls on ls.id=posting_addresses.ls
    where 
    posting_addresses.period='$period' and ls.ls='$ls'";
    $query = $db->connection->prepare($sql);
    $query->execute();
    while ($row99 = $query->fetch()) {
      $res=true;
    };        
 return $res;
}

И без проблем дозальем то, чего нет в БД. Да не тут то было, оказывается операция select в этом случае весьма дорогостоящая, и т.к. в БД записей порядка 600тыс, и индексы проставлены на ls и period корректно, но всёж скорость проверки крайне низкая, и т.о. скорость «дозалития» сокращается с двух суток до суток. Ну что собственно не устраивает.

Решение №2. Вдумчивое. Решил было выгрузить ключевые строки (лицевой счет) в файлы: файл ls_in_base.txt — лицевые счета которые уже в БД и ls_all.txt — файл со всеми лицевыми счетами, которые должны быть в БД, отсортировав их командой sort:

sort ls_in_base.txt > ls_in_base.txt
sort ls_all.txt > ls_all.txt

Далее воспользуемся Linux командой comm, вычленив уникальные записи файла ls_all которые не содержаться в файле ls_in_base:

comm -23 ls_all.txt ls_in_base.txt > no_in_base.txt

И далее уже в скрипте вместо проверки наличия лс в БД при помощи запроса, проверяем наличие лс в БД при помощи in_array:

$no_in_base_ls=file_get_contents("no_in_base.txt");
$no_in_base_arr=explode("\n",$no_in_base_ls);
...
if (in_array($ls, $no_in_base_arr)==true){
...
заливаем данные в БД
...
}

В результате скорость увеличилась в разы, и БД дозалить удалось в течении часа

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.