Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Выбор случайных фото / 25 сообщений из 34, страница 1 из 2
19.01.2005, 12:48
    #32872147
TigranE
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
Таблица базы данных содержит фотографии товаров, каждая запись в таблице имеет два поля - id(первичный ключ) и good_id(внешний ключ к соответствующей записи в таблице товаров). Необходимо случайным образом выбрать RAND_PHOTOS_NUM (напр. 3) фотографий. Выбранные фотографии не должны повторятсья. Общее число фотографий в таблице может оказаться меньше RAND_PHOTOS_NUM.

Написал следующий код, но мне кажется все можно сделать гораздо проще. Пожалуйста посоветуйте как оптимизировать приведенный отрывок кода или скажите другое решение. Спасибо.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
  $photos=array();
  $res=mysql_query('select * from '.TBL_PHOTOS) or die(mysql_error());
  while($row=mysql_fetch_assoc($res))
    $photos=$row
  $num_photos=count($photos);
  $rand_photos=array();
  $max_iters= 20 ;
  if ($num_photos> 0 )
  {
    $j= 0 ;
    while($j<RAND_PHOTOS_NUM)
    {
      $k= 0 ;
      while(array_key_exists($rand_val, $rand_photos) && $k< 20 )
      {
        $rand_val=mt_rand( 0 , $num_photos- 1 );
        $rand_photos[$j]=$photos[$rand_val];
        $k++;
      }
      $j++;
    }
  }
  
...
Рейтинг: 0 / 0
19.01.2005, 13:04
    #32872197
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
TigranEмне кажется все можно сделать гораздо проще.Не проще, а правильнее$res=mysql_query('select * from '.TBL_PHOTOS) or die(mysql_error());Незачем запрашивать ВСЮ базу данных, чтобы выбрать из неё три элемента.
Код:
1.
2.
$res = mysql_query('SELECT COUNT(*) as cnt FROM '.TBL_PHOTOS);
$data = mysql_fetch_assoc($res);
$res = mysql_query('SELECT * FROM '.TBL_PHOTOS.' LIMIT '.mt_rand(0,$data['cnt']-1);
ну и т.д.
...
Рейтинг: 0 / 0
19.01.2005, 14:14
    #32872399
4m@t!c
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
*Незачем запрашивать ВСЮ базу данных, чтобы выбрать из неё три элемента.
Код:
1.
2.
3.
4.
5.
$res = mysql_query('SELECT COUNT(*) as cnt FROM '.TBL_PHOTOS);

что бы подсчитать кол-во элементов - перебирается вся база
 *
$data = mysql_fetch_assoc($res);
$res = mysql_query('SELECT * FROM '.TBL_PHOTOS.' LIMIT '.mt_rand(0,$data['cnt']-1);
ну и т.д.
Я понимаю, что нет такого понятий, как "первый элемент БД", "последний элемент БД". Есть просто строка и идентификатор этого поля(не всегда). Если таблица с картинками не обновляется, то запрос будет выбриать одни и те же n-первых фото.
...
Рейтинг: 0 / 0
19.01.2005, 14:41
    #32872467
hell
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
А так?)

Код: plaintext
1.
select distinct  x from table order by rand() limit  3 

В этом плане MySQL очень удобен

"The CBO without stats is like a morning without coffee." T.Kyte
...
Рейтинг: 0 / 0
19.01.2005, 17:15
    #32873009
DocAl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
4m@t!c
что бы подсчитать кол-во элементов - перебирается вся база

База (а, точнее, таблица) перебирается для подсчёта количества элементов только при отсутствии подходящего индекса.
...
Рейтинг: 0 / 0
19.01.2005, 17:16
    #32873012
DocAl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
hellА так?)

Код: plaintext
1.
select distinct  x from table order by rand() limit  3 

В этом плане MySQL очень удобен

"The CBO without stats is like a morning without coffee." T.Kyte
Выглядит изячно, но не будет ли такой запрос использовать временную таблицу?...
...
Рейтинг: 0 / 0
19.01.2005, 17:28
    #32873044
4m@t!c
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
DocAl 4m@t!c
что бы подсчитать кол-во элементов - перебирается вся база

База (а, точнее, таблица) перебирается для подсчёта количества элементов только при отсутствии подходящего индекса.
гы-гы.. да с "базой" - это я конечно лопухнул. А насчет индекса - индекс же должен быть в условии, а если нет условия, то речь же за индекс не идет.
...
Рейтинг: 0 / 0
19.01.2005, 17:39
    #32873075
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
4m@t!c *Незачем запрашивать ВСЮ базу данных, чтобы выбрать из неё три элемента.
Код:
1.
2.
$res = mysql_query('SELECT COUNT(*) as cnt FROM '.TBL_PHOTOS);что бы подсчитать кол-во элементов - перебирается вся база[/quote]Не понял юмора. Это объяснение того, что делалось в оригинале или что?[quot  *]
$data = mysql_fetch_assoc($res);
$res = mysql_query('SELECT * FROM '.TBL_PHOTOS.' LIMIT '.mt_rand(0,$data['cnt']-1);
ну и т.д.
Я понимаю, что нет такого понятий, как "первый элемент БД", "последний элемент БД". Есть просто строка и идентификатор этого поля(не всегда). Если таблица с картинками не обновляется, то запрос будет выбриать одни и те же n-первых фото.Да, ошибочка вышла, забыл указать второй параметр после запятой (почему-то решил, что первый параметр - номер записи, а не количество). А по поводу остального добавить нужный ORDER BY, надеюсь, труда не составит?
...
Рейтинг: 0 / 0
19.01.2005, 17:41
    #32873081
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
По поводу ORDER BY RAND читайте ман.
...
Рейтинг: 0 / 0
19.01.2005, 17:56
    #32873123
DocAl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
Ман штука хорошая, но именно тут он ничего особо полезного не сказал.
Запрос работает, да, делает то, что нужно.
Но про то, что такой запрос будет создавать временную таблицу не сказано, а это, увы, факт..( Со всем вытекающими в случае, если таблица большая...
...
Рейтинг: 0 / 0
19.01.2005, 20:16
    #32873371
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
Да пёс с ней, с временной таблицейВ выражениях вида ORDER BY не следует использовать столбец с величинами RAND(), поскольку применение оператора ORDER BY приведет к многократным вычислениям в этом столбце.
...
Оператор RAND() не следует воспринимать как полноценный генератор случайных чисел...Этого достаточно, чтобы не использовать ORDER BY RAND
Ещё помнится бывали глюки на 3.x версии с тем, что выбиралось одно и то же (не каждый раз одно и то же, но довольно часто, да и периуд был небольшим).
...
Рейтинг: 0 / 0
19.01.2005, 20:35
    #32873390
TigranE
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
блинЫ, пришли туда откуда начали :) так что мне делать с этими случайными фото?
...
Рейтинг: 0 / 0
19.01.2005, 21:53
    #32873442
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
TigranEблинЫ, пришли туда откуда начали :) так что мне делать с этими случайными фото?Я же всё написал - выбираете COUNT'ом количество записей, потом при помощи PHP генерируете нужное число случайных чисел и достаёте записи в указанных позициях (LIMIT rnd,1) при некотором способе сортировки (ORDER BY id, к примеру). Да, это требует N+1 запрос к базе - если кто-нибудь знает более простой и надёжный способ - было бы интересно услышать (жаль нельзя доставать из базы сразу из нескольких диапазонов, типа LIMIT x,1,y,1,z,1)
...
Рейтинг: 0 / 0
19.01.2005, 22:53
    #32873465
TigranE
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
*Я же всё написал - выбираете COUNT'ом количество записей, потом при помощи PHP генерируете нужное число случайных чисел и достаёте записи в указанных позициях (LIMIT rnd,1) при некотором способе сортировки (ORDER BY id, к примеру). Да, это требует N+1 запрос к базе - если кто-нибудь знает более простой и надёжный способ - было бы интересно услышать (жаль нельзя доставать из базы сразу из нескольких диапазонов, типа LIMIT x,1,y,1,z,1)

Так что-ли? Поправьте новичка плиз :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
  $res=mysql_query('select count(*) from '.TBL_PHOTOS) or die(mysql_error());
  $num_photos=mysql_result($res,  0 ,  0 );
  $max_iters= 20 ;
  $rand_photos=array();
  $rand_vals=array();
  for ($i= 0 ; $i<RAND_PHOTOS_NUM; $i++)
  {
    $k= 0 ;
    do {
      $rand_val=mt_rand( 0 , $num_photos- 1 );
      $k++;
    } while(in_array($rand_val, $rand_vals) && $k<$max_iters);
    $rand_vals[]=$rand_val;

    $res=mysql_query('select * from '.TBL_PHOTOS.
      " order by id limit $rand_val, 1") or die(mysql_error());
    if ($row=mysql_fetch_assoc($res))
      $rand_photos[]=$row;
  }
...
Рейтинг: 0 / 0
19.01.2005, 22:55
    #32873466
TigranE
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
кстати при чем тут "order by"?
...
Рейтинг: 0 / 0
19.01.2005, 23:01
    #32873467
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
TigranEТак что-ли? Поправьте новичка плиз :)Оно работает? Значит похоже. Оно не работает? PHP FAQ: Ничего не работает! Что делать??? (хотя похоже вы с ним знакомы ;) )
2 TigranE : PHP FAQ: MySQL. Просто и понятно.
...
Рейтинг: 0 / 0
20.01.2005, 12:12
    #32874270
Армянка
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
По темe выбора случайных строк из таблицы MYSQL запросом:

Код: plaintext
select * from tablename order by rand(unix_timestamp()) limit  1 
Подобный запрос подойдет для небольших таблиц, если же таблица содержит
несколько сот тысяч записей запрос будет работать медлено т.к. MySQL будет
обрабатывать все записи таблицы, расладывая их в случайном порядке и только
после этого выбирая первую запись в полученной очередности. Все это, конечно,
требует определенного времени. В случае, если у вас есть хотя бы одно поле
типа auto_increment, для создания более быстрого запроса можно поступить
следующим образом:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
  $res=mysql_query('select min(id), max(id) from '.TBL_PHOTOS)
    or die(mysql_error());
  $min_id=mysql_result($res,  0 ,  0 );
  $max_id=mysql_result($res,  0 ,  1 );
  $rand_id=rand($min_id, $max_id);
  $res=mysql_query('select * from '.TBL_PHOTOS." where id>=$rand_id limit 1")
    or die(mysql_error());
  if ($row=mysql_fetch_assoc($res))
  {
    extract($row);
    ........
    ........
  }

P.S. Тигран джан, я нечто подобное уже варила для сайта кока-колы, если ничего
не выйдет позвони, отмылю.
...
Рейтинг: 0 / 0
20.01.2005, 12:15
    #32874279
hell
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
*Этого достаточно, чтобы не использовать ORDER BY RAND
Ещё помнится бывали глюки на 3.x версии с тем, что выбиралось одно и то же (не каждый раз одно и то же, но довольно часто, да и периуд был небольшим).

http://dev.mysql.com/doc/mysql/ru/LIMIT_optimisation.html]про LIMIT


Если LIMIT # используется с ORDER BY, MySQL закончит сортировку, как только найдет первые # строк, вместо того, чтобы сортировать всю таблицу.


Т.е. по идее для LIMIT 3 строк думаю не очень страшно 3 вызова RAND() :-)

Хотя проверить не могу.
Насчет временной таблицы - сортировка так или иначе использует временную таблицу(если индекса нет, конечно)
...
Рейтинг: 0 / 0
20.01.2005, 12:24
    #32874315
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
hellТ.е. по идее для LIMIT 3 строк думаю не очень страшно 3 вызова RAND() :-)И как вы себе это представляете? Для начала необходимо каждой записи сопоставить случайное число, а у вас же получается взял первые попавшиеся три записи и забыл (это бы ещё ничего, если бы они действительно всегда получались случайными).
2 Армянка , опять же не хватает ORDER BY (хотя не знаю, насколько оно всё же необходимо - спорный вопрос), а из-за привязки к id получается неравномерное распределение (и вообще малопонятно что из-за отсутсвия ORDER BY) - представьте гипотетическую ситуацию - в базе всего две записи, с id = 1 и c id = 1000 - как вы думаете, какая из них в вашем случае будет выпадать чаще? ;)
Вот и получается, что те записи, до которых есть большой промежуток, будут "выпадать" чаще, чем те, которые идут подряд.
...
Рейтинг: 0 / 0
20.01.2005, 12:54
    #32874440
Армянка
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
Переписываем с учетом справедливого замечания г-на * :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
$res=mysql_query('select min(id), max(id) from '.TBL_PHOTOS)
    or die(mysql_error());
  $min_id=mysql_result($res,  0 ,  0 );
  $max_id=mysql_result($res,  0 ,  1 );
  $rand_id=mt_rand($min_id, $max_id);

  $sign = mt_rand( 0 ,  1 ) ? '>=' : '<';

  $res=mysql_query('select * from '.TBL_PHOTOS." where id $sign $rand_id limit 1")
    or die(mysql_error());
  if ($row=mysql_fetch_assoc($res))
  {
    extract($row);
    ........
    ........
  }
 
...
Рейтинг: 0 / 0
20.01.2005, 13:13
    #32874521
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
[quot Армянка]Переписываем с учетом справедливого замечания г-на * :)[/quote]Судя по всему - вы его не поняли.
...
Рейтинг: 0 / 0
20.01.2005, 13:24
    #32874579
Армянка
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
*[quot Армянка]Переписываем с учетом справедливого замечания г-на * :)[/quote]Судя по всему - вы его не поняли.

так просветите великодушно :))
...
Рейтинг: 0 / 0
20.01.2005, 13:29
    #32874601
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
Армянкатак просветите великодушно :))Просто прочтите ещё раз внимательно - от дыр и неравномерности вы так не избавитесь
...
Рейтинг: 0 / 0
20.01.2005, 16:18
    #32875283
hell
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
*Я же всё написал - выбираете COUNT'ом количество записей, потом при помощи PHP генерируете нужное число случайных чисел и достаёте записи в указанных позициях (LIMIT rnd,1) при некотором способе сортировки (ORDER BY id, к примеру). Да, это требует N+1 запрос к базе - если кто-нибудь знает более простой и надёжный способ - было бы интересно услышать (жаль нельзя доставать из базы сразу из нескольких диапазонов, типа LIMIT x,1,y,1,z,1)

Согласен, rand() будет выполнятся для всех случаев. Но и в вашем случае будет происходить полное сканирование таблицы/индекса:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
mysql> EXPLAIN select id from bugs.mantis_bug_table ORDER BY id LIMIT  5 , 1 ;
+------------------+-------+---------------+---------+---------+------+------+-------------+
| table            | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+------------------+-------+---------------+---------+---------+------+------+-------------+
| mantis_bug_table | index | NULL          | PRIMARY |        4  | NULL |    30  | Using index |
+------------------+-------+---------------+---------+---------+------+------+-------------+
 1  row in set ( 0 . 00  sec)

mysql> EXPLAIN select id from bugs.mantis_bug_table ORDER BY rand() LIMIT  1 ;
+------------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| table            | type  | possible_keys | key     | key_len | ref  | rows | Extra                                        |
+------------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| mantis_bug_table | index | NULL          | PRIMARY |        4  | NULL |    30  | Using index; Using temporary; Using filesort |
+------------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
 1  row in set ( 0 . 00  sec)
...
Рейтинг: 0 / 0
20.01.2005, 16:40
    #32875376
*
*
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выбор случайных фото
hellНо и в вашем случае будет происходить полное сканирование таблицы/индекса:А я и не утверждал обратного. Если внимательно вчитаться в ман, то будет понятно, что проблема в том, что функция RAND() - нешустрая. Собственно, возьмите базу поболе и посмотрите по времени, что будет быстрее select id from bugs.mantis_bug_table ORDER BY id LIMIT 5,1 или select id from bugs.mantis_bug_table ORDER BY rand() LIMIT 1
PS: подозреваю, что время выборки будет зависеть от номера записи, т.е. сгенерированного $rnd - попробуйте взять первую запись (LIMIT 0,1) и последнюю (LIMIT $max,1) и усреднить результат - у меня при единичных запросах (без учёта SELECT COUNT(*) FROM bugs.mantis_bug_table - MyAdmin не выдаёт время её выполнения - делать более правильный тест было лень) разница составила ~4 раза. Возможно, при выборе сразу нескольких записей, ситуация изменится (RAND() позволяет это сделать в один запрос). А вообще, попробуйте - из того же phpMyAdmin'а при многократных запросах типа select id from bugs.mantis_bug_table ORDER BY rand() результат мне показался неудовлетворительным.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Выбор случайных фото / 25 сообщений из 34, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]