vechnokrainii
@vechnokrainii
ну почти всегда(

Как оптимизировать этот php код?

Здравствуйте! Скажите, можно ли как-то код оптимизировать. Его цель сверить 2 массива и вывести значения который есть в первом ($dada), но нет во втором ($base) . Первый массив я получаю из TSV файла (45000 записей) В tsv идут значаения и я преобразую их в массив массивов. Второй массив я вытягиваю из sql - базы. Но чтобы не тянуть все поля, так как для сверки нужно только одно, беру ток ID. Время проверки на дубликаты при 20000 записей в базе составило почти 11 минут. А там еще и записывать в базу потом надо. В результе я записал 45000 в базу. Но у менять есть еще файлы ( по 20-40 тыс.записей) который нужно сверять и записывать, если вдруг в базе чего-то нет. Повторю, что 10 минут это только время когда он сверяет. Или это нормальное время? Просто впервые работаю с с таким объемом.
$data = []; //массив котрый я получаю из файла
$base = []; //массив который я беру sql запросом из базы. Содержит в себе значение только одного поля - ID

$maxBase = count($base);
$start = microtime(true);
	foreach($data as $dates) {
		$i = 0;
		foreach ($base as $bases) {
			if($dates['ID'] == $bases['ID'] ) {
				break;
			} 
			$i++;
			if($i == $maxBase) {
				$itog[] = $dates;
			}
		}
	}
$finish = microtime(true);
$time = $finish - $start
  • Вопрос задан
  • 295 просмотров
Решения вопроса 2
FanatPHP
@FanatPHP
Чебуратор тега РНР
я думаю, даже in_array будет быстрее чем это.
Но по-хорошему надо сделать значения индексами
тогда проверка будет проходить мгновенно
$base = array_flip(array_column($base, 'ID'));
foreach($data as $dates) {
    if (!isset($base[$dates['ID']])) {
            $itog[] = $dates;
    }
}
Ответ написан
cesnokov
@cesnokov
<head>&nbsp;</head>
Сложно сказать не видя всего кода и данных в файлах и базе. Но оптимизировать точно можно. Вот вам примеры:
  • Если TSV файлы слишком большие, то не надо их в массив пихать. Можно их читать построчно fgetcsv() и работать с маленькими объёмами данных.
  • Если вы часто берёте из таблицы одно и тоже, то есть смысл индексировать это поле ALTER TABLE xxx ADD INDEX(ID).
  • Если в базе поле ID настроено уникальным (индекс UNIQUE) то можно писать в базу без проверки ID, вместо INSERT используя INSERT IGNORE.
  • Вносить изменения в базу данных не частями по одной строке (создавая кучу запросов), а в конце вычислений одним длинным запросом.


И т.д. :)
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Stalker_RED
@Stalker_RED
Сравнить пересечение массивов можно так: https://www.php.net/manual/ru/function.array-diff.php

Но возможно еще быстрее будет залить все в базу, во временную таблицу (load data infile) и потом добавить куда нужно используя insert ignore.
1. создать временную таблицу (без индекса)
2. load data infile ...
3. создать индекс по id
4. insert ignore into ... select (или on duplicate key update?)
5. удалить временную

20к записей должно обрабатываться за несколько секунд. Ну может секунд за 20, если сервер совсем слабый.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы