Как работает 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, время: 17:53. |