[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: случайная запись
nasferatu
Как лучше сделать запрос случайной записи из БД????



Спустя 9 минут, 12 секунд (18.03.2009 - 14:49) Viking написал(а):
select * from tablizza order by rand() limit 1;

Спустя 9 минут, 8 секунд (18.03.2009 - 14:58) nasferatu написал(а):
Viking, читал, что order и rand нежелательно вместе использовать. Или это не так????

Спустя 19 минут, 8 секунд (18.03.2009 - 15:18) Viking написал(а):
да, похоже оно сначала всю таблицу сортирует, а потом одну запись достает, т.е. работает медленно, должен быть нормальный способ, но сегодня я его не вижу

Спустя 7 минут, 8 секунд (18.03.2009 - 15:25) nasferatu написал(а):
может использовать два запроса??? сначала все записи, а потом брать айди из диапозона, но тогда есть вероятность ошибки, если какая-нибудь запись будет удалена

Спустя 6 минут, 41 секунда (18.03.2009 - 15:31) Viking написал(а):
видимо надо копать в сторону id=round(rand()*count(*)) но у меня сегодня как-то не копается...

Спустя 4 минуты, 2 секунды (18.03.2009 - 15:35) nasferatu написал(а):
поробуем в ту сторону покапать, может что-нибудь получится

Спустя 25 минут, 30 секунд (18.03.2009 - 16:01) sergeiss написал(а):
Я вот тут попробовал кое-что...
Таблица из 723705 записей, 204 колонки. Комп не супер-пупер скоростной (не сервер, а рабочий ноутбук), но более-менее все-таки smile.gif
БД - PostgreSQL.

Даю команду на выборку
SQL
select * from block_3120 order by random() limit 1

Время выборки - 20-22 секунды, при многократных повторных запусках

Делаю другую выборку, в 2 этапа. Сначала выбираю произвольную дату, а потом уже выбираю все данные, с произвольной выборкой по этой дате:
SQL
select *
from block_3120 where date_ = (select date_ from block_3120 order by random() limit 1 )
order by random()
limit 1

Время выборки - 2-3 секунды. Также при многократных повторах.

Вывод: раз в 7-11 быстрее получилось, на пустом месте, без особых изысков. Единственное уточнение (возможно, существенное) - по дате есть индексация.

Спустя 2 минуты, 47 секунд (18.03.2009 - 16:04) nasferatu написал(а):
sergeiss, спасибо, сейчас поробуем у себя

Спустя 9 минут, 17 секунд (18.03.2009 - 16:13) nasferatu написал(а):
В моем случае это будет так.

PHP
$result mysql_query("SELECT id_album, foto FROM foto WHERE id=(SELECT id FROM foto ORDER BY rand() LIMIT 1)");


Спустя 33 секунды (18.03.2009 - 16:13) Viking написал(а):
точно
select * from big where id>=round(rand()*(select max(id) from big)) limit 1;
работает быстро, с учетом возможных пропусков id

Спустя 10 минут, 53 секунды (18.03.2009 - 16:24) sergeiss написал(а):
Цитата (nasferatu @ 18.03.2009 - 16:13)
В моем случае это будет так.

PHP
$result = mysql_query("SELECT id_album, foto FROM foto WHERE id=(SELECT id FROM foto ORDER BY rand() LIMIT 1)");

А разница по времени какая получилась?

Спустя 3 минуты, 29 секунд (18.03.2009 - 16:28) Viking написал(а):
Цитата
В моем случае это будет так.
PHP
$result = mysql_query("SELECT id_album, foto FROM foto WHERE id=(SELECT id FROM foto ORDER BY rand() LIMIT 1)");

дык тут опять ордер с ранд

а мой пример почему-то неправильно работает...

Спустя 31 минута, 34 секунды (18.03.2009 - 16:59) Viking написал(а):
PHP
$res mysql_query("select max(id) from big");
$max rand(0,mysql_result($res,0,0));
$res mysql_query("select * from big where id>=$max limit 1");

вот это точно нормально работает

Спустя 3 минуты, 27 секунд (18.03.2009 - 17:03) nasferatu написал(а):
у меня и те работали.
а по времени выполнения он получше булет????

Спустя 10 минут, 49 секунд (18.03.2009 - 17:14) Viking написал(а):
то что два запроса это конечно хуже, но в один корректно не получается, день сегодня такой, сами запросы работают быстро, а с order by rand однозначно медледнно

Спустя 45 минут, 33 секунды (18.03.2009 - 17:59) Sylex написал(а):
у меня вот че вышло:
SQL
SELECT
*
FROM test_tab JOIN (SELECT FLOOR(RAND() * MAX(id)) AS rn from test_tab) AS tmp
WHERE id>=tmp.rn
LIMIT 1


работает

Спустя 3 минуты, 44 секунды (18.03.2009 - 18:03) Sylex написал(а):
кстати, вот наткнулся на хорошие темки smile.gif :
http://jan.kneschke.de/projects/mysql/order-by-rand
http://habrahabr.ru/blogs/mysql/54176/

Спустя 30 минут, 2 секунды (18.03.2009 - 18:33) kirik написал(а):
Если одна запись нужна, то есть хороший пример во второй ссылке, что дал Sylex:
Цитата
Для начала узнаем общее кол-во записей в таблице:

    SELECT COUNT(*) FROM tTable;

Далее просто вычислим произвольное число от 0 до кол-ва записей в этой таблице

    rand_row = round(rand() * row_count);

Теперь без проблем можно сделать выборку произвольной записи:

    SELECT * FROM tTable LIMIT rand_row, 1;


А если нужна не одна, то наверное лучше кэшировать в файл все id-шники в сериализованном массиве, потом этот массив shuffle'ить и затем делать выборку нужных айдишников.. Когда же наконец сделают нормальный order by rand.. smile.gif

Спустя 17 часов, 3 минуты, 38 секунд (19.03.2009 - 11:37) nasferatu написал(а):
мда, этот пример, наверно, пока самый удачный smile.gif

Спустя 4 часа, 14 минут, 28 секунд (19.03.2009 - 15:51) nasferatu написал(а):
протестировал
PHP
$result = mysql_query("SELECT * FROM order by rand() limit 1");


время mysql: 0.003810, всего затрачено: 0.039264

а
PHP
$result = mysql_query("SELECT * FROM foto");
$rand_row = rand(0,mysql_num_rows($result));
$result = mysql_query("SELECT * FROM foto LIMIT $rand_row,1");


время mysql: 0.004899, всего затрачено: 0.049555

значит, лучше использовать только один запрос (записей пока в таблице не много)

Спустя 24 минуты, 35 секунд (19.03.2009 - 16:16) Viking написал(а):
у меня в таблице 300 000 записей:
select * from big order by rand() limit 1; - 1 row in set (0.69 sec)
против:
select count(*) from big; - 1 row in set (0.00 sec) smile.gif (тестировал прямо в mysql, поэтому точность низкая)
select * from big limit 200000,1; - 1 row in set (0.06 sec)

Цитата
$result = mysql_query("SELECT * FROM foto");
$rand_row = rand(0,mysql_num_rows($result));
$result = mysql_query("SELECT * FROM foto LIMIT $rand_row,1");

так нет смысла делать, ты вытягиваешь ВСЕ записи в пхп и там считаешь их количество, по этмоу у тебя и время большое, лучше сразу посчитать как в примере kirikа

Спустя 1 час, 32 минуты, 18 секунд (19.03.2009 - 17:48) nasferatu написал(а):
0.03 получается
Быстрый ответ:

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