Как избежать запросов в циклах?

Статус
Закрыто для дальнейших ответов.

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
Две таблицы: Форум, название: TB_1 (id,login,tema,opisanie) и комменты к темам на форуме, название: TB_2 (id, id_temy,login,komment)
Мне нужно вывести из этих двух таблиц на страницу в таком виде:
Тема: Бла бла бла из первой таблицы
Комментов: Число комментов к этой теме
И так на странице около 10 тем написано..
Код:
$zapros = mysql_query("SELECT * FROM `TB_1`");
while($_cikl = mysql_fetch_array($zapros)){
$zapros2 = mysql_result(mysql_query("SELECT COUNT(*) FROM `TB_2` WHERE `id_temy` = '"$_cikl['id']"'"),0);
echo 'Тема: '.$_cikl['tema'].' Комментов: '.$zapros2;
}
Все нормально работает, но недавно прочитал, что внутри циклов не должно быть запросов к БД... И это верно, ведь если тысяча тем на форуме, то получится тысяча запросов в цикле, что бы вывести подсчет...
 

Snickers

Быдлокодер
Регистрация
05.11.2010
Сообщения
388
Две таблицы: Форум, название: TB_1 (id,login,tema,opisanie) и комменты к темам на форуме, название: TB_2 (id, id_temy,login,komment)
Мне нужно вывести из этих двух таблиц на страницу в таком виде:
Тема: Бла бла бла из первой таблицы
Комментов: Число комментов к этой теме
И так на странице около 10 тем написано..
Код:
$zapros = mysql_query("SELECT * FROM `TB_1`");
while($_cikl = mysql_fetch_array($zapros)){
$zapros2 = mysql_result(mysql_query("SELECT COUNT(*) FROM `TB_2` WHERE `id_temy` = '"$_cikl['id']"'"),0);
echo 'Тема: '.$_cikl['tema'].' Комментов: '.$zapros2;
}
Все нормально работает, но недавно прочитал, что внутри циклов не должно быть запросов к БД... И это верно, ведь если тысяча тем на форуме, то получится тысяча запросов в цикле, что бы вывести подсчет...
в TB_1 создай колонку count и при добавлении поста прибавляй к значению +1
Код:
mysql_query("UPDATE `TB_1` SET `count`=`count`+1 WHERE `id`=$id LIMIT 1");
также следи чтобы не прибавлялось при редактировании поста и отнималось при удалении.
Код:
mysql_query("UPDATE `TB_1` SET `count`=`count`-1 WHERE `id`=$id LIMIT 1");
периодически можно делать пересчет для пущей уверености
Код:
$zapros = mysql_query("SELECT * FROM `TB_1`");
while($_cikl = mysql_fetch_array($zapros)){
    $count = mysql_result(mysql_query("SELECT COUNT(*) FROM `TB_2` WHERE `id` =".$_cikl['id']),0);
    mysql_query("UPDATE `TB_1` SET `count`=$count WHERE `id`=".$_cikl['id']);
}
 

medwoodu

Злобный модер
Регистрация
22.12.2005
Сообщения
1 418
Две таблицы: Форум, название: TB_1 (id,login,tema,opisanie) и комменты к темам на форуме, название: TB_2 (id, id_temy,login,komment)
Мне нужно вывести из этих двух таблиц на страницу в таком виде:
Тема: Бла бла бла из первой таблицы
Комментов: Число комментов к этой теме
И так на странице около 10 тем написано..
Код:
$zapros = mysql_query("SELECT * FROM `TB_1`");
while($_cikl = mysql_fetch_array($zapros)){
$zapros2 = mysql_result(mysql_query("SELECT COUNT(*) FROM `TB_2` WHERE `id_temy` = '"$_cikl['id']"'"),0);
echo 'Тема: '.$_cikl['tema'].' Комментов: '.$zapros2;
}
Все нормально работает, но недавно прочитал, что внутри циклов не должно быть запросов к БД... И это верно, ведь если тысяча тем на форуме, то получится тысяча запросов в цикле, что бы вывести подсчет...
Читаем про LEFT JOIN и GROUP BY, что нить типа SELECT TB_1.name, COUNT(TB_2.id) FROM TB_1 LEFT JOIN TB_2 ON TB_1.id = TB_2.id_temy GROUP BY TB_1.id
 

Snickers

Быдлокодер
Регистрация
05.11.2010
Сообщения
388
капец.. любят же минусы лепить... что за бред с колонкой говорите?
а представьте как машина грузится считать все посты всех тем на странице при каждом обновлении страницы? а если людей много? эта колонка смотрит в будущее и прогнозирует нагрузку. вы думаете в том же контакте сообщения каждый раз считаются заново? все это статичные данные, а в настройках есть кнопка для пересчета.
прежде чем писать что бред, подумайте хоть сначала. прокодеры млин (те кто минусы лепят)

я всегда стараюсь оптимизировать свой код, чтобы не пришлось в срочном порядке потом все переделывать когда сервер будет падать каждые 5 мин от перегрузки.
 

kein

Частный случай
Регистрация
23.11.2009
Сообщения
446
По существу правильно минус, потому как ваше решение подходит для крупных проектов, и несомненно лучше использовать дополнительное поле в некоторых случаях особенно когда таблиц в запросе выходит за 3-4 и больше.
В данном же случае ТС новичок, ему будет полезно знать, что можно просто получить результат правильным запросом, о котором он не подозревал.
А ваше решение, я уверен, внесет в его код большую путаницу, и несомненно будут ошибки, потому как за отдельным счетчиком следить сложнее, если конечно все запросы не вынесены в отдельную модель и код хорошо структурирован - но в данном случае я думаю такого нет - иначе не последовал бы подобный вопрос.
Да и нагрузка на его форуме вряд ли будет большой.
Исходя из всех эти размышлений лучшим решением относительно затраты/результат - будет решение по совету Medwoodu.
 

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
в TB_1 создай колонку count и при добавлении поста прибавляй к значению +1
Код:
mysql_query("UPDATE `TB_1` SET `count`=`count`+1 WHERE `id`=$id LIMIT 1");
также следи чтобы не прибавлялось при редактировании поста и отнималось при удалении.
Код:
mysql_query("UPDATE `TB_1` SET `count`=`count`-1 WHERE `id`=$id LIMIT 1");
периодически можно делать пересчет для пущей уверености
Код:
$zapros = mysql_query("SELECT * FROM `TB_1`");
while($_cikl = mysql_fetch_array($zapros)){
    $count = mysql_result(mysql_query("SELECT COUNT(*) FROM `TB_2` WHERE `id` =".$_cikl['id']),0);
    mysql_query("UPDATE `TB_1` SET `count`=$count WHERE `id`=".$_cikl['id']);
}
У меня вот раньше так и было сделано:) А за подсчет(кнопочки для пересчета) спасибо!

Читаем про LEFT JOIN и GROUP BY, что нить типа SELECT TB_1.name, COUNT(TB_2.id) FROM TB_1 LEFT JOIN TB_2 ON TB_1.id = TB_2.id_temy GROUP BY TB_1.id
Работает:):):) Только говорят, что в будущем будет грузить систему... Придется назад переделывать Ваш вариант на старый, который был прежде..
 

medwoodu

Злобный модер
Регистрация
22.12.2005
Сообщения
1 418
в TB_1 создай колонку count и при добавлении поста прибавляй к значению +1
Код:
mysql_query("UPDATE `TB_1` SET `count`=`count`+1 WHERE `id`=$id LIMIT 1");
также следи чтобы не прибавлялось при редактировании поста и отнималось при удалении.
Код:
mysql_query("UPDATE `TB_1` SET `count`=`count`-1 WHERE `id`=$id LIMIT 1");
периодически можно делать пересчет для пущей уверености
Код:
$zapros = mysql_query("SELECT * FROM `TB_1`");
while($_cikl = mysql_fetch_array($zapros)){
    $count = mysql_result(mysql_query("SELECT COUNT(*) FROM `TB_2` WHERE `id` =".$_cikl['id']),0);
    mysql_query("UPDATE `TB_1` SET `count`=$count WHERE `id`=".$_cikl['id']);
}
У меня вот раньше так и было сделано:) А за подсчет(кнопочки для пересчета) спасибо!

