Как я выбираю случайную запись эффективно в MySQL?

mysql> EXPLAIN SELECT * FROM urls ORDER BY RAND() LIMIT 1;
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                           |
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
|  1 | SIMPLE      | urls  | ALL  | NULL          | NULL | NULL    | NULL | 62228 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+-------+---------------------------------+

Вышеупомянутое не квалифицирует как эффективное, как я должен сделать это правильно?

ОБНОВЛЕНИЕ

Кажется, что использование решения, упомянутого в ответе все еще, не помогает:

mysql> explain SELECT  *
    -> FROM    (
    ->         SELECT  @cnt := COUNT(*) + 1,
    ->                 @lim := 10
    ->         FROM    urls
    ->         ) vars
    -> STRAIGHT_JOIN
    ->         (
    ->         SELECT  r.*,
    ->                 @lim := @lim - 1
    ->         FROM    urls r
    ->         WHERE   (@cnt := @cnt - 1)
    ->                 AND RAND(20090301) < @lim / @cnt
    ->         ) i;
+----+-------------+------------+--------+---------------+------+---------+------+-------+------------------------------+
| id | select_type | table      | type   | possible_keys | key  | key_len | ref  | rows  | Extra                        |
+----+-------------+------------+--------+---------------+------+---------+------+-------+------------------------------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL | NULL    | NULL |     1 |                              |
|  1 | PRIMARY     | <derived3> | ALL    | NULL          | NULL | NULL    | NULL |    10 |                              |
|  3 | DERIVED     | r          | ALL    | NULL          | NULL | NULL    | NULL | 62228 | Using where                  |
|  2 | DERIVED     | NULL       | NULL   | NULL          | NULL | NULL    | NULL |  NULL | Select tables optimized away |
+----+-------------+------------+--------+---------------+------+---------+------+-------+------------------------------+
5
задан user198729 25 April 2010 в 09:24
поделиться

2 ответа

Квассной написал сообщение о случайном выборе строк без выполнения сортировки. Его пример выбирает 10 строк случайным образом, но вы можете адаптировать его для выбора только одной строки.

Если вы хотите, чтобы это было действительно быстро, вы можете использовать приближение, которое не будет полностью однородным или иногда не вернет строку.

Вы также можете использовать хранимую процедуру для быстрого выбора случайной строки из сообщения Билла Карвина :

SET @r := (SELECT ROUND(RAND() * (SELECT COUNT(*) FROM mytable)));
SET @sql := CONCAT('SELECT * FROM mytable LIMIT ', @r, ', 1');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

Обратите внимание, что это будет работать намного быстрее в MyISAM, чем в InnoDB, потому что COUNT (*) дорого в InnoDB но почти мгновенно в MyISAM.

4
ответ дан 15 December 2019 в 00:54
поделиться

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

0
ответ дан 15 December 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: