Как работает 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). |
Цитата:
|
Не всё так просто. В phpBB привелегии пользователей храняться хрен найди в зашифрованном виде где. И доступ к форумам проверяется функцией, которая это дело расшифровывает: $auth->acl_get('f_read', $forum_id). Прямым доступом к БД тут никак не сделаешь. Картинка в тему:
![]() |
Цитата:
|
Одно из правил оптимизации - не делать SELECT *, а перечислять нужные поля.
Т.к. запрос то на mysql сервере сразу отработает и все данные где то будет хранить. SELECT по всем постам это ужас. Думай чтобы разбить этот алгоритм на множественное кол-во запросов. Сначала получаешь ограничения, а потом по этим ограничениям выбираешь данные. |
Я изначально сделал так, после чего мой 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. |
Цитата:
|
Нормального алгоритма для безглючной работы этого блока так и не придумал, пришлось рыть документацию по phpBB. В итоге сделал так:
$ignore=implode(',', array_keys($auth->acl_getf('!f_read', true))); //получаем список всех форумов, к которым у пользователя нет доступа Ну а дальше - WHERE NOT IN($ignore) |
Часовой пояс GMT +3, время: 10:19. |