Фильтрация большого количества данных

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

stalxed

Постоялец
Регистрация
29 Мар 2007
Сообщения
56
Реакции
8
Очень часто сталкиваюсь с простой, но на деле сложной задачей.
Сразу с примера, писал парсер, который должен ходить по сайту как бот, например бот яндекса. И он не должен ходить по одной и той же странице сайта, тоесть каждую уникальную страницу пройти только один раз. Да былоб значений мало, то и проблем нет, но когда нужно фильтровать много милионов записей, допустим БД уже содержит лямба два, и нужно добавить 100 записей в минуту ещё!!!
Я решал задачу очень просто, способ один так сказать, который я знаю.
1
  • Создаём два txt файла
  • В первом файле задания, тоесть данные добавляются в конец, а берутся сначала
  • Второй файл хистори, в него данный только добавляются в конец
  • И перед добавлением URL в файлы, проходимся по файлу хистори функцией gets, в цикле поставив feof
  • Если добавляем сразу много значений, то при обходе циклом сравниваем искомые значения сравниваются со значением в getc...
Пример:
PHP:
public function addUrls($urls)
{
        $urls = array_unique($urls);
        $file_urls = fopen($this->directory.$this->file_urls, 'r+b');
        flock($file_urls, LOCK_EX);
        while (!feof($file_urls))
        {
            $str = trim(fgets($file_urls));
            foreach ($urls as $ukey => $url)
            {
                if ($url == $str)
                    unset($urls[$ukey]);
            }
        }
        fseek($file_urls, 0, SEEK_END);
        if (count($urls) > 0)
        {
            $file_history_urls = fopen($this->directory.$this->file_history_urls, 'ab');
            flock($file_history_urls, LOCK_EX);
            foreach ($urls as $url)
            {
                fwrite($file_urls, $url."\n");
                fwrite($file_history_urls, $url."\n");
            }
            fclose($file_history_urls);
            fclose($file_urls);
            return $urls;
        }
        else
        {
            fclose($file_urls);
            return FALSE;
        }
 }
Минус, работает медленно, если файл очень большой.
2
Не пробывал, но можно использовать мускул, где будет два столбца - url(он же индекс и уникальное значение), и поле использовался ли в парсинге URL.
НО проблем так же не мало, нужно поддерживать в работоспособном состояние БД и тд, и скорость будет не намного выше.
3
Вот над третим способом и думаю, хранить большой массив в памяти... Ведь есть всякие мемкеш и тд, можно с их помощью хранить большой массив?

И интересны также другие подходы к решению этой задачи, ведь она много где нужна! Собиратель мыл, собиратель ссылок для спама(в spamIt и тд) и тд!
 
Третий способ не подойдет, потому что при большом размере массива в памяти, мускул начнет выжирать память, генерить наргузку на сервак, и в итоге это скажется на быстродейтсвии скрипта и на лояльности к тебе хостера
 
memcached предназначен для кэширования данных, а не хранения их в большом объёме.
Большой массив это сколько (в MB)?

Если затык только в проверке был ли уже обработан URL, то лучше использовать БД (например BDB или SQLite).
 
Чем БД лучше? У меня при гараздо меньших объёмов работы мускул сжирал больше ресурсов, чем файлы(именно в данной задаче)...
 
Тем, что поиск по БД производится быстрее, если БД нормально спроектирована.
Да и не нужен для такой задачи мускуль.
 
В базе сделать несколько таблиц.
Типа:
a
b
c
d
e
f
g
h
куда распихивать в зависимости от первой буквы в урле :)
поиск будет быстреньким.

зы. два миллиона записей это немного даже для мускула) из гигабайтовой таблицы с логами выборки по ip посетителей длятся 2секунды :)
 
В базе сделать несколько таблиц.
зы. два миллиона записей это немного даже для мускула) из гигабайтовой таблицы с логами выборки по ip посетителей длятся 2секунды :)
Нужна магия индексов, нэ?
 
Нужна магия индексов, нэ?
Угу, верно копаете.

Если использовать хранение данных в файлах, то массив можно херануть в serialize(); и зажать через gzcompress();

Только serialize() слегка медленная функция, так-что это не панацея.
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху