Большой Воронежский Форум
» Программирование>Оптимизация SQL запроса.
Zhendos II 13:03 08.10.2007
Вообщем начал я тут доделывать кое че на одном форуме, но из-за хостера в одном месте лагает из-за превышения лимита ресурсов. Есть 3 таблицы, в одной инфа о бане(ban_id, ban_userid, ban_ip, ban_email, ban_mod, ban_date, ban_forum, ban_text, ban_time; где ban_mod-id юзверя, который банил; ban_date-дата бана; ban_forum-id раздела, кде забанили; ban_text-причина бана; ban_time-длительность бана) во второй инфа о юзверях(нам от тудава нужны: user_id, username), ну и третья инфа о разделе(оттудава нужно: forum_name). Мне надо составить список забаненных юзверей в таком виде: имя забаненного юзверя|имя банившего|время бана|раздел|на сколько.
Всеб ничего, только проблема в том, как в одном sql запросе вытащить "имя забаненного юзверя" и "имя банившего", без "имени банившего" запрос выглядел так:

Сообщение от :
$sql = "SELECT b.*, u.username, f.forum_name
FROM " . BANLIST_TABLE . " b, " . USERS_TABLE . " u, " . FORUMS_TABLE . " f
WHERE u.user_id = b.ban_userid
AND f.forum_id = b.ban_forum
OR b.ban_forum = 0
AND b.ban_userid <> 0
AND u.user_id <> " . ANONYMOUS . "
ORDER BY b.ban_id desc";

дальше функциями движка мы вбиваем все, что получилось в массив:

Сообщение от :
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Could not select current user_id ban list', '', __LINE__, __FILE__, $sql);
}

$user_list = $db->sql_fetchrowset($result);
$db->sql_freeresult($result);

теперь в цикле перебираем все полученные данные и выводим на экран:

Сообщение от :
for($i = 0; $i < count($user_list); $i++)
{
$ban_time = create_date($board_config['default_dateformat'], $user_list[$i]['ban_date'] , $board_config['board_timezone']);
print $user_list[$i]['username'] . ' | '.$ban_time.' | '.$user_list[$i]['forum_name'].' | '. $user_list[$i]['ban_time'];
}

Все работает. А теперь у меня вопрос, как, не используя еще одного запроса(я его пихал в цикл, ресурсов жрал уйма, поэтому хостер и дал пинка, хотя все работало), т.е. затрачивая минимум ресурсов, вытащить имя юзверя, который забанил? [Ответ]
DimmaN 14:08 08.10.2007
написать примерно так (примерно - потому что не знаю правильного синтаксиса ПХП)

$sql = "SELECT b.*, u.username, f.forum_name, moders.username
FROM " . BANLIST_TABLE . " b, " . USERS_TABLE . " moders, " . USERS_TABLE . " u, " . FORUMS_TABLE . " f
WHERE u.user_id = b.ban_userid AND moders.user_id = b.ban_mod
AND f.forum_id = b.ban_forum
OR b.ban_forum = 0
AND b.ban_userid <> 0
AND u.user_id <> " . ANONYMOUS . "
ORDER BY b.ban_id desc";

PS только это не оптимизация [Ответ]
Zhendos II 15:37 08.10.2007
DimmaN, тогда такой вопрос, хоть и синтекса ПХП не знаешь, но все же. Вот я выполню такой запрос, потом запишу все это в массив:

Сообщение от :
$user_list = $db->sql_fetchrowset($result);

потом в цикле будем из этой переменной доставать то че нам надо:

Сообщение от :
for($i = 0; $i < count($user_list); $i++)
{
$ban_time = create_date($board_config['default_dateformat'], $user_list[$i]['ban_date'] , $board_config['board_timezone']);
print $user_list[$i]['username'] . ' | '.$ban_time.' | '.$user_list[$i]['forum_name'].' | '. $user_list[$i]['ban_time'];
}

и вот тут меня интересует, как я определю, к модератору ли относиться следущее значение:$user_list[$i]['username'] или к обычному юзверю, ведь как я понимаю, Sql запрос запишет в массив две одинаковах колонки, которые будут называться "username", только значение у них буит разное...
p.s. если кто мня поймет, будет хорошо, описал проблему как смог. [Ответ]
DimmaN 15:43 08.10.2007
ну епта, ну напиши тогда

$sql = "SELECT b.*, u.username, f.forum_name, moders.username as mod_name
FROM " . BANLIST_TABLE . " b, " . USERS_TABLE . " moders, " . USERS_TABLE . " u, " . FORUMS_TABLE . " f
WHERE u.user_id = b.ban_userid AND moders.user_id = b.ban_mod
AND f.forum_id = b.ban_forum
OR b.ban_forum = 0
AND b.ban_userid <> 0
AND u.user_id <> " . ANONYMOUS . "
ORDER BY b.ban_id desc"; [Ответ]
Zhendos II 17:09 08.10.2007
DimmaN, спасибо...
Теперь другое, перенес всю инфу с сервака на локалку, установил этот скрипт, теперь блин пишет:

Сообщение от :
Fatal error: Maximum execution time of 30 seconds exceeded in ...\www\admin\admin_user_ban.php on line 406

причем "on line 406" всегда разное и колеблиться внутри цикла:

Сообщение от :
for($i = 0; $i < count($user_list); $i++)
{
$ban_time = create_date($board_config['default_dateformat'], $user_list[$i]['ban_date'] , $board_config['board_timezone']);
print $user_list[$i]['username'].' | '. $user_list[$i]['mod_name']. ' | '.$ban_time.' | '.$user_list[$i]['forum_name'].' | '. $user_list[$i]['ban_time'];
}

вообщем делал пошти все, даже начальный скрипт херачил - открывает секунд через 20 еле-еле. Это все как я понял из-за объема информации, как с этим бороться, мож кто знает? [Ответ]
DimmaN 08:27 09.10.2007
Zhendos II, ну это уже ошибка ПХП парсера, как я понимаю. Типа страничку долго формирует.....А сколько ж записей возвертает запрос? [Ответ]
грека 08:37 09.10.2007

Сообщение от DimmaN:
$sql = "SELECT b.*, u.username, f.forum_name, moders.username
FROM " . BANLIST_TABLE . " b, " . USERS_TABLE . " moders, " . USERS_TABLE . " u, " . FORUMS_TABLE . " f
WHERE u.user_id = b.ban_userid AND moders.user_id = b.ban_mod
AND f.forum_id = b.ban_forum
OR b.ban_forum = 0
AND b.ban_userid <> 0
AND u.user_id <> " . ANONYMOUS . "
ORDER BY b.ban_id desc";

$sql = "SELECT b.*, u.username, f.forum_name, moders.username
FROM " . BANLIST_TABLE . " b "
. " LEFT JOIN " . USERS_TABLE . " moders ON b.ban_mod = moders.user_id "
. " LEFT JOIN " . USERS_TABLE . " u ON b.ban_userid = u.user_id "
. " LEFT JOIN " . FORUMS_TABLE . " f ON b.ban_forum = f.forum_id
WHERE b.ban_userid <> 0
AND b.ban_userid <> " . ANONYMOUS . "
ORDER BY b.ban_id desc"; [Ответ]
DimmaN 08:56 09.10.2007
грека, ну во первых лефт джоин меняет смысл, так что тут нужет фулл. Если ты перенес условие в джойны, то первые два предиката из where надо замочить Но эт фигня, понятно...

Главное, это так влияет на план исполнения запроса в МуСКЛ? Там тупой оптимизатор?
[Ответ]
грека 09:01 09.10.2007
DimmaN, мочить ничего не надо - я эти условия у тебя взял =)
фул тоже не нужен, потому что я так надеюсь что там юники на ключах стоят

а вот про планы мускула не в курсе, вполне может быть что он там декартово произведение в твоем случае делает. мало ли

upd: а, да - забыл условия джойнов из вхере выкинуть
[Ответ]
зайка 09:03 09.10.2007
жендос и жендос [Ответ]
грека 09:07 09.10.2007
зайка, он "зендос" =\ [Ответ]
Zhendos II 13:16 09.10.2007
зайка, а эт тип к чему?

Сообщение от грека:
зайка, он "зендос" =\

Как хош, так пускай и буит... не обижусь:-)

Сообщение от DimmaN:
А сколько ж записей возвертает запрос?

херанякнул EXPLAIN перед SELECT, получил:

Сообщение от :
table type possible_keys key key_len ref rows Extra
moders ALL PRIMARY NULL NULL NULL 6 Using temporary; Using filesort
u ALL PRIMARY NULL NULL NULL 6
f ALL PRIMARY NULL NULL NULL 3
b ALL NULL NULL NULL NULL 720 where used

но значения у хостера, на серваке намного больше, я от тудыва воткнул только табличку с баном, таблица u там имеет больше 14000, а f около 500.
Да и можно мне поподробнее про LEFT JOIN? [Ответ]
DimmaN 14:31 09.10.2007

Сообщение от Zhendos II:
Да и можно мне поподробнее про LEFT JOIN?

кури доку по SQL, совсем обленился [Ответ]
Zhendos II 14:55 09.10.2007
DimmaN, да все уже прочитал Пасиб большое.
Кста, мой sql запрос обрабатывался

Сообщение от :
7.3597481250763

эт только сам запрос, цикл еще дольше, после предложенного грека, стало:

Сообщение от :
0.041857004165649

а если в связке с циклом, то:

Сообщение от :
0.34096002578735

я думаю хостеру этого будет достаточно, чтоб нне загружать серв, да и вообще скрипт хотяп будет работать.
DimmaN, грека, пасиб.
[Ответ]
грека 16:04 09.10.2007
Zhendos II, я белую саузу уважаю если чо

Сообщение от Zhendos II:
а если в связке с циклом, то:
Цитата:
0.34096002578735

еп. да что ты там делаешь - траекторию шаттла что ли считаешь? =\ [Ответ]
Zhendos II 18:10 09.10.2007

Сообщение от грека:
еп. да что ты там делаешь - траекторию шаттла что ли считаешь? =\

Ну пошти, эт я так, для порядку высчитал, мож кому пригодится... [Ответ]
Вверх