Есть некая структура файлов(котороя не обновляется и не изменяется, просто папки и файлы). Мне надо реализовать навигацию по этим файлам. Просто включить Options +Indexes не устраивает. Собственно что будет быстрее работать. Если мы загоним весь список файлов в базу(не сами файлы а просто их иерархию) и будем просто вытаскивать из базы. Или будем через system('ls') ползать? Или еще чтонибудь предложите? ЗЫ пока писал вспомнил про opendir/readdir. он наверно будет быстрее?
Базу юзай. Чтобы рекурсивно не лазить по директориям. Легче гораздо это. Да и теоретически быстрее. Хотя для твоего проекта все равно - он не будет настолько популярным, чтобы замечать разницу.
nerezus что ты на меня сразу набросился? Я не говорил нечего не про какой проет. Мне просто интересно что в данному случае лучше. Кстати ненадо получать рекурсивно список файлов. Нужно только список из папки/подпапки. А нагрузка будет хотябы потому что файлов в папки будет порядка 500 штук(возможно больше) И опять ты на меня накинулся. Такое впечатление будто я тебя прошу за меня что-то писать или сделать. ЗЫ уже двое за базу. Кстати можно еще прокешировать запрос к базе(так-как инфа меняться будет ну очень редко)
бд полюбому будет лучшим вариантом.. 500 файлов постоянно дергать неудобно + с бд больше возможностей
Пока уезжал тема упала, ну да ясно что тут долго обсуждать. Предлагаю свой вариант "что бы быстрее". Нам в любом случае понадобиться отсканить директории что бы мы не использовали базу или файл. Хранить дерево предлагаю в массиве такой структуры 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', $tree, false, 60000);//Сохраняем массив в кеше (если будем работать через кеш. Не забыть выставить нужное время!) 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/
А что ты мучаешься. один тест у тебя уже сделано напиши второй и для БД =) Я думаю что БД быстрее т.к. хранить в каждом запущенном скрипте структуру из 14к элементов - накладно. Да и в БД есть тоже свой кеш, который можно настроить.
Да можно сделать тест. Только вот ЧТО хранить в БД. Точнее КАК хранить структуру папок? Предлагайте варианты, я попробую сделать тест и проверим.
О да, офигеть структура сложная: id, файл в системе, реальное имя По имени файлав системе(типа 12ab211d2bac12d) смотрится его путь(12/12ab/12ab211d2bac12d) и реальное имя.
2 nerezus Ждал твоих комментов. Если не сложно поясни почему база быстрее файлов? Ведь она тоже на файлах. Это не спор, это вопрос, действительно интересно. И если говорить именно о скорости, все же как будет быстрее, из оперативки брать данные или все же из базы? Ну если не трудно дай все же ответ чуть шире чем обычно
Ну тебе придется делать свое подобие базы в противном случае Не будешь же ты хранить файлы под их реальными именами, а потом лазить по всем папкам в их поиске? %)
Хм... может я дурак... или неопытен, но вот нифига не понял. Ладно, опыт придет. Спасибо и на том, будет над чем подумать, мало ли вдруг понадобится решать подобную задачу для чего нибудь своего.
3 поля в бд. Индексное уникальное слово или автоинкрементное целое - это номер файла Временное имя файла(сгенерировано скриптом) Реальное имя файла(при отдаче подставляется).
Red_Red1 Наверное ты знаешь что БД развивается уже не один десяток лет, и даже в общих идеях и алгоритмах все более ли менее отточено. Взять хотя бы b-tree (сбалансированное дерево)... и представь поиск по нему, и поиск по харду... По сбалансированному дереву, при достаточно большом количестве записей ты получишь результат за 3-4 операции. Ну это я для примера, но общий смысл думаю понятен - почему база быстрее файлов.
2 VDShark. Конечно я понимаю почему база быстрее файлов и то как она ищет по индексированым полям. Идея моя в другом. Вот скажи что будет быстрее сделать запрос в базу и обработать результат ИЛИ выполнить вот эту строку PHP: echo $arr['D']['DIR1']['SUBDIR1']['SUBDIR2']; Я не делаю ПОИСК по харду, я загружаю ОДИН конкретный файл. ИЛИ же как я предложил вообще забираю массив из оперативки используя кеш. Т.е. у нас уже есть нужный массив.
Имя файла/папки. Массив $arr хранит все дерево каталогов. _______________________________________ Исправил код в предыдущем посту, допустил ошибку.