Читаем про LEFT JOIN и GROUP BY, что нить типа SELECT TB_1.name, COUNT(TB_2.id) FROM TB_1 LEFT JOIN TB_2 ON TB_1.id = TB_2.id_temy GROUP BY TB_1.id
Работает:):):) Только говорят, что в будущем будет грузить систему... Придется назад переделывать Ваш вариант на старый, который был прежде..
Вот когда будет, тогда и надо задумываться об оптимизации. Только я сомневаюсь, что будут сильно ощутимые нагрузки до миллиона записей:) а там вы уже захотите все переделать
 

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
Вот когда будет, тогда и надо задумываться об оптимизации. Только я сомневаюсь, что будут сильно ощутимые нагрузки до миллиона записей:) а там вы уже захотите все переделать
Переделал снова на Ваш вариант с соединением таблиц:) До миллиона мне ещё долго будет, т.к сайт даже не открывал, только тестирую его на локалке и на платном хостинге (пробные 14 дней обычно дают), уже 5й раз так регюсь и тестирую сайт на работу с мобильного:)
 

Snickers

Быдлокодер
Регистрация
05.11.2010
Сообщения
388
Вот когда будет, тогда и надо задумываться об оптимизации. Только я сомневаюсь, что будут сильно ощутимые нагрузки до миллиона записей:) а там вы уже захотите все переделать
Переделал снова на Ваш вариант с соединением таблиц:) До миллиона мне ещё долго будет, т.к сайт даже не открывал, только тестирую его на локалке и на платном хостинге (пробные 14 дней обычно дают), уже 5й раз так регюсь и тестирую сайт на работу с мобильного:)
мои первые сайты тоже для мобильников были) ой время было.. всяки WapEngine, WapMotor из движков. а из конструкторов, wab.ru, kmx.ru, ещё какие то были до кучи) афигенная в то время игра цивилизация civa.vab.ru хостинги тоже были бесплатные, например h2m.ru, кудаже без вареза seclub.org... блин. такое время профукали... порой даже обидно как обесценивается с ходом прогресса, когда раньше это было так круто а главное затягивало.. и игры стары, сейчас уже не так играются как раньше и нет той романтики прошлого... скучаю по квадратикам страшно)
 

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
мои первые сайты тоже для мобильников были) ой время было.. всяки WapEngine, WapMotor из движков. а из конструкторов, wab.ru, kmx.ru, ещё какие то были до кучи) афигенная в то время игра цивилизация civa.vab.ru хостинги тоже были бесплатные, например h2m.ru, кудаже без вареза seclub.org... блин. такое время профукали... порой даже обидно как обесценивается с ходом прогресса, когда раньше это было так круто а главное затягивало.. и игры стары, сейчас уже не так играются как раньше и нет той романтики прошлого... скучаю по квадратикам страшно)
Вот я тоже хочу сделать сайт, что то типа wab.ru - знакомств, где люди будут знакомиться и общаться:) Думаю, что те кто сидят с мобильных больше смотрят на интерфейс сайта, его функционал, поэтому стараюсь его наполнять, что бы в нем было что то такое, чего нет на других, но придумать это весьма сложно:( Я так же начинал с wab.ru, затем перешл на kmx, затем решил перейти на php, оч долго искал хостинг с поддержкой php, mysql и что бы рекламы не было, нашел: http://byethost.com/ - замечательный бесплатный хостинг, а главное (!) нет рекламы на сайте)
P.S А я даже не использую движков, пишу всё с нуля сам, пополняю себя знаниями, так сказать набиваю руку))
P.P.S А что за "квадратики"?
 

Snickers

Быдлокодер
Регистрация
05.11.2010
Сообщения
388
Вот я тоже хочу сделать сайт, что то типа wab.ru - знакомств, где люди будут знакомиться и общаться:) Думаю, что те кто сидят с мобильных больше смотрят на интерфейс сайта, его функционал, поэтому стараюсь его наполнять, что бы в нем было что то такое, чего нет на других, но придумать это весьма сложно:( Я так же начинал с wab.ru, затем перешл на kmx, затем решил перейти на php, оч долго искал хостинг с поддержкой php, mysql и что бы рекламы не было, нашел: http://byethost.com/ - замечательный бесплатный хостинг, а главное (!) нет рекламы на сайте)
P.S А я даже не использую движков, пишу всё с нуля сам, пополняю себя знаниями, так сказать набиваю руку))
P.P.S А что за "квадратики"?
квадратики в смысле пиксельная графика)
да ятоже писал свой первый двиг на вапе. у меня тогда душераздерающий постраничный вывод был) чего стоила только логика вывода номеров страниц)
я вообще только недавно выбрался из процедурного подхода создания скриптов и перешел к ооп)
 

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
квадратики в смысле пиксельная графика)
да ятоже писал свой первый двиг на вапе. у меня тогда душераздерающий постраничный вывод был) чего стоила только логика вывода номеров страниц)
я вообще только недавно выбрался из процедурного подхода создания скриптов и перешел к ооп)
Кажется, что с постраничным выводом в первый раз у всех происходит душераздирание, потому как я понял КАК работает скрипт вывода постраничной навигации, я перечитал не одну статью по php :) Главное понять работу скрипта, а не пользоваться готовыми, а то сайт будет нормальный - а как устранять ошибки и прочее не знаешь :wacko:

Вопрос не по теме, вот код:
Код:
$gl2 = mysql_query("SELECT `id` FROM `$userstable` WHERE `login` = '".$_SESSION['login']."' AND `pass` = '".$_SESSION['pass']."'");
if (mysql_num_rows($gl2)!==1){exit ('Ошибка входа!<br> <a href="/">На главную</a>');}
Он написан в инклуде, например config.php и подключается ко всем файлам, которые доступны только зарегистрированным - тем кто выполнил вход. Вход выполняется на главной странице, там для пароля и логина две формы, они обрабатываются, поылается запрос к БД, и если пользователем с таким логином и паролем найден, то заносим их в сессию.
Теперь вопрос:
Можно ли как то войти в запрещенную зону, т.е войти на сайт? Или подделать сессию?
 
  • Like
Реакции: kein

Snickers

Быдлокодер
Регистрация
05.11.2010
Сообщения
388
что касается подделки сессии.
это невозможно, сессию можно только украсть.
нельзя подделать ключ сессии, это уникальная строчка для каждого юзера. чтобы получить доступ к другому юзеру, необходимо вытащить ключ сессии из его браузера. иначе никак
 

minority

generator randomly php
Регистрация
02.05.2010
Сообщения
443
Код:
$gl2 = mysql_query("SELECT `id` FROM `$userstable` WHERE `login` = '".$_SESSION['login']."' AND `pass` = '".$_SESSION['pass']."'");
if (mysql_num_rows($gl2)!==1){exit ('Ошибка входа!<br> <a href="/">На главную</a>');}
Это у вас так реализована проверка сессии пользователя?
 

Snickers

Быдлокодер
Регистрация
05.11.2010
Сообщения
388
Код:
$gl2 = mysql_query("SELECT `id` FROM `$userstable` WHERE `login` = '".$_SESSION['login']."' AND `pass` = '".$_SESSION['pass']."'");
if (mysql_num_rows($gl2)!==1){exit ('Ошибка входа!<br> <a href="/">На главную</a>');}
Это у вас так реализована проверка сессии пользователя?
кстати да, запрос бесполезен. тот же ид можно опять же в сессии хранить.
а если просто нужно держать полльзователя залогининым. то достаточно просто сохранить в сессию ид. и доставать из базы по ид юзера.
значения сессии хранятся на сервере, а не у пользователя, у пользователя только ключ. так что нет смысла перепроверять данные каждый раз. они пользователем не изменяются и другой ид он написать не сможет
 

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
Код:
$gl2 = mysql_query("SELECT `id` FROM `$userstable` WHERE `login` = '".$_SESSION['login']."' AND `pass` = '".$_SESSION['pass']."'");
if (mysql_num_rows($gl2)!==1){exit ('Ошибка входа!<br> <a href="/">На главную</a>');}
Это у вас так реализована проверка сессии пользователя?
Ага... я не знал, что сессию нельзя подменить, считал что она как кука, поэтому и делал для это запрос в бд...

кстати да, запрос бесполезен. тот же ид можно опять же в сессии хранить.
а если просто нужно держать полльзователя залогининым. то достаточно просто сохранить в сессию ид. и доставать из базы по ид юзера.
значения сессии хранятся на сервере, а не у пользователя, у пользователя только ключ. так что нет смысла перепроверять данные каждый раз. они пользователем не изменяются и другой ид он написать не сможет
Т.е надо сделать вот так, без запросов?
Код:
if(!isset($_SESSION['id'])) {exit('Ошибка входа!')}
 

medwoodu

Злобный модер
Регистрация
22.12.2005
Сообщения
1 418
Код:
$gl2 = mysql_query("SELECT `id` FROM `$userstable` WHERE `login` = '".$_SESSION['login']."' AND `pass` = '".$_SESSION['pass']."'");
if (mysql_num_rows($gl2)!==1){exit ('Ошибка входа!<br> <a href="/">На главную</a>');}
Это у вас так реализована проверка сессии пользователя?
Ага... я не знал, что сессию нельзя подменить, считал что она как кука, поэтому и делал для это запрос в бд...

кстати да, запрос бесполезен. тот же ид можно опять же в сессии хранить.
а если просто нужно держать полльзователя залогининым. то достаточно просто сохранить в сессию ид. и доставать из базы по ид юзера.
значения сессии хранятся на сервере, а не у пользователя, у пользователя только ключ. так что нет смысла перепроверять данные каждый раз. они пользователем не изменяются и другой ид он написать не сможет
Т.е надо сделать вот так, без запросов?
Код:
if(!isset($_SESSION['id'])) {exit('Ошибка входа!')}
Лучше перекидывать на авторизацию.
 

FiRеFоX

V.I.P.
Регистрация
07.08.2010
Сообщения
744
Код:
$gl2 = mysql_query("SELECT `id` FROM `$userstable` WHERE `login` = '".$_SESSION['login']."' AND `pass` = '".$_SESSION['pass']."'");
if (mysql_num_rows($gl2)!==1){exit ('Ошибка входа!<br> <a href="/">На главную</a>');}
Это у вас так реализована проверка сессии пользователя?
Ага... я не знал, что сессию нельзя подменить, считал что она как кука, поэтому и делал для это запрос в бд...

кстати да, запрос бесполезен. тот же ид можно опять же в сессии хранить.
а если просто нужно держать полльзователя залогининым. то достаточно просто сохранить в сессию ид. и доставать из базы по ид юзера.
значения сессии хранятся на сервере, а не у пользователя, у пользователя только ключ. так что нет смысла перепроверять данные каждый раз. они пользователем не изменяются и другой ид он написать не сможет
Т.е надо сделать вот так, без запросов?
Код:
if(!isset($_SESSION['id'])) {exit('Ошибка входа!')}
Лучше перекидывать на авторизацию.
Сделал) Большое спасибо, теперь хоть избавился ещё от одного лишнего запроса)
 
Статус
Закрыто для дальнейших ответов.
Верх Низ