Получение id страницы по URL. Скорость.
Сегодня я опять играюсь с профайлером :) В общем мне кажется, что заметка будет полезной для тех, кто хочет иметь у себя ЧПУ и быстрый способ получения требуемой страницы.
В заметке будет рассматриваться сайт который использует списки смежности для хранения дерева. Вообще способ получения id страницы по url был описан еще до меня здесь.
Здесь я просто предложу два своих способа и сравню их скорости.
Способ 1.
Здесь для получения id страницы мы пройдемся по url и выполним по запросу на каждый уровень вложенности. Легче посмотреть код, чем понять что я написал :)
<?php
function get_id($path)
{
$uri_parts=explode('/', $path);
$last_parent=0;
for($x=0; $x<count($uri_parts); $x++)
{
mysql_query("select id from test where parent='".$last_parent."'
and alias='".mysql_real_escape_string($uri_parts[$x])."'");
list($last_parent)=mysql_fetch_row();
}
return $last_parent;
}
?>
Т.е. если у нас будет адрес about/contacts/branch1 эта функция выполнит три запроса для получения искомого id страницы branch1.
Способ 2.
Есть альтернативный вариант с применением таблиц, которые присоединяют сами себя к себе же :) (self-joins). Вот он:
<?php
function get_id($path)
{
$uri_parts=explode('/', $path);
$query_joins="";
$query_where="where t1.alias='".$uri_parts[0]."'";
for($x=1; $x<count($uri_parts); $x++)
{
$query_joins.=" left join test as t".($x+1)." on t".($x+1).".parent = t".$x.".id ";
$query_where.=" and t".($x+1).".alias = '".mysql_real_escape_string($uri_parts[$x])."' ";
}
mysql_query("select t".$x.".id from test as t1".$query_joins.$query_where);
list($xid)=mysql_fetch_row();
return $xid;
}
?>
Результат выполнения тот же.
А теперь самое интересное. Я обещал замеры и производительность. Так вот несмотря на то, что self-join должны по идее становится медленее с каждой новой присоединенной таблицей (так написано в этой
статье ), они оказываются намного быстрее чем вариант с запросом на уровень сложенности (вариант 1). Не буду голословным а просто приведу результаты профайлинга. Об условиях: тесты производились на машине со след. конфигурацией: CPU 2.5 GHz, RAM 512 MB, CentOS 4.2, Apache 1.3, PHP 5.1.2, MySQL 5.0.16. В тестовую таблицу было забито 11280 записей. Сама таблица состояла из четырех полей: id(INT), parent(INT), alias(VARCHAR 15), article(TEXT). Данные были абсолютно реальными, т.е. не сгенерированные спец. скриптом сочетания из одной-двух букв а настоящие слова и статьи. Путь состоял из 10 компонентов (уровень вложенности 10).
Теперь собственно результаты:
вариант 1- среднее время 102ms,
вариант 2- среднее время 15ms.
Вывод очевиден. Недостаток self-join заключается в ограничении на количество присоединяемых таблиц (уровень вложенности).