огромные массивы

Статус
В этой теме нельзя размещать новые ответы.

phillip

Полезный
Регистрация
4 Сен 2007
Сообщения
411
Реакции
15
есть файл, 3млн строк с url'ами. Надо в файле убрать те урлы, которые ведут с одного домена. то бишь уникализировать по доменам. Пример:

http://nulled.cc/newthread.php?do=newthread&f=214
http://nulled.cc/memberlist.php

из этих двух ссылок надо оставить только одну, так как домены совпали.

Как это сделать максимально быстро? Я стал делать так.... Забил все в один массив, затем беру первый элемент массива, заношу в массив $result. Далее беру еще одну строку, вычисляю домен в ней, ищу в $result добавляли ли такой домен. Если не добавляли, добавляем. И так далее. В итоге чем дальше идем, тем медленнее работает скрипт потому что $result разрастается. В итоге, за 3 часа у меня прошло 500к строк, и практически остановилось, далее идет ооочень медленно. Я подозреваю что 3млн он будет проходить еще до след.вечера.
Подскажите как сделать чтоб было быстрее
 
Методом пузырька можно перебирать долго, но это самый простой способ сортировки: тут можно прочитать про методы вообще.
Я бы сделал немного по другому, отсортировал строки (получил бы значения доменов), после чего все это лучше влить в базу, а дальше уже делать выборку с объединением по полю домена. Mysql с GROUP BY сделает это несколько быстрее. При этом, сразу получится массив с отсортированными значениями.
 
создаешь таблицу в БД
и делаешь у нее поле уникальным

потом в цикле читаешь файл с домена и тупо инсертишь с игнором ошибок

при индексе "уникальный" СУБД сама будет все фильтровать .. причем это дело будет сортироваться ... выстраиваться в виде дерева .. т.е. имхо самый простой в реализации способ и при этом достаточно производительный
как для разовой операции самое оно

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

ful_url domain
и ключ цеплять только на domain
ну и в domain вставлять лишь вырезанный домен ( не всю ссылку) так будет еще чуть быстрее фильтровать
 
согласен с chang, но более быстрым вариантом будет использование не мускуля а key-val хранилища, например redis, ибо так будет в сотни раз быстрее.
 
chang, чето я вставляю так как ты сказал, и получается у меня... что при работе с файлами удалялось меньше ссылок, а счас из 600к осталось 100к... то есть 5из6 не попали в бд, а раньше 3 из 5 не попадали.... где косяк может быть?
 
chang, чето я вставляю так как ты сказал, и получается у меня... что при работе с файлами удалялось меньше ссылок, а счас из 600к осталось 100к... то есть 5из6 не попали в бд, а раньше 3 из 5 не попадали.... где косяк может быть?
ты думаешь что здесь есть телепаты? Выложи код которым ты это делаешь.
 
В случае с бд писал так

PHP:
$count=0;
$z=file('source.txt');
echo count($z).'<br/>';
foreach($z as $key => $url){
	preg_match("&(https|http)://(.+)?/&",$url,$m);
	
	if(!isset($m[2])) continue;
	
		
	$STH = $DBH->prepare("INSERT INTO `rama` VALUES( 0 , ? , ?)");
	@$STH->execute(array($url,$m[2]));
	
	$count++;
	if($count==1000) { echo $key.'<br/>'; flush(); $count=0; }
}
в случае с файлами
PHP:
$domens=array();
$count=0;
foreach($z as $key => $url){
	//echo $url."<br/>";

	$exist=null;
	preg_match("&(https|http)://(.+)?/&",$url,$m);
	
	if(!isset($m[2])) continue;
	
	
	foreach($domens as $domen){
		if($domen==$m[2]) $exist=true;
	}
	if(!$exist){
		$domens[]=$m[2];
		//$fn=fopen('result.txt','w');
		$fn=fopen('result.txt','a');
		fwrite($fn, $url);
		fclose($fn);
		
		$fn=fopen('result-domains.txt','a');
		fwrite($fn, $m[2]);
		fclose($fn);
	}
	$count++;
	if($count==1000) { echo $key.'<br/>'; flush(); $count=0; }
	
}
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху