Когда MySQL ORDER BY RAND () выполняет порядок? - PullRequest
2 голосов
/ 02 августа 2011

Я читал об ORDER BY RAND () и его проблемах с производительностью - относятся ли они только к запросам, которые возвращают большие наборы данных?Например, если у меня есть таблица с 100 000 строк и я возвращаю набор данных с 10 записями, используя предложение WHERE, а затем использую ORDER BY RAND () LIMIT 1, будет ли применен этот ORDER BY RAND () ПОСЛЕ того, как моя таблица будет отфильтрованазаписи, соответствующие предложению WHERE и, следовательно, имеющие незначительные проблемы с производительностью?

Ответы [ 4 ]

8 голосов
/ 03 августа 2011

Вы правы, он будет применять ORDER BY после уменьшения количества строк с WHERE, GROUP BY и HAVING.Но он будет применять ORDER BY до LIMIT.

Так что, если вы отфильтруете количество строк в достаточной степени, тогда да, ORDER BY RAND () может достичь желаемого результата без существенного снижения производительности.Есть законное преимущество в простом и легко читаемом коде.

Проблема возникает, когда вы думаете , что ваш запрос должен уменьшать строки до чего-то небольшого, но со временем ваши данные растут,количество строк, которое нужно отсортировать, снова становится большим.Поскольку ваш запрос выполняет LIMIT 10 для отсортированного результата, он скрывает тот факт, что вы выполняете ORDER BY RAND () для строк по 500 тыс.Вы просто видите, как производительность таинственным образом ухудшается.

Я написал об альтернативных методах выбора случайной строки в моей книге Антипаттерны SQL: предотвращение ловушек программирования баз данных или в других ответах здесь, наПереполнение стека:

2 голосов
/ 03 августа 2011

Неважно, сколько строк вы выберете. Если вы ORDER BY RAND(), случайное число вычисляется для каждой строки в таблице. Это потому, что он должен вычислить случайное значение для каждой строки, чтобы узнать, какая строка сгенерировала наибольшее значение. Поэтому, если у вас есть таблица с 100 000 строк, а затем вызовите ORDER BY RAND() LIMIT 1 Вы говорите MySQL сгенерировать случайное число для 100 000 строк, отсортируйте их по этому номеру и затем получите первую.

Это намного быстрее:

  1. ВЫБРАТЬ СЧЕТ (*) ОТ Table

  2. Генерация случайного числа между 0 и результатом вышеупомянутого запроса минус 1 на вашем языке сценариев / программирования.

  3. SELECT * FROM Table LIMIT random_number_here, 1

1 голос
/ 10 августа 2011

Основываясь на быстром тестировании, я должен сделать вывод, что ORDER BY RAND () применяется только после применяется оператор WHERE, а не ко всему набору данных.

Результаты из таблицы с 50000 строк:

SELECT * FROM `mytable` LIMIT 1  (1 total, Query took 0.0007 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' LIMIT 1 (1 total, Query took 0.0010 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' (142 total, Query took 0.0201 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' ORDER BY RAND() LIMIT 1 (1 total, Query took 0.0229 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' ORDER BY RAND() (142 total, Query took 0.0236 sec)
SELECT * FROM `mytable` ORDER BY RAND() LIMIT 1 (1 total, Query took 0.4224 sec)
0 голосов
/ 02 августа 2011

Значение RAND() будет рассчитываться для каждой строки, поэтому оно не очень эффективно для больших наборов данных, предложение LIMIT не меняет этого.Обычный способ обойти это - заранее вычислить случайное число, а затем извлечь соответствующую ему строку на основе предварительно сгенерированного индексированного столбца.

Вот одно подробное объяснение:

http://jan.kneschke.de/projects/mysql/order-by-rand/

...