[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Выборка случайных записей
two
В google'e много вариантов. Какой найменее ресурсоёмкий и найболее быстрый ?

$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 сек

Спустя 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

Спустя 18 минут, 28 секунд (15.02.2011 - 17:52) two написал(а):
Подведу итоги самостоятельно:

Вариант с 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. Важно быстренько выдать ему результат и заняться следующим, чтобы очередь не копилась.

По этому под большими нагрузками последний вариант смотрится симпотичнее. Только нижний предел стоит искать тогда, когда таблица сильно модифицируется. А если не сильно, можно и ноль поставить:

$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`");
$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);
заключается в том, что значения в поле `id` не всегда распределено равномерно и без "дырок". При удалении записей "дырки" будут появляться, а значит есть вероятность попасть в них.

Спустя 45 минут, 32 секунды (18.02.2011 - 10:52) twin написал(а):
Цитата
При удалении записей "дырки" будут появляться, а значит есть вероятность попасть в них.
ВнимательнЕЕ смотри:
".... WHERE `id` >= $random LIMIT 0,1 ");

Спустя 28 минут, 8 секунд (18.02.2011 - 11:20) Michael написал(а):
На таком хорошем примере объясню(может кому интересно :) ) принцип использования индуктивных размышлений в программировании.
Идем от частного случая к общему:
имеем таблицу:
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
Всё равно дыры присутствуют =(
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.