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

Тема в разделе "Как сделать...", создана пользователем stalxed, 12 авг 2008.

Статус темы:
Закрыта.
  1. stalxed

    stalxed Постоялец

    Регистр.:
    29 мар 2007
    Сообщения:
    61
    Симпатии:
    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_urlsLOCK_EX);
            while (!
    feof($file_urls))
            {
                
    $str trim(fgets($file_urls));
                foreach (
    $urls as $ukey => $url)
                {
                    if (
    $url == $str)
                        unset(
    $urls[$ukey]);
                }
            }
            
    fseek($file_urls0SEEK_END);
            if (
    count($urls) > 0)
            {
                
    $file_history_urls fopen($this->directory.$this->file_history_urls'ab');
                
    flock($file_history_urlsLOCK_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 и тд) и тд!
     
  2. pslava

    pslava

    Регистр.:
    16 май 2007
    Сообщения:
    618
    Симпатии:
    122
    Третий способ не подойдет, потому что при большом размере массива в памяти, мускул начнет выжирать память, генерить наргузку на сервак, и в итоге это скажется на быстродейтсвии скрипта и на лояльности к тебе хостера
     
  3. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    590
    memcached предназначен для кэширования данных, а не хранения их в большом объёме.
    Большой массив это сколько (в MB)?

    Если затык только в проверке был ли уже обработан URL, то лучше использовать БД (например BDB или SQLite).
     
  4. stalxed

    stalxed Постоялец

    Регистр.:
    29 мар 2007
    Сообщения:
    61
    Симпатии:
    8
    Чем БД лучше? У меня при гараздо меньших объёмов работы мускул сжирал больше ресурсов, чем файлы(именно в данной задаче)...
     
  5. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    590
    Тем, что поиск по БД производится быстрее, если БД нормально спроектирована.
    Да и не нужен для такой задачи мускуль.
     
  6. Slayter

    Slayter

    Регистр.:
    8 апр 2006
    Сообщения:
    232
    Симпатии:
    52
    В базе сделать несколько таблиц.
    Типа:
    a
    b
    c
    d
    e
    f
    g
    h
    куда распихивать в зависимости от первой буквы в урле :)
    поиск будет быстреньким.

    зы. два миллиона записей это немного даже для мускула) из гигабайтовой таблицы с логами выборки по ip посетителей длятся 2секунды :)
     
  7. anarki

    anarki Прохожие

    Нужна магия индексов, нэ?
     
  8. admLoki

    admLoki генератор случайного PHP

    Регистр.:
    14 сен 2006
    Сообщения:
    481
    Симпатии:
    93
    Угу, верно копаете.

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

    Только serialize() слегка медленная функция, так-что это не панацея.
     
Статус темы:
Закрыта.