array_intersect - как заставить работать?

Тема в разделе "PHP", создана пользователем deni.pc, 20 июл 2009.

Статус темы:
Закрыта.
Модераторы: latteo
  1. deni.pc

    deni.pc

    Регистр.:
    6 сен 2006
    Сообщения:
    201
    Симпатии:
    57
    Необходимо определить наличие слов из файла words.txt в базе. В общем и целом все работает, но...
    ... и тут начинается проблема.
    В базе около 70000 записей, цикл доходит то до 2434-ой записи, то до 4183-ой, то до еще какойто случайной и останавливается.
    Есть подозрения, что array_intersect ведет себя как то некорректно (организовывал вывод на эран 70000 записей - все работает). Используемый код ниже:

    $keys = file('words.txt');
    array_walk($keys,create_function('&$v,$k','$v=trim(strtolower($v));'));
    $query = "SELECT id_link,title,longdescription FROM $links WHERE status = 1";
    $result = mysql_query($query, $link);
    $b = mysql_num_rows($result);
    echo ("<BR>Elements in the base: $b");
    while ($row = mysql_fetch_array($result))
    { $n++;
    $contents=str_replace (' -', ' ', $row["title"]);
    $contents=str_replace ('.', ' ', $contents);
    $contents=str_replace (',', ' ', $contents);
    $contents=str_replace ('!', ' ', $contents);
    $contents=str_replace ('?', ' ', $contents);
    $contents=str_replace (':', ' ', $contents);
    $contents=str_replace (';', ' ', $contents);
    $contents=str_replace (')', ' ', $contents);
    $contents=str_replace ('(', ' ', $contents);
    $contents=str_replace ('"', ' ', $contents);
    $arr = explode(' ', $contents);

    $contents=str_replace (' -', ' ', $row["longdescription"]);
    $contents=str_replace ('.', ' ', $contents);
    $contents=str_replace (',', ' ', $contents);
    $contents=str_replace ('!', ' ', $contents);
    $contents=str_replace ('?', ' ', $contents);
    $contents=str_replace (':', ' ', $contents);
    $contents=str_replace (';', ' ', $contents);
    $contents=str_replace (')', ' ', $contents);
    $contents=str_replace ('(', ' ', $contents);
    $contents=str_replace ('"', ' ', $contents);
    $arr2 = explode(' ', $contents);
    array_walk($arr,create_function('&$v,$k','$v=trim(strtolower($v));'));
    array_walk($arr2,create_function('&$v,$k','$v=trim(strtolower($v));'));
    if (count (array_intersect($keys,$arr)))
    {
    $query = 'UPDATE '.$links.' SET status = 0, id_cat = '.$id_cat.' WHERE id_link = '. $row["id_link"];
    $result2 = mysql_query($query, $link);
    if ($result2) echo ("<BR>$n. in title - ".$row["title"]); else {echo('Error in title');}
    } else
    {
    if (count (array_intersect($keys,$arr2)))
    {
    $query = 'UPDATE '.$links.' SET status = 0, id_cat = '.$id_cat.' WHERE id_link = '. $row["id_link"];
    $result = mysql_query($query, $link);
    if ($result) echo ("<BR>$n. in desc - ".$row["longdescription"]); else {echo('Error in desc');}
    } else {
    echo ("<BR>$n. Ненайдено - ".$row["title"]." : ".$row["longdescription"]);
    }

    }

    }

    Может я что-то криво объяснил, мало опыта, заранее прошу - сильно не ругайтесь :)
     
  2. sTarT1k

    sTarT1k Писатель

    Регистр.:
    17 июл 2009
    Сообщения:
    7
    Симпатии:
    1
    Попробуй set_time_limit(600) сделать...
    Может быть на хостинге есть ограничение на времени работу скрипта и он просто не успевает завершить все, к тому же если скрипт работает до 2000+ записей корректно, то маловероятно что в нем ошибки.
     
  3. deni.pc

    deni.pc

    Регистр.:
    6 сен 2006
    Сообщения:
    201
    Симпатии:
    57
    не, фокус не удался.
    фишка в том, что выполняется он 3-5 секунд и встает.
    когда делал импорт этих 70000 записей выполнялся сек. 15-20 - все гут.

    грешу на array_intersect,
    пытался в ручную перебирать в цикле - та же история - вылетает на случайном месте.
    могу я сервак нагрузить сильно этим делом?
     
  4. sTarT1k

    sTarT1k Писатель

    Регистр.:
    17 июл 2009
    Сообщения:
    7
    Симпатии:
    1
    Тогда попробуй на локальной машине запустить, все таки мне кажется проблема в хостинге, может там запрещено set_time_limit()...
    Просто я даже представить не могу откуда может появиться логическая ошибка после 2000 правильных циклов!
     
  5. deni.pc

    deni.pc

    Регистр.:
    6 сен 2006
    Сообщения:
    201
    Симпатии:
    57
    Точно!
    Локально все заработало, но явно долго выполняется скрипт.
    Какое решение возможно в этом раскладе? Как мне все это реализовать на хостинге?
     
  6. sTarT1k

    sTarT1k Писатель

    Регистр.:
    17 июл 2009
    Сообщения:
    7
    Симпатии:
    1
    А вот это сложнее...
    По идеи лучше для такого брать виртуальный сервер!
    Но если уж надо помучиться, то я вижу только 1 выход:
    Разбивать одну задачу на несколько циклов...Т.е разбить всю базу во временные таблицы по 3000 записей и работать с ней через рекурсию...
    Но если дело не в php, а в mysql, то попробовать перейти на mysqli...
     
    deni.pc нравится это.
  7. chixchix

    chixchix Писатель

    Регистр.:
    17 июл 2009
    Сообщения:
    2
    Симпатии:
    0
    а зачем пересечение искать в цикле?
     
  8. deni.pc

    deni.pc

    Регистр.:
    6 сен 2006
    Сообщения:
    201
    Симпатии:
    57
    а где его надо искать?
    Есть другое решение?
    Я беру из базы строку, привожу ее к определенному виду, разбиваю на слова в массив и ищу пересечения данного масива words и полученного, тем самым определяя совпадения.
     
  9. chixchix

    chixchix Писатель

    Регистр.:
    17 июл 2009
    Сообщения:
    2
    Симпатии:
    0
    file() возвращает список, следовательно, достаточно будет получить данные из базы в виде ассоциативного массива с ключами типа "k##n", где k - номер строки в базе, а n - номер слова в строке, и собсно в array_intersect() поменять местами $arr/$arr2 и $keys. В результирующем массиве получите номера строк (k##n), которые надо будет апдейтить. Кроме того, совершенно не обязательно считывать всю базу в массив, можно заливать ее туда кусками, а после интерсекта очищать массив и заливать следующий кусок, тем самым вы сможете найти баланс между памятью, которая будет использована скриптом и количеством вызовов интерсекта, если конечно вообще в нем проблема. Во всяком случае, вы перестанете вызывать интерсект и разные другие замечательные функции 7000 раз за время работы. Еще вариант - файл заменить таблицей. Тоже будет быстрее, наверное.
     
Статус темы:
Закрыта.