Комментарии 18
Насколько знаю медленный результат был из-за того что использовалась MyISAM, если перейти на InnoDB то все будет ок без танцев с бубном.
explainextended.com/2009/03/01/selecting-random-rows/
explainextended.com/2009/03/01/selecting-random-rows/
А можно реальный пример, когда действительно требуется выборка случайных строк?
Мне, кроме сбора статистики по большой таблице в ограниченное время, ничего в голову не приходит.
Мне, кроме сбора статистики по большой таблице в ограниченное время, ничего в голову не приходит.
во всех примерах которые попадались — что-то типа «показать пользователю в сайдбаре три рандомных товара»…
не проще ли срандомить айди товара из заданных пределов и выбрать 3 товара?
Не известно заранее, в каких пределах будут id товара, у которых category_id=5.
В общем случае они будут идти не по порядку (например 1, 2, 3, 555, 123444), а итеративно выбирать значения до тех пор, пока не получим нужные нам значения — медленно
В общем случае они будут идти не по порядку (например 1, 2, 3, 555, 123444), а итеративно выбирать значения до тех пор, пока не получим нужные нам значения — медленно
Ну вообще-то идея имеет право на жизнь… «where id>=random_from_php limit 1», повторить три раза с разными значениями random_from_php
такой подход не будет работать, если id распределены следующим образом:
1, 2, 3, 4, 555, 556, 557, три случайных random_from_php попадут между двумя неразрывными последовательностями и получим в итоге 555, 555, 555, конечно, можно вводить дополнительные условия (не выбирать уже выбранные), как-то анализировать распределение id, но это уже намного сложнее и медленнее
1, 2, 3, 4, 555, 556, 557, три случайных random_from_php попадут между двумя неразрывными последовательностями и получим в итоге 555, 555, 555, конечно, можно вводить дополнительные условия (не выбирать уже выбранные), как-то анализировать распределение id, но это уже намного сложнее и медленнее
Я и не говорил что это будет работать в данном конкретном случае. Кстати, для случаев типа вашего можно подумать над кешированием, например, тысячи (число от фонаря) готовых отрендереных блоков и вставки рандомного из них. Да, это не чистый рандом, но работать будет еще быстрее (не надо каждый раз рендерить сам блок).
Дык у автора спросите. Я просто человеку на вопрос «зачем» ответил.
Вообще я таким не занимаюсь — у нас проблеммные таблички от 100млн, и там не до order by rand() ;)
Вообще я таким не занимаюсь — у нас проблеммные таблички от 100млн, и там не до order by rand() ;)
Реальный пример из моей работы — выбор случайных категорий товаров из разных комбинаций (всего 4000000 записей):
«Обычный»: запрос
SELECT
osc1.*
FROM
object_category osc1
WHERE region_id=6
ORDER BY RAND()
LIMIT 10
Время выполнения: 1.726с; 1.851с; 1.803с; 1.784с
«Ускоренный» запрос:
SELECT
osc1.*
FROM
object_category osc1, random_seed rs
WHERE
osc1.id=(rs.id+564756) AND region_id=6
ORDER BY
rs.random_seed
LIMIT 10
Время выполнения: 0.007с; 0.010с; 0.006с; 0.008с
К сожалению, html-оформление не отображается…
«Обычный»: запрос
SELECT
osc1.*
FROM
object_category osc1
WHERE region_id=6
ORDER BY RAND()
LIMIT 10
Время выполнения: 1.726с; 1.851с; 1.803с; 1.784с
«Ускоренный» запрос:
SELECT
osc1.*
FROM
object_category osc1, random_seed rs
WHERE
osc1.id=(rs.id+564756) AND region_id=6
ORDER BY
rs.random_seed
LIMIT 10
Время выполнения: 0.007с; 0.010с; 0.006с; 0.008с
К сожалению, html-оформление не отображается…
Всему свое место и время. Я бы рекомендовал, при всей своей любви к RDBMS, глянуть на redis.io/commands/srandmember
Поясните пожалуйста
>выбрать случайные id из промежутка в данном случае нельзя: из-за условия WHERE, id идут уже не по порядку и разряженно.
и
> WHERE oc1.id=(rs.id+564756)
как бы говорит о том, что вы можете попасть в id которого не существует и выборка выдаст null
или я чего-то не понял?
>выбрать случайные id из промежутка в данном случае нельзя: из-за условия WHERE, id идут уже не по порядку и разряженно.
и
> WHERE oc1.id=(rs.id+564756)
как бы говорит о том, что вы можете попасть в id которого не существует и выборка выдаст null
или я чего-то не понял?
Спасибо за замечание.
Действительно, в таблице random_seed должно быть столько же значений, сколько в таблице, из которой нужно брать случайные строки + N записей, где N это максимально возможное значение random_from_php
Действительно, в таблице random_seed должно быть столько же значений, сколько в таблице, из которой нужно брать случайные строки + N записей, где N это максимально возможное значение random_from_php
Решение не ново. Кстати, подобным образом в NoSQL еще записи случайные выбирают.
К сожалению, когда писал статью не видел подобных решений в интернете. Можете скинуть ссылку?
Даже на stackoverflow предлагают селектить rand()*MAX(id)
Даже на stackoverflow предлагают селектить rand()*MAX(id)
Вот тут один товарищ расписывал различные варианты jan.kneschke.de/projects/mysql/order-by-rand/
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Быстрый выбор случайных значений из больших таблиц MySQL по условию