Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Как работает mysql_query? (https://javascript.ru/forum/server/30436-kak-rabotaet-mysql_query.html)

Freakmeister 04.08.2012 00:24

Как работает mysql_query?
 
Снова встал ребром вопрос - как написать менее ресурсоёмко? Вчера мой сайт благополучно лёг после вживления в него нового куска кода. При 5 пользователях онлайн, проц был съеден моментально, а остатки оперативы в последующие 10 минут. Причиной этому послужил не код приведённый ниже - это уже моя попытка понять как можно написать менее ресурсоёмко.

Собссна, теоретический вопрос к знатокам - когда я делаю такой запрос с циклом, то что происходит при этом?
var $limit=10;
var $n=0;
$query = mysql_query("SELECT * FROM phpbb_posts ORDER BY post_id DESC", $db);
while ($n<$limit) {
	$row = mysql_fetch_array($query);
	$n++;
	//операции
}

Вариант А: mysql_query вытаскивает ВСЕ данные из phpbb_posts одним запросом, что очень ресурсоёмко, а потом mysql_fetch_array обрабатывает результат уже средствами php.
Вариант Б: mysql_query просто инициализирует связь с таблицей по выбранному фильтру, без вытаскивания значений, что не даёт особой нагрузки, а само вытаскивание уже происходит маленькими порциями при каждом обращении к mysql_fetch_array.
Вариант Ц: Ты баклан, почему ты не использовал LIMIT в SQL-запросе?

Для тех кто склоняется к последнему варианту, поясняю - в моём случае использовать LIMIT в SQL-запросе не получится. Потому что проверка прав пользователя происходит средствами php, и приходится сначала вытаскивать запись из БД, а потом уже проверять километровой функцией нужно выводить её на страницу или нет (грёбаный phpBB).

devote 04.08.2012 00:58

Цитата:

Сообщение от Freakmeister
Потому что проверка прав пользователя происходит средствами php, и приходится сначала вытаскивать запись из БД, а потом уже проверять километровой функцией нужно выводить её на страницу или нет (грёбаный phpBB).

и что с чем вы сравниваете в PHP ? какие поля сравниваете и с какими? Любой вопрос я уверен что можно решить простыми запросами в БД

Freakmeister 04.08.2012 02:32

Не всё так просто. В phpBB привелегии пользователей храняться хрен найди в зашифрованном виде где. И доступ к форумам проверяется функцией, которая это дело расшифровывает: $auth->acl_get('f_read', $forum_id). Прямым доступом к БД тут никак не сделаешь. Картинка в тему:


B@rmaley.e><e 04.08.2012 07:39

Цитата:

Сообщение от Freakmeister
Вариант А: mysql_query вытаскивает ВСЕ данные из phpbb_posts одним запросом, что очень ресурсоёмко, а потом mysql_fetch_array обрабатывает результат уже средствами php.
Вариант Б: mysql_query просто инициализирует связь с таблицей по выбранному фильтру, без вытаскивания значений, что не даёт особой нагрузки, а само вытаскивание уже происходит маленькими порциями при каждом обращении к mysql_fetch_array.
Вариант Ц: Ты баклан, почему ты не использовал LIMIT в SQL-запросе?

Почему это вариант Б лучше — непонятно. От постоянного дёрганья базе лучше стать не может. А ещё данные, соответствующие выборке, надо где-то хранить. Как это делать с учётом того, что данных могут попросить много, а клиентов может быть ещё больше и всем надо быстро ответить — опять же, неясно. Ну и для идентификации нужен какой-нибудь идентификатор сессии, который придётся пересылать при каждом запросе, что увеличит как сетевую нагрузку, так и время работы БД, т.к. ей придется каждый раз искать данные, соответствующие сессии.

micscr 04.08.2012 11:02

Одно из правил оптимизации - не делать SELECT *, а перечислять нужные поля.
Т.к. запрос то на mysql сервере сразу отработает и все данные где то будет хранить.
SELECT по всем постам это ужас.
Думай чтобы разбить этот алгоритм на множественное кол-во запросов. Сначала получаешь ограничения, а потом по этим ограничениям выбираешь данные.

Freakmeister 04.08.2012 13:26

Я изначально сделал так, после чего мой VDS-сервер благополучно лёг:

$i=$n=0;
$limit = 10;
while ($n<$limit) {
    $query = mysql_query("SELECT post_id, topic_id, forum_id, poster_id, post_time, post_subject FROM phpbb_posts ORDER BY post_id DESC LIMIT $i,1", $_P['db']);
    $row = mysql_fetch_array($query);

    if ($auth->acl_get('f_read', $row['forum_id'])) { // есть ли у юзера доступ

        //вытаскиваем имя пользователя и цвет его ника
        $query2 = mysql_query("SELECT username, user_colour FROM `phpbb_users` WHERE user_id=".$row['poster_id']." LIMIT 1", $_P['db']);
        $row2 = mysql_fetch_array($query2);

        //здесь идёт вывод через echo
         $n++;
    }
    $i++;
}

При обновлении страницы тут делается 20 маленьких запросов в лучшем случае. Короче, я сейчас думаю в сторону mysql_unbuffered_query.

devote 04.08.2012 14:10

Цитата:

Сообщение от Freakmeister
$auth->acl_get

ну дык расковыряй что делает эта функция... и какая версия phpBB?

Freakmeister 05.08.2012 15:26

Нормального алгоритма для безглючной работы этого блока так и не придумал, пришлось рыть документацию по phpBB. В итоге сделал так:
$ignore=implode(',', array_keys($auth->acl_getf('!f_read', true))); //получаем список всех форумов, к которым у пользователя нет доступа

Ну а дальше - WHERE NOT IN($ignore)


Часовой пояс GMT +3, время: 10:19.