Автор Тема: Случайная картинка  (Прочитано 12299 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн tigranav

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 6
  • +0/-0
  • 0
    • Просмотр профиля
    • http://www.tigranav.net
Случайная картинка
« : 06 Декабря 2006, 09:59:33 »
Как лучше сделать скрипт случайное фото?
Исходные данные - таблица с картинками
У меня в  голове крутиться самый простой вариант:
 просто выгружать все картинки в массив, потом брать случайный номер и выводить

Может быть есть более правильный метод?

Оффлайн html_coder

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 427
  • +0/-0
  • 0
    • Просмотр профиля
Случайная картинка
« Ответ #1 : 06 Декабря 2006, 10:43:02 »
Если эта таблица в базе (мало ли какая таблица может быть)

то можно например так
Таким запросом получаешь общее колиеч



$result 
mysql_query(\'SELECT COUNT(*) as images_count FROM images\');
$images_count = mysql_result($result, 0, 0);
random_image = rand(0, $images_count);

//Случайное изображение
mysql_query(\'SELECT * FROM images LIMIT \'.$random_image.\',1);



Вот примерно так можно попробовать.

Оффлайн tigranav

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 6
  • +0/-0
  • 0
    • Просмотр профиля
    • http://www.tigranav.net
Случайная картинка
« Ответ #2 : 06 Декабря 2006, 10:56:25 »
Да, именно так я и думал. Просто хотелось узнать, может быть как то по другому будет быстро...

Спасибо за ответ.

Оффлайн Egorsha

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 60
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Случайная картинка
« Ответ #3 : 08 Декабря 2006, 09:16:20 »
По другому тоже можно. И быстрее будет. Но это тема другой ветки форума.

SELECT *  FROM images ORDER BY RAND() LIMIT 1

- всего один запрос.

Оффлайн tigranav

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 6
  • +0/-0
  • 0
    • Просмотр профиля
    • http://www.tigranav.net
Случайная картинка
« Ответ #4 : 08 Декабря 2006, 09:25:57 »
А какой ветки?
Это полный запрос или в RAND нужно писать параметры?

Оффлайн Egorsha

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 60
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Случайная картинка
« Ответ #5 : 08 Декабря 2006, 10:06:23 »
Это полный запрос. Поменяй только название базы, если не совпадает.

А ветка скорее всего "Базы данных".
Там кстати такое уже обсуждалось - одна случайная запись из базы.

Оффлайн tigranav

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 6
  • +0/-0
  • 0
    • Просмотр профиля
    • http://www.tigranav.net
Случайная картинка
« Ответ #6 : 08 Декабря 2006, 10:10:00 »
Примного благодарен.

Оффлайн html_coder

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 427
  • +0/-0
  • 0
    • Просмотр профиля
Случайная картинка
« Ответ #7 : 08 Декабря 2006, 10:43:40 »
Цитировать
Egorsha:
По другому тоже можно. И быстрее будет. Но это тема другой ветки форума.

 SELECT * FROM images ORDER BY RAND() LIMIT 1

 - всего один запрос.


Egorsha, а вы уверены что это будет быстрее???

А если таблица будет большая?

Из документации по MySQL:

В выражениях вида ORDER BY не следует использовать столбец с величинами RAND(), поскольку применение оператора ORDER BY приведет к многократным вычислениям в этом столбце.

Оффлайн Egorsha

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 60
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Случайная картинка
« Ответ #8 : 08 Декабря 2006, 12:03:12 »
Если уж очень интересно, то попытаюсь ответить...
(Хотя сейчас, после переноса топика в другую ветку - опять разговор не по теме получится.)

На счет уверенности - скорее уверен в том, что ни в чем не уверен.

Но осмелюсь заметить, что в заданном вопросе не уточнялась какая база используется. (Решили, что MySQL - типа "по умолчанию"). А вдруг у других БД в документации по иному прописано.

Быстрее? Можно проверить на опыте, в данном конкретном случае (это дело задавшего вопрос).

И еще хочу объяснить, то почему ответил в этом топике.
Мне просто не понравился первоначальный  Ваш ответ. :)

Почему?  

Все просто -  приведенный Вами код делает не то, о чем спрашивали.

Построчно:
- запрос на количество записей в таблице;
- получение количества записей;
- случайное число N в интевале от "нуля" до "количество записей"
-... и наконец получение N первых записей из таблицы (но не одной случайной)

При Вашем подходе к поставленному вопросу, нужно сделать выборку всех записей (при большой базе - получится большой массив), в посчитать количество элементов массива, случайным образом выбрать элемент массива, содержащий id-записи и по этому id получить запись из базы. Нумерация записей может быть не скозной, а с пробелами (к примеру записи id=999 может не быть в базе, а N=999).

И что так быстрее будет (если база большая)?

И, кстати, вместо функции rand()  лучше бы воспользоваться mt_rand()....

Но от темы уже ушли.

Может закрыть эту тему? а?

Оффлайн for_i_0

  • $15 per hour
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 555
  • +0/-0
  • 2
    • Просмотр профиля
    • http://www.php.net/manual/en
Случайная картинка
« Ответ #9 : 08 Декабря 2006, 13:00:27 »
Egorsha
[OFF]Пожалуй, подождем html_coder - а.[/OFF]
[off]Безработный[/off]

Оффлайн html_coder

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 427
  • +0/-0
  • 0
    • Просмотр профиля
Случайная картинка
« Ответ #10 : 08 Декабря 2006, 13:13:36 »
Цитировать
Egorsha:
Может закрыть эту тему? а?


Нет, от чего же закрыть, тему надо развить...

Значит ещё раз смотрим внимательно мой пример.

1) Где в моем коде я перекладываю всё полученное из базы в массив?
2)
Цитировать
Egorsha:
и наконец получение N первых записей из таблицы (но не одной случайной)


А это где?

Смотрим сюда Что какое LIMIT n,m

Проще говоря запрос выбирает одну запись со смещения $random_image,  которое как вы правильно поняли будет в интервале от 0 до количества изображений, т.е. гаранитировано я выберу одну запись и 100% случайную... Где привязка к ID? В данном случае абсолютно всё равно какие ID есть в базе а каких нет?

По поводу быстродействия утверждать не буду надо проверять, но практически уверен, что на огрмной таблице ORDER BY RAND() будет работать медленнее (сталкивался с ним), при чем гораздо!

Оффлайн Egorsha

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 60
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Случайная картинка
« Ответ #11 : 08 Декабря 2006, 14:25:35 »
Все сдаюсь ;)

Цитировать
html_coder:
...ещё раз смотрим внимательно мой пример...


И это правильно - не доглядел ;)

mysql_query(\'SELECT * FROM images LIMIT \'.$random_image.\',1);

Увидел это, и воспринял "неправильно", типа так:


mysql_query
(\'SELECT * FROM images LIMIT \'.$random_image,1);


отсюда "LIMIT n", "первые n" и т.д.
(Только давай этот второй параметр "1" не будем развивать в продолжение темы ;) Он меня слегка смутил, но так как давно уже написан класс работы с базой и я "явно" этой функцией так же давно не пользуюсь (и вряд ли "явно" воспользуюсь)).

А вот если бы я "правильно" увидел:

mysql_query(\'SELECT * FROM images LIMIT \'.$random_image.\',1\');


То сразу бы заметил LIMIT n,m :) (Ну, а что делать, я тоже могу ошибаться. Вон нет "кавычки" и все ОК. :))

И вот уже интересно, чес слово, все это проверить, что быстрее.
Из всех таблиц, что  есть в распоряжении одна с 7200 записями. Потянет за "огромную"? (Другой просто нет).
Или "чистота эксперимента" не будет соблюдена?

Тему надеюсь не закроют до окончания "эксперимента"? :)

Оффлайн Yukko

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1586
  • +0/-0
  • 0
    • Просмотр профиля
    • http://estrabota.com.ua
Случайная картинка
« Ответ #12 : 08 Декабря 2006, 14:49:03 »
Цитировать
А вдруг у других БД в документации по иному прописано.

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

Я в код MySQL не смотрел, пусть меня поправят те, кто смотрел, но про механизм образования этого "случайного" я могу догадаться проведя эксперимент:
select * from table order by 1
select * from table order by 2
select * from table order by 3
select * from table order by n
где n — количество полей в таблице.
Если ORDER BY RAND() случайно где-то сортирует таблицу по одному из случайно выбранных полей, а потом берет случайную запись из получившегося результата, то можно себе представить, что будет, если сортировка будет проводиться на таблице с миллионом записей и по полю, по которому нет индекса.

Делать ORDER BY RAND() на больших таблицах без LIMIT, детально не разобравшись, сколько рядков будет просмотрено, чтобы вернулся  запрошенный результат, по которому будет делаться ORDER BY RAND(), я бы не стал ;) склеит ласты, потом не расклеишь. Судя по всему, в мануале не зря написан пример:
mysql> SELECT * FROM table1, table2 WHERE a=b AND c ORDER BY RAND() LIMIT 1000;
http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html

Цитировать
Egorsha:
Все просто - приведенный Вами код делает не то, о чем спрашивали.

а если попробовать разобраться с LIMIT?
работа в Украине

Оффлайн tigranav

  • Заглянувший
  • Новичок
  • *
  • Сообщений: 6
  • +0/-0
  • 0
    • Просмотр профиля
    • http://www.tigranav.net
Случайная картинка
« Ответ #13 : 08 Декабря 2006, 14:49:26 »
Из дискуссии я понял что лучше использовать пример html_coder-а
mysql_query(\'SELECT * FROM images LIMIT \'.$random_image.\',1\');

Оффлайн Egorsha

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 60
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Случайная картинка
« Ответ #14 : 08 Декабря 2006, 17:49:59 »
Цитировать
Yukko:
а если попробовать разобраться с LIMIT?


Выше написал -  не правильно трактовал отсутствующую "кавычку" в коде html_coder-а. Отсюда и LIMIT n вместо LIMIT n,m и все остальное вытекающее... и т.д. и т.п.

Уважаемый html_coder, если я, пребывая в невольном заблуждении, все же умудрился чем-то оскорбить Вас (а цели такой не преследовал, мотивации описал выше), то просьба извинить меня.

Теперь проведенный "эксперимент".
Код (отрицательные значения лечатся F5 - не стал обрабатывать различные секунды):

$table
="...";
$tm1=gettimeofday();
$result mysql_query(\'SELECT COUNT(*) as images_count FROM \'.$table);
$images_count = mysql_result($result, 0, 0);
$random_image = rand(0, $images_count);
mysql_query(\'SELECT * FROM \'.$table.\' LIMIT \'.$random_image.\',1\');
$tm2=gettimeofday();
$tmp1=$tm2[\'usec\']-$tm1[\'usec\'];
$tm1=gettimeofday();
mysql_query(\'SELECT * FROM \'.$table.\' ORDER BY RAND() LIMIT 1\');
$tm2=gettimeofday();
$tmp2=$tm2[\'usec\']-$tm1[\'usec\'];
echo "Записей: ".$images_count."
";
echo "Время работы: ".$tmp1." - микросекунд
";
echo "Время работы: ".$tmp2." - микросекунд
";
echo "K
	
=".($tmp2/$tmp1)."
";


Результаты: (можете сами проверить кому интересно)

При использовании ORDER BY RAND() работает в общем медленнее.
- На меленьких таблицах разница есть, но маленькая - десятки-сотни микросекунд.
- На таблице побольше уже ощутимее:

По минимуму где-то так:

Время работы: 21540 - микросекунд
Время работы: 129674 - микросекунд
Записей: 7811
K =6.02014856082

По максимуму может вылезти и намного выше. (Выпадало и К=130.)

- Если записи по объему большие (например, картинка лежит в поле таблицы), то время работы запроса увеличивается и в одном и втором случае, а коэффициент K в принципе не меняется.
 
Цитировать
tigranav:
Из дискуссии я понял что лучше использовать пример html_coder-а


Если большая база и критично время - то именно так.

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28