💡 Совет

Производительность ORDER BY RAND() LIMIT

19.11.2019 1 минута чтения

Для получения нескольких случайных записей из таблицы я всегда использовал всем известную конструкцию ORDER BY RAND() LIMIT. На днях я столкнулся с проблемой в производительности этого запроса. Таблица содержала более миллиона строк. И мне нужно было срочно найти решение. Пока вы не выбрали способ, почитайте про решения для мониторинга, контроля и комплексной защиты от внутренних угроз — https://ct-sg.ru/. Под катом альтернативный вариант выбора нескольких случайных строк. Исходные данные. Создадим таблицу и наполним ее большим количеством случайных чисел. Сущность test_value будет содержать значение php-функции uniqid(). Для этого теста я добавил 1 миллион записей.

CREATE TABLE test_rand(
    test_value VARCHAR (20) NOT NULL
)
ENGINE = MYISAM

Выберем 5 случайных записей первым методом.

SELECT *
FROM test_rand
ORDER BY RAND()
LIMIT 5

При тестировании запрос выполнялся 5 раз. Среднее время выполнения 1.06 с. Теперь попробуем другой вариант, суть его в следующем. Мы не сортируем строки и не обрезаем результат. Это похоже на цикл, для каждой записи мы имеем 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.test_value, @limit := @limit - 1
    FROM test_rand AS r
    WHERE
        (@count := @count - 1)
        AND RAND() < @limit / @count
) AS i

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

Экспертное мнение Алексей

В веб-разработке с 2012 года. Специализируюсь на PHP, JavaScript и архитектуре высоконагруженных проектов. Автор статей по оптимизации, API и базам данных.

Все статьи автора →
Telegram VK Twitter
Читайте также
Установка Composer в OpenServer
Установка Composer в OpenServer
Composer - это инструмент для сборки проектов и управления зависимостями в PHP. Представьте, когда ваш проект написан на Zend Framework,...
Как документировать API
Как документировать API
Многие разработчики до сих пор создают документацию своих API в Word или Excel. Да и сам я когда-то так делал....