PDA

Просмотр полной версии : Что будет быстрее работать?(теория)


EST a1ien
05.11.2008, 23:56
Есть некая структура файлов(котороя не обновляется и не изменяется, просто папки и файлы).
Мне надо реализовать навигацию по этим файлам. Просто включить Options +Indexes не устраивает.

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

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

ЗЫ пока писал вспомнил про opendir/readdir. он наверно будет быстрее?

Chaak
06.11.2008, 00:04
База медленная штука. Используй readdir();

nerezus
06.11.2008, 00:22
Базу юзай. Чтобы рекурсивно не лазить по директориям. Легче гораздо это. Да и теоретически быстрее.

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

mr.The
06.11.2008, 00:38
база имхо.
к теме надо опрос прикрутить =\

nerezus
06.11.2008, 01:20
не нужен опрос. Да и автор не знает походу, что ему надо.

EST a1ien
06.11.2008, 11:20
nerezus что ты на меня сразу набросился?

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

ЗЫ уже двое за базу. Кстати можно еще прокешировать запрос к базе(так-как инфа меняться будет ну очень редко)

++Norton++
06.11.2008, 11:52
Тоже за базу. Должно быть быстрее.

Trieg
06.11.2008, 15:47
бд полюбому будет лучшим вариантом.. 500 файлов постоянно дергать неудобно + с бд больше возможностей

Red_Red1
11.11.2008, 18:38
Пока уезжал тема упала, ну да ясно что тут долго обсуждать.
Предлагаю свой вариант "что бы быстрее".

Нам в любом случае понадобиться отсканить директории что бы мы не использовали базу или файл.
Хранить дерево предлагаю в массиве такой структуры

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
$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
$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/

fucker"ok
11.11.2008, 22:39
А что ты мучаешься. один тест у тебя уже сделано напиши второй и для БД =)

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

Red_Red1
12.11.2008, 00:00
Да можно сделать тест.
Только вот ЧТО хранить в БД.
Точнее КАК хранить структуру папок? Предлагайте варианты, я попробую сделать тест и проверим.

nerezus
12.11.2008, 00:22
О да, офигеть структура сложная: id, файл в системе, реальное имя

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

Red_Red1
12.11.2008, 00:41
2 nerezus
Ждал твоих комментов. Если не сложно поясни почему база быстрее файлов? Ведь она тоже на файлах. Это не спор, это вопрос, действительно интересно.
И если говорить именно о скорости, все же как будет быстрее, из оперативки брать данные или все же из базы? Ну если не трудно дай все же ответ чуть шире чем обычно :)

nerezus
12.11.2008, 01:01
Если не сложно поясни почему база быстрее файлов? Ну тебе придется делать свое подобие базы в противном случае ;)
Не будешь же ты хранить файлы под их реальными именами, а потом лазить по всем папкам в их поиске? %)

Red_Red1
12.11.2008, 01:04
Хм... может я дурак... или неопытен, но вот нифига не понял.
Ладно, опыт придет. Спасибо и на том, будет над чем подумать, мало ли вдруг понадобится решать подобную задачу для чего нибудь своего.

nerezus
12.11.2008, 01:08
3 поля в бд.
Индексное уникальное слово или автоинкрементное целое - это номер файла
Временное имя файла(сгенерировано скриптом)
Реальное имя файла(при отдаче подставляется).

VDShark
12.11.2008, 10:20
Red_Red1 Наверное ты знаешь что БД развивается уже не один десяток лет, и даже в общих идеях и алгоритмах все более ли менее отточено. Взять хотя бы b-tree (сбалансированное дерево)... и представь поиск по нему, и поиск по харду... По сбалансированному дереву, при достаточно большом количестве записей ты получишь результат за 3-4 операции. Ну это я для примера, но общий смысл думаю понятен - почему база быстрее файлов.

Red_Red1
12.11.2008, 11:36
2 VDShark. Конечно я понимаю почему база быстрее файлов и то как она ищет по индексированым полям. Идея моя в другом.
Вот скажи что будет быстрее сделать запрос в базу и обработать результат ИЛИ выполнить вот эту строку

echo $arr['D']['DIR1']['SUBDIR1']['SUBDIR2'];

Я не делаю ПОИСК по харду, я загружаю ОДИН конкретный файл. ИЛИ же как я предложил вообще забираю массив из оперативки используя кеш. Т.е. у нас уже есть нужный массив.

astrologer
12.11.2008, 13:59
Вот скажи что будет быстрее сделать запрос в базу и обработать результат ИЛИ выполнить вот эту строку...echo $arr['D']['DIR1']['SUBDIR1']['SUBDIR2']['filename']; А что выведет эта строка?

Red_Red1
12.11.2008, 14:11
А что выведет эта строка?
Имя файла/папки.
Массив $arr хранит все дерево каталогов.
_______________________________________
Исправил код в предыдущем посту, допустил ошибку.