Отправить заявку

MySQL - выбор случайных строк. Оптимизация запроса.

Для получения нескольких случайных записей из таблицы 98% программистов всегда используют всем известную конструкцию ORDER BY RAND() LIMIT xx. Для тех кто не знает как работает данная команда (которая гробит производительность) - запрос копирует выборку во временную таблицу и добавляет поле со случайным значением и после этого начинает выбирать по этому "новому" полю случайные строки. Если таблица содержит много строк - производительность просто упадет в самый низ!

Это похоже на цикл, для каждой записи мы имеем 2 переменные @count и @limit. @count уменьшается на 1 для каждой просматриваемой строки, @limit уменьшается для каждой выбранной строки:

SELECT test_value
FROM (
    SELECT @count := COUNT(*) + 1, @limit := 5
    FROM test_rand
) AS vars
STRAIGHT_JOIN (
    SELECT r.*, @limit := @limit - 1
    FROM test_rand AS r
    WHERE
        (@count := @count - 1)
        AND RAND() < @limit / @count
) AS i

Стоит отметить, что в InnoDB таблицах такой разницы можно не заметить, так как COUNT() работает намного быстрее в MyISAM.
Такой вариант лучше использовать для таблиц с большим количеством данных, так как он основан на вероятностном подходе. Как всегда решать вам. Если в таблице 10 строк и вам нужно выбрать 1 случайную, то с этим отлично справится ORDER BY RAND(). Если в таблице несколько миллионов записей, тогда уже стоит подумать.

Другие публикации