Быстрый поиск разницы файлов
Ну собственно это история одной маленькой победы, которые происходят обычно у ИТишников каждый день 😉
Предыстория: при работе скрипта по заливке данных в БД из файла произошло зависание сервера. Скрипт работал в несколько потоков с одним файлом. Потому определить на каком именно месте файла произошла остановка не представлялось возможным. Удалять уже залитое в БД и стартовать скрипт заново — не вариант, скрипт и так работал двое суток, и терять их снова — ну так себе решение.
Решение №1. «В лоб». Ну думаю доработаю скрипт так, что если данные уже есть, то просто пропускаем. Т.е. перед вставкой выполняем проверку функцией вида:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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:
1 2 |
sort ls_in_base.txt > ls_in_base.txt sort ls_all.txt > ls_all.txt |
Далее воспользуемся Linux командой comm, вычленив уникальные записи файла ls_all которые не содержаться в файле ls_in_base:
1 |
comm -23 ls_all.txt ls_in_base.txt > no_in_base.txt |
И далее уже в скрипте вместо проверки наличия лс в БД при помощи запроса, проверяем наличие лс в БД при помощи in_array:
1 2 3 4 5 6 7 8 |
$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){ ... заливаем данные в БД ... } |
В результате скорость увеличилась в разы, и БД дозалить удалось в течении часа