Как стать автором
Обновить

Комментарии 18

Таблица уже имеет тип InnoDB.
А можно реальный пример, когда действительно требуется выборка случайных строк?
Мне, кроме сбора статистики по большой таблице в ограниченное время, ничего в голову не приходит.
во всех примерах которые попадались — что-то типа «показать пользователю в сайдбаре три рандомных товара»…
не проще ли срандомить айди товара из заданных пределов и выбрать 3 товара?
Не известно заранее, в каких пределах будут id товара, у которых category_id=5.
В общем случае они будут идти не по порядку (например 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, но это уже намного сложнее и медленнее
Я и не говорил что это будет работать в данном конкретном случае. Кстати, для случаев типа вашего можно подумать над кешированием, например, тысячи (число от фонаря) готовых отрендереных блоков и вставки рандомного из них. Да, это не чистый рандом, но работать будет еще быстрее (не надо каждый раз рендерить сам блок).
Дык у автора спросите. Я просто человеку на вопрос «зачем» ответил.
Вообще я таким не занимаюсь — у нас проблеммные таблички от 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-оформление не отображается…
Поясните пожалуйста
>выбрать случайные id из промежутка в данном случае нельзя: из-за условия WHERE, id идут уже не по порядку и разряженно.

и
> WHERE oc1.id=(rs.id+564756)

как бы говорит о том, что вы можете попасть в id которого не существует и выборка выдаст null
или я чего-то не понял?

Спасибо за замечание.

Действительно, в таблице random_seed должно быть столько же значений, сколько в таблице, из которой нужно брать случайные строки + N записей, где N это максимально возможное значение random_from_php
Еще, скорость зависит не столько от общего кол-ва записей в таблице, а от количества записей после применения условий where (возможно, только если индекс по where-полям есть). У меня на myisam в 11kk записей так.
К сожалению, когда писал статью не видел подобных решений в интернете. Можете скинуть ссылку?
Даже на stackoverflow предлагают селектить rand()*MAX(id)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации