$res = mysql_query("SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table`");
$row = mysql_fetch_object($res);
$offset = $row->offset;
$res = mysql_query("SELECT * FROM `table` LIMIT $offset, 1");
$us = mysql_fetch_assoc($res);
По моему мнению этот запрос довольно быстрый. Но насколько он оптимальный не знаю.
Спасибо за помощь
Спустя 7 минут, 59 секунд (15.02.2011 - 17:05) Michael написал(а):
Это у тебя не один, а два запроса. Глядится неплохо. А по скорости - можешь сам замерить. Только на более менее больших данных. Сравни например с таким:
$res = mysql_query("SELECT * FROM `table` ORDER BY RAND() LIMIT 1");
Спустя 13 минут, 53 секунды (15.02.2011 - 17:19) two написал(а):
Michael
Твой вариант медленнее.
Твой вариант медленнее.
Спустя 5 минут, 42 секунды (15.02.2011 - 17:24) Michael написал(а):
Цитата (two) |
Michael Твой вариант медленнее. |
Это не мой вариант, а стандартный из хелпа. О его тормознутости знаю.
а подробности можно? На скольких строках, время в миллисек.
Спустя 7 минут (15.02.2011 - 17:31) Snus написал(а):
Michael
Да, two дело говорит. Действительно быстрее. На себе попробовал. Таблица ~2млн, по твоему запросу - 23.1759 сек. А метод two 0.8858 сек
Да, two дело говорит. Действительно быстрее. На себе попробовал. Таблица ~2млн, по твоему запросу - 23.1759 сек. А метод two 0.8858 сек
Спустя 2 минуты, 29 секунд (15.02.2011 - 17:34) two написал(а):
Michael
Ну смотри:
1'000
0.00505518913
0.00125408173
10'000
0.0912001133
0.00746798515
100'000
0.61438584328
0.0475871563
500'000
21.3207550049
1.58239793777
1'000'000
72.680314064
1.64496612549
Ну смотри:
1'000
0.00505518913
0.00125408173
10'000
0.0912001133
0.00746798515
100'000
0.61438584328
0.0475871563
500'000
21.3207550049
1.58239793777
1'000'000
72.680314064
1.64496612549
Спустя 18 минут, 28 секунд (15.02.2011 - 17:52) two написал(а):
Подведу итоги самостоятельно:
Вариант с RAND() можно использовать в таблице до 100 записей. В ином случае намного быстрее будет мой вариант.
Нашел еще один сбособ:
Он быстрее моего, хотя при сравнении их пишут, что он медленнее. Проверьте кто-нибудь скорость :)
Вариант с RAND() можно использовать в таблице до 100 записей. В ином случае намного быстрее будет мой вариант.
Нашел еще один сбособ:
$range_result = mysql_query("SELECT MAX(`id`) AS max_id , MIN(`id`) AS min_id FROM `table`");
$range_row = mysql_fetch_object($range_result);
$random = mt_rand($range_row->min_id, $range_row->max_id);
$result = mysql_query("SELECT * FROM `table` WHERE `id` >= $random LIMIT 0,1 ");
$us = mysql_fetch_assoc($result);
Он быстрее моего, хотя при сравнении их пишут, что он медленнее. Проверьте кто-нибудь скорость :)
Спустя 2 дня, 15 часов, 8 минут, 59 секунд (18.02.2011 - 09:01) twin написал(а):
Если ты серьёзно этим озабочен, значит ожидаешь большую посещаемость, правильно? Так вот. При больших нагрузках не столь важна скорость выполнения скрипта, сколько скорость выполнения отдельных запросов. Тоесть мерять нужно их.
Поясню. Допустим мы проектируем макдональдс. И ожидаем большой наплыв посетителей. Для этого у нас есть помещение (PHP) и несколько точек раздачи (MySql). Не совсем правильно расчитывать пропускную способность, меряя скорость употребления пирожка каждым посетителем. Гораздо важнее знать расторопность продовца и количество покуаемых гамбургеров. Если продавцы справляются с потоком посетителей, то все хорошо. Выдали побыстрому ему бомж-ланч, и пусть себе мирно кушает в уголочке хоть полчаса. Места много. А если продавец будет по часу возится с каждым, то на выдаче будет очередь, а помещение будет простаивать.
Так и тут. Не так важно, сколько времени молотит процесс php. Важно быстренько выдать ему результат и заняться следующим, чтобы очередь не копилась.
По этому под большими нагрузками последний вариант смотрится симпотичнее. Только нижний предел стоит искать тогда, когда таблица сильно модифицируется. А если не сильно, можно и ноль поставить:
Поясню. Допустим мы проектируем макдональдс. И ожидаем большой наплыв посетителей. Для этого у нас есть помещение (PHP) и несколько точек раздачи (MySql). Не совсем правильно расчитывать пропускную способность, меряя скорость употребления пирожка каждым посетителем. Гораздо важнее знать расторопность продовца и количество покуаемых гамбургеров. Если продавцы справляются с потоком посетителей, то все хорошо. Выдали побыстрому ему бомж-ланч, и пусть себе мирно кушает в уголочке хоть полчаса. Места много. А если продавец будет по часу возится с каждым, то на выдаче будет очередь, а помещение будет простаивать.
Так и тут. Не так важно, сколько времени молотит процесс php. Важно быстренько выдать ему результат и заняться следующим, чтобы очередь не копилась.
По этому под большими нагрузками последний вариант смотрится симпотичнее. Только нижний предел стоит искать тогда, когда таблица сильно модифицируется. А если не сильно, можно и ноль поставить:
$range_result = mysql_query("SELECT MAX(`id`) AS max_id FROM `table`");
$range_row = mysql_fetch_object($range_result);
$random = mt_rand(0, $range_row->max_id);
$result = mysql_query("SELECT * FROM `table` WHERE `id` >= $random LIMIT 0,1 ");
$us = mysql_fetch_assoc($result);
Спустя 1 час, 5 минут, 24 секунды (18.02.2011 - 10:07) linker написал(а):
Минус этого метода
$range_result = mysql_query("SELECT MAX(`id`) AS max_id FROM `table`");заключается в том, что значения в поле `id` не всегда распределено равномерно и без "дырок". При удалении записей "дырки" будут появляться, а значит есть вероятность попасть в них.
$range_row = mysql_fetch_object($range_result);
$random = mt_rand(0, $range_row->max_id);
$result = mysql_query("SELECT * FROM `table` WHERE `id` >= $random LIMIT 0,1 ");
$us = mysql_fetch_assoc($result);
Спустя 45 минут, 32 секунды (18.02.2011 - 10:52) twin написал(а):
Цитата |
При удалении записей "дырки" будут появляться, а значит есть вероятность попасть в них. |
ВнимательнЕЕ смотри:
".... WHERE `id` >= $random LIMIT 0,1 ");
Спустя 28 минут, 8 секунд (18.02.2011 - 11:20) Michael написал(а):
На таком хорошем примере объясню(может кому интересно :) ) принцип использования индуктивных размышлений в программировании.
Идем от частного случая к общему:
имеем таблицу:
значения в таблице притянуты за уши, но это как раз выражение возможного частного. На граничных, "странных" вариантах проверять начинаем.
Анализируем как на этой таблице будет работать вариант с MAX(id)
Случайное число $random будет постоянно бить между 3 до 1000, это очевидно.
Значит под `id` >= $random будет выдавать постоянно id==1000, что не верно, т.к. все 4 записи должны быть равнозначны.
Т.е. в этом частном случае алгоритм не верен.
А значит и в общем (для любой возможной таблицы) - тоже.
Идем от частного случая к общему:
имеем таблицу:
id
1
2
3
1000
значения в таблице притянуты за уши, но это как раз выражение возможного частного. На граничных, "странных" вариантах проверять начинаем.
Анализируем как на этой таблице будет работать вариант с MAX(id)
Случайное число $random будет постоянно бить между 3 до 1000, это очевидно.
Значит под `id` >= $random будет выдавать постоянно id==1000, что не верно, т.к. все 4 записи должны быть равнозначны.
Т.е. в этом частном случае алгоритм не верен.
А значит и в общем (для любой возможной таблицы) - тоже.
Спустя 12 минут, 57 секунд (18.02.2011 - 11:33) twin написал(а):
Ну вот почему я и написал про нижний предел.
Цитата |
нижний предел стоит искать тогда, когда таблица сильно модифицируется. |
Только я имел ввиду перекос в нижню сторону. Если таблица часто модифицируется минимальный id постоянно увеличивается, то с нулем в нижнем пределе чаще всего будeт выпадать строчка с минимальным id.
Спустя 1 час, 7 минут, 34 секунды (18.02.2011 - 12:41) linker написал(а):
twin
Да-да, теперь заметил.
Да-да, теперь заметил.
Спустя 2 дня, 4 часа, 37 минут, 40 секунд (20.02.2011 - 17:18) two написал(а):
twin
Всё равно дыры присутствуют =(
Всё равно дыры присутствуют =(