[MySQL] выбор случайных записей

1 234
[Удален]
#21

30.000 записей? Да это детская таблица совсем. Вы про нее сказали, что она огромная? :)

rtyug
На сайте с 13.05.2009
Offline
263
#22
So1:
30.000 записей? Да это детская таблица совсем. Вы про нее сказали, что она огромная? :)

на том сервере было выделено 1М оперативки в my.cnf из 256 рекоммендованого для минимума :)

и под ключи 1М

и на серваке еще работало 10 сайтов :)

как только написать не правильный запрос или сделать ошибку в сложном запросе, то CPU сервера сразу под 100% :)

====

я стараюсь писать все время правильно, чтобы потом 1000 раз не переделывать одно и тоже самое, или я не прав?

Спалил тему: Pokerstars вывод WMZ, etc на VISA 0% или SWIFT + Конверт USD/GBP,etc (net profit $0,5 млрд) (https://minfin.com.ua/blogs/94589307/115366/) Monobank - 50₴ на счет при рег. тут (https://clck.ru/DLX4r) | Номер SIP АТС Москва 7(495) - 0Ꝑ, 8(800) - 800Ꝑ/0Ꝑ (http://goo.gl/XOrCSn)
[Удален]
#23

прав, но не прав. Все обычно дотачивается под систему, поэтому нужно писать и правильно и гибко, чтобы потом можно было переделать немного.

По теме: не существует нормальных способов ORDER BY RAND().

можно сделать вот так:

alter table `your_table` add column order1 tinyint(4) unsigned;
alter table `your_table` add index `order_index` (`order1`) using btree;

далее каждой строке назначаем новое рандомное значение

update `your_table` set order1 = round(rand()*100)

выборка

select * from `your_table` order by order1

будет быстрее работать. Разница в том, что тут сортировка идет по индексированному полю и при большом количестве записей такая выборка с сортировкой будет работать в разы быстрее.

можно вот это

update `your_table` set order1 = round(rand()*100)

по крону запустить и не делать update в скрипте, если вам не важно получать каждый раз новые данные.

ENGINE тут нужно InnoDB делать, а не MyISAM если будете делать сначала update, потому что он заблокирует в случае MyISAM таблицу на чтение целиком.

T
На сайте с 13.01.2009
Offline
50
#24
rtyug:
я только что попробовал на таблице в 30 000 значений, запрос - выполнялся около 0.1 - 0.09 что есть не красиво...?? (правда потом через раз по разному)

За 0.1 вся ваша система вылазить не должна. а не 1 запрос

M
На сайте с 20.08.2004
Offline
376
#25
So1:
update `your_table` set order1 = round(rand()*100)

тоже думал о таком, но идея мне не понравилась.

1. немного не рандомные уже значения будут,

а в случае с * 100 всего 100 вариантов.

Представьте что у вас база из 100 000 записей, а рандомных наборов у вас будет ВСЕГО 100.

может я правда чего то вашей теме не допонял.

отец сыночка, лапочки дочки и еще одного сыночка
S
На сайте с 27.03.2009
Offline
29
#26

Как вариант можно поробовать так:

1. Генерим одно случайное число (r)

2. Во внутреннем подзапросе выбираем 10 записей начиная с позиции r

3. Во внешнем подзапросе ставим рандомную сортировку

Плюсы: Нет доп полей и тяжелая рандомная сортировка работает только с 10 записями, это быстро.

Минусы: Псевдослучайность.

[Удален]
#27
Miracle:
тоже думал о таком, но идея мне не понравилась.
1. немного не рандомные уже значения будут,
а в случае с * 100 всего 100 вариантов.
Представьте что у вас база из 100 000 записей, а рандомных наборов у вас будет ВСЕГО 100.
может я правда чего то вашей теме не допонял.

Ну сделайте умножение на миллион (правда тут MySQL-ю прийдется построить BTREE побольше, но это все равно пустяк). tinyint на что-нибудь побольше поменяйте. Рандомных значений будет столько, сколько нужно и в случае умножения на 100 - проведите эксперимент и посмотрите на результаты. Даже на базе с миллионом записей. Напишите скриптик, который будет загонять вмассив полученные значения, прогоните по циклу, а дальше по всем получившимся массивам сделайте diff. Так или иначе моим способом можно добиться получения выборки рандомных записей относительно "малой кровью".

DeveloperRu
На сайте с 27.02.2009
Offline
72
#28

можно попробовать такой вариант

SELECT FLOOR(RAND() * COUNT(*)) AS rand_row FROM foo;

SELECT * FROM foo LIMIT $rand_row, 1;

DeveloperRu добавил 02.08.2010 в 06:56

или

SELECT * FROM my_table

WHERE pk_column >=

(SELECT FLOOR( MAX(pk_column) * RAND()) FROM my_table)

ORDER BY pk_column

LIMIT 1;

Ответы на вопросы (http://telenok.com)
edogs software
На сайте с 15.12.2005
Offline
775
#29

Из вроде не упоминавшихся, но вполне кошерных вариантов на практике вполне годных (вместо извращений с хитрыми выборками, индексами строящимися по 2 часа и т.д.).

Отдельная таблица с ID, состоящая только из них. Будет сравнительно шустро. Основной бонус - не мучать основную таблицу индексами и выборками по ней. Побочный бонус - это будет маленькая таблица. Для полного кайфа в таблице можно создать поле с последовательными ИД и выбирать по ним.

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

Следующий возможный этап это не уникальность рандома. Во многих случаях она не нужна. Тогда после генерации случайных наборов, достаточно не удалять их сразу после использования. Если речь идет про сайт с реальными пользователями, то вероятность повторения набора для отдельно взятого юзера достаточно мала и даже если она случится - ничего вроде как страшного. А в свободное время можно перегенерить наборы сгенеренных рандомов.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
[Удален]
#30

edogs, что стоит MySQL-ю построить бинарное дерево по одному полю? (это про индексы, которые строятся по 2 часа). Вот индексы, состоящие из нескольких полей в принципе могут строиться достаточно долго особенно если есть не integer поля (varchar, например).

Отдельная таблица с ID не учитывает параметры запроса

Отдельный скрипт, который строит доп таблицу по крону не гарантирует актуальность данных.

SELECT FLOOR(RAND() * COUNT(*)) AS rand_row FROM foo;
SELECT * FROM foo LIMIT $rand_row, 1;

тут мывыбираем одну запись, а нам чаще всего нужно много. LIMIT $row_count, 10 даст 10 последовательных, но не рандомных записей.

SELECT * FROM my_table
WHERE pk_column >=
(SELECT FLOOR( MAX(pk_column) * RAND()) FROM my_table)
ORDER BY pk_column
LIMIT 1;

то же самое только тут даже ORDER лишний, т.к. нечего сортировать, если в выборке одна запись.

Как я и сказал, не существует нормальных быстрых способов ORDER BY RAND()

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

1 234

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий