Что будет быстрее работать?(теория)

Discussion in 'PHP' started by EST a1ien, 5 Nov 2008.

  1. EST a1ien

    EST a1ien Elder - Старейшина

    Joined:
    2 Apr 2006
    Messages:
    249
    Likes Received:
    48
    Reputations:
    16
    Есть некая структура файлов(котороя не обновляется и не изменяется, просто папки и файлы).
    Мне надо реализовать навигацию по этим файлам. Просто включить Options +Indexes не устраивает.

    Собственно что будет быстрее работать.
    Если мы загоним весь список файлов в базу(не сами файлы а просто их иерархию) и будем просто вытаскивать из базы.
    Или будем через system('ls') ползать?

    Или еще чтонибудь предложите?

    ЗЫ пока писал вспомнил про opendir/readdir. он наверно будет быстрее?
     
    #1 EST a1ien, 5 Nov 2008
    Last edited: 5 Nov 2008
  2. Chaak

    Chaak Elder - Старейшина

    Joined:
    1 Jun 2008
    Messages:
    1,059
    Likes Received:
    1,067
    Reputations:
    80
    База медленная штука. Используй readdir();
     
  3. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Базу юзай. Чтобы рекурсивно не лазить по директориям. Легче гораздо это. Да и теоретически быстрее.

    Хотя для твоего проекта все равно - он не будет настолько популярным, чтобы замечать разницу.
     
  4. mr.The

    mr.The Elder - Старейшина

    Joined:
    30 Apr 2007
    Messages:
    1,080
    Likes Received:
    456
    Reputations:
    38
    база имхо.
    к теме надо опрос прикрутить =\
     
  5. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    не нужен опрос. Да и автор не знает походу, что ему надо.
     
  6. EST a1ien

    EST a1ien Elder - Старейшина

    Joined:
    2 Apr 2006
    Messages:
    249
    Likes Received:
    48
    Reputations:
    16
    nerezus что ты на меня сразу набросился?

    Я не говорил нечего не про какой проет. Мне просто интересно что в данному случае лучше.
    Кстати ненадо получать рекурсивно список файлов. Нужно только список из папки/подпапки.
    А нагрузка будет хотябы потому что файлов в папки будет порядка 500 штук(возможно больше)
    И опять ты на меня накинулся. Такое впечатление будто я тебя прошу за меня что-то писать или сделать.

    ЗЫ уже двое за базу. Кстати можно еще прокешировать запрос к базе(так-как инфа меняться будет ну очень редко)
     
    #6 EST a1ien, 6 Nov 2008
    Last edited: 6 Nov 2008
  7. ++Norton++

    ++Norton++ Elder - Старейшина

    Joined:
    20 Nov 2006
    Messages:
    167
    Likes Received:
    39
    Reputations:
    0
    Тоже за базу. Должно быть быстрее.
     
  8. Trieg

    Trieg Elder - Старейшина

    Joined:
    26 Oct 2007
    Messages:
    82
    Likes Received:
    9
    Reputations:
    0
    бд полюбому будет лучшим вариантом.. 500 файлов постоянно дергать неудобно + с бд больше возможностей
     
  9. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Пока уезжал тема упала, ну да ясно что тут долго обсуждать.
    Предлагаю свой вариант "что бы быстрее".

    Нам в любом случае понадобиться отсканить директории что бы мы не использовали базу или файл.
    Хранить дерево предлагаю в массиве такой структуры
    Code:
    Array
    (
        [0] => file1
        [1] => file2
        [2] => file3
        [DIR1] => Array
            (
                [0] => file1
                [1] => file2
            )
        [DIR2] => Array
            (
                [0] => file1
                [1] => file2
                [2] => file3
                [SUBDIR1] => Array
                    (
                       [0] => file1
                       [1] => file2
                       [2] => file3
                    )
            )
    
    Дальше мы можем сериализовать массив (serialize) и засунуть строку в файл. Потом грузить массив из файла и пользоваться им для навигации. Можно положить строку сериализованого массива в базу. Тут вопрос, база данных ведь тоже представляет собой файл(ы) получается мы будем обращаться к файлам в любом случае, так какая разница что использовать базу или файл? (очень хочу узнать ответ : )) Хотя можно в базе хранить дерево не одной записью, а несколькими, тогда смысл может и будет, выигрываем в объеме загружаемых данных.
    Далее, начинаем ускорять это дело. Мысль такая использовать кеширование в памяти. Т.е. будем хранить в памяти на сервере массив дерева каталогов при необходимости берем массив сразу из памяти, а не с файла/базы.
    Объем памяти потребуется относительно небольшой.
    Вот примерный расчет взят с моего диска С. Общее количество файлов и папок 14000 (установлена винда ХП, офис, и несколько других программок). Возьмем среднее количество букв в имени файла/папки равным 15 (символов). Итого имеем 14000*15=210000 (байт-символов) или 205 килобайт. Много мало решать вам.
    Теперь все это в коде.
    1. Сканер директорий.
    PHP:
     <?php
    $memcache 
    = new Memcache();
    $memcache->pconnect('127.0.0.1'11211);//Подключаем сервер кеша

    function dir_tree($root)//Рекурсивная функция для сканирования директории. Возвращает массив-дерево
      
    {
        
    $res = array();$root .= '/';
        
    $dirs scandir($root);
        foreach(
    $dirs as $name){
          if(
    is_dir($root.$name)){
            if(
    $name == '.' || $name == '..'){
              continue;
            }
            
    $res[$name] = dir_tree($root.$name);
          }else{
            
    $res[] = $name;
          }
        }
       return 
    $res;    
      }

      
    $root = isset($_GET['root']) ? $_GET['root'] : '';
      
    $root substr($root,0,1) == '|' substr($root,1) : $root;
      
    $scan = isset($_GET['scan']);
      if(
    $scan){
        
    set_time_limit(0);
        
    $tree=dir_tree($root);//Получаем массив-дерево
        
    file_put_contents('d:/dir.txt',serialize($tree));//Сохраняем в файл полученый массив-дерево (можно не делать если не будем использовать файлы)
        
    $memcache->set('all_data_m'$treefalse60000);//Сохраняем массив в кеше (если будем работать через кеш. Не забыть выставить нужное время!)
        
    echo "Ok!";
       }
      
    echo 
    "<FORM ><INPUT type=text name = root><br />//Форма в которой укаываем диру для построение дерева.
      <input type =hidden name=scan value=1>
      <input type=submit value=scan></FORM><br />"
    ;
    ?>
    2. Скрипт навигации на основе массива дерева каталогов используя кеш в памяти.
    PHP:
     <?php
    $memcache 
    = new Memcache();
    $memcache->pconnect('127.0.0.1'11211);//Конект  к кешу
     /**
      * function array_getbranch Возвращает указанный элемент массива
      * т.е. преобразовывает строку вида dir1|dir2|...|dirN в $var[dir1][dir2]...[dirN] - массив
      * Уровни массива в строке разделяются |
      * Если данного элемента нет, то вернет NULL
      *$branch string Строка-путь к элементам
      * $arr array|null Массив для обработки, если NULL, то вернет только "строку доступа" ([a][b][c]...), а не значение
      *  c данного массива
      * @return mixed Указанный узел/"строка доступа"/NULL(если ветка с ошибками или не существует такого элемента)
      */
    function array_getbranch($branch,$arr null)
     {
      if(
    $branch != '' && !preg_match("/^(?:\[\'[\w\d\- ]+\'\])+$/",$branch "['".str_replace('|',"']['",$branch)."']"))
       {
        return 
    null//если ветка не пустая и в ней ошибка -> результат уже ясен
       
    }
      return 
    is_null($arr) ? $branch : eval("return @\$arr$branch;");
     }  

    // ----------- Засекаем время -{Начаало}----------------------------
    $mtime microtime();
    $mtime explode(" ",$mtime);
    $mtime $mtime[1] + $mtime[0];
    $tstart $mtime;
    // ------------ Засекаем время {Конец}------------------------
      
      
    $root = isset($_GET['root']) ? $_GET['root'] : '';
      
    $root substr($root,0,1) == '|' substr($root,1) : $root;
      
      
    $tmp $memcache->get('all_data_m');//Берем из кеша массив
      
    $data array_getbranch($root,$tmp);//Получаем нужный элемент массива по параметру  $root (dir1|dir2|...|dirN)
      
      
    echo "<PRE>";
      
    //print_r ($data);
      
    $ret substr($root,0,strrpos($root,'|'));
      echo 
    '"'.str_replace('|','\\',$root)."\"<br />";
      echo 
    "<br /><A href = \"?root=$ret\">..</A><br />" ;
      foreach(
    $data as $key=>$value)//Выводим в браузер содержимое каталога.
       
    {
        echo 
    "<br />";
        if(
    is_array($value)){
          echo 
    "<A href=\"?root=$root|$key\">$key</A>";
        }else{
          echo 
    "$value";
        }
       }

    // ------- считаем пройденное время --------------Начало
    $mtime microtime();
    $mtime explode(" ",$mtime);
    $mtime $mtime[1] + $mtime[0];
    $tend $mtime;
    $totaltime ceil(($tend $tstart)*10000)/10000;
    $time='<br />Страница сгенерирована за '.$totaltime.' секунд.';
    // ------- считаем пройденное время --------------Конец
    echo $time;
    ?>
    Первый скрипт запускаем один раз для сканирования, а вторым пользуемся для навигации. Если структура каталогов изменилась, то снова нужно запустить сканирование.
    Можно сделать разные проверки и прочее, но это нужно уже для конкретной задачи.
    Вот такое вот решение. Интересно услышать критику.
    З.Ы.
    Для использования кеша придется установить memcache. Очень коротко почитать можно тут
    http://www.webnext.ru/blog/2007/09/18/php-memcache.html
    Есть версия для винды (ей и пользовался)
    http://jehiah.cz/projects/memcached-win32/
     
    4 people like this.
  10. fucker"ok

    fucker"ok Elder - Старейшина

    Joined:
    21 Nov 2004
    Messages:
    580
    Likes Received:
    279
    Reputations:
    91
    А что ты мучаешься. один тест у тебя уже сделано напиши второй и для БД =)

    Я думаю что БД быстрее т.к. хранить в каждом запущенном скрипте структуру из 14к элементов - накладно.
    Да и в БД есть тоже свой кеш, который можно настроить.
     
  11. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Да можно сделать тест.
    Только вот ЧТО хранить в БД.
    Точнее КАК хранить структуру папок? Предлагайте варианты, я попробую сделать тест и проверим.
     
  12. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    О да, офигеть структура сложная: id, файл в системе, реальное имя

    По имени файлав системе(типа 12ab211d2bac12d) смотрится его путь(12/12ab/12ab211d2bac12d) и реальное имя.
     
    1 person likes this.
  13. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    2 nerezus
    Ждал твоих комментов. Если не сложно поясни почему база быстрее файлов? Ведь она тоже на файлах. Это не спор, это вопрос, действительно интересно.
    И если говорить именно о скорости, все же как будет быстрее, из оперативки брать данные или все же из базы? Ну если не трудно дай все же ответ чуть шире чем обычно :)
     
  14. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Ну тебе придется делать свое подобие базы в противном случае ;)
    Не будешь же ты хранить файлы под их реальными именами, а потом лазить по всем папкам в их поиске? %)
     
  15. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Хм... может я дурак... или неопытен, но вот нифига не понял.
    Ладно, опыт придет. Спасибо и на том, будет над чем подумать, мало ли вдруг понадобится решать подобную задачу для чего нибудь своего.
     
  16. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    3 поля в бд.
    Индексное уникальное слово или автоинкрементное целое - это номер файла
    Временное имя файла(сгенерировано скриптом)
    Реальное имя файла(при отдаче подставляется).
     
  17. VDShark

    VDShark Elder - Старейшина

    Joined:
    1 Feb 2007
    Messages:
    260
    Likes Received:
    158
    Reputations:
    62
    Red_Red1 Наверное ты знаешь что БД развивается уже не один десяток лет, и даже в общих идеях и алгоритмах все более ли менее отточено. Взять хотя бы b-tree (сбалансированное дерево)... и представь поиск по нему, и поиск по харду... По сбалансированному дереву, при достаточно большом количестве записей ты получишь результат за 3-4 операции. Ну это я для примера, но общий смысл думаю понятен - почему база быстрее файлов.
     
  18. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    2 VDShark. Конечно я понимаю почему база быстрее файлов и то как она ищет по индексированым полям. Идея моя в другом.
    Вот скажи что будет быстрее сделать запрос в базу и обработать результат ИЛИ выполнить вот эту строку
    PHP:
    echo $arr['D']['DIR1']['SUBDIR1']['SUBDIR2'];
    Я не делаю ПОИСК по харду, я загружаю ОДИН конкретный файл. ИЛИ же как я предложил вообще забираю массив из оперативки используя кеш. Т.е. у нас уже есть нужный массив.
     
    #18 Red_Red1, 12 Nov 2008
    Last edited: 12 Nov 2008
  19. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    А что выведет эта строка?
     
  20. Red_Red1

    Red_Red1 Banned

    Joined:
    12 Jan 2007
    Messages:
    246
    Likes Received:
    258
    Reputations:
    83
    Имя файла/папки.
    Массив $arr хранит все дерево каталогов.
    _______________________________________
    Исправил код в предыдущем посту, допустил ошибку.
     
    #20 Red_Red1, 12 Nov 2008
    Last edited: 12 Nov 2008