ORDER BY RAND() в MySQL

В своей работе столкнулся с выборкой случайных элементов из таблиц mysql. В этой заметке я расскажу некоторые мои соображения по этому поводу.

О чем идет речь?

Когда встает задача выбора слечайных элементов из таблиц, в первую очередь на ум приходит запрос вида:

Но давайте посмотрим, а что происходит при выполнении данного запроса?

Вот примерный ход действий:

  1. Выбираем ВСЕ строки таблицы
  2. записываем из во временныю таблицу с дополнительным полем, куда сохранаются результаты работы функции RAND()
  3. Затем все это дело сортируется по добавленному поля с использованием filesort
  4. Вабираются 10 записей из отсортированной таблицы

Все бы ничего, если бы таблица имела 10-100 строк, ну на крайний случай 1000. А представим, что в таблицу попадает больше ста тысяч строк или еще хуже пара миллионов... Правильно СЕРВЕР ЛЯЖЕТ:)

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

Вариантов реализации очень много. Например, например пожно просто сгенерироварь несколько уникальных идентификаторов и вделать выборку с конструкцией IN. Универсального решения в этом случае нет...

 

 

 

Комментарии (8)
  • Александр Пятница 16 Апрель 2010
    Это получается такая выборка SELECT A.id as board_id, A.*, B.* FROM jb_board as A, jb_board_cat as B WHERE A.id_category = B.id AND old_mess = 'old' AND checkbox_top = '1' ORDER by RAND() LIMIT $limit тоже может привести к тому, что сервак ляжет?
  • vasiatka Понедельник 19 Апрель 2010
    Вообще запросы сразу к нескольким таблицам являются очень тяжелыми. Все зависит о размеров получаемой таблицы. Оцените количество строк в запросе типа этого SELECT A.*, B.* FROM jb_board as A, jb_board_cat as B WHERE A.id_category = B.id AND old_mess = 'old' AND checkbox_top = '1' Если это количество всегда меленькое (пусть даже в пределах 1000), то я думаю сервер не упадет, а если это число много больше, то MySQl ляжет однозначно.
  • vasiatka Понедельник 19 Апрель 2010
    Представьте, сколько по времени будет выполняться файлокая сортировка таблицы скажем из 10^7.
  • vasiatka Понедельник 19 Апрель 2010
    Лучше придумать какой либо алгоритм для выбора случайных записей. Универсального решения тут нет, нужно смотреть в каждом конкретном случае.
  • Сергей Вторник 17 Август 2010
    А если вместо RAND() указано конкретное поле, а записей и в самом деле миллион-два, запрос также положит MySQL? А что если дополнительно стоит условие в WHERE, которое отбирает сотню-другую по индексированному полю?
  • vasiatka Четверг 19 Август 2010
    В первом случае такие запросы должны работать нормально, а для правильности по указанному полю надо создать индекс. Вообще если в запрос делает выборку по индексированному полю, то запросы должны работать очень быстро.Но конечно, каждый конкретный случай надо смотреть отдельно, чтобы понять что делает мускул.
  • Сергей Пятница 20 Август 2010
    Проверил, запрос типа SELECT ... FROM ... WHERE indexed_field = const ORDER BY RAND() из почти миллиона записей вначале выбирает поля соответствующие условию отбора, и если их в пределах сотни (мой случай), запрос отрабатывает очень быстро.
  • vasiatka Вторник 31 Август 2010
    "...и если их в пределах сотни (мой случай)..." - в этом есть ключ к пониманию. Временная таблица создается и сортируется лишь для этой сотни записей. А если эта сотня "подрастет", то ситуация коренным образом измениться.
Добавить комментарий
Вам необходимо включить показ изображений в браузере для того чтобы увидеть код

Дайте нам знать, что вы - живой человек. Для нас это важно!
Кликните, если плохо видно

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

Рейтинг@Mail.ru