2015-08-07 2 views
3

Я хочу выбрать случайную запись из большой таблицы. После поиска нашли наконец два решения;выберите случайную запись из таблицы, почему сначала медленно, чем секунда?

: с

select id from `table` where id = (floor(1 + rand() * 2880000)); 

б:

select id from `table` where id >= (floor(1 + rand() * 2880000)) limit 1; 

Но первое (а) решение далеко медленнее, чем вторых (б), примерно в 40 раз медленнее.

После выполнения много раз, я нахожу более странную проблему. Первое решение может вернуть две записи.

select id from `table` where id = (floor(1 + rand() * 2880000)); 
+---------+ 
| id  | 
+---------+ 
| 2484024 | 
| 1425029 | 
+---------+ 
2 rows in set (1.06 sec) 

Мой вопрос:

  • Почему первое решение медленнее, чем второе решение?
  • Почему первое решение возвратило две записи?

Моя версия MySQL:

mysql> show variables like "%version%"; 
+-------------------------+-------------------------+ 
| Variable_name   | Value     | 
+-------------------------+-------------------------+ 
| innodb_version   | 5.5.43     | 
| protocol_version  | 10      | 
| slave_type_conversions |       | 
| version     | 5.5.43-0ubuntu0.12.04.1 | 
| version_comment   | (Ubuntu)    | 
| version_compile_machine | x86_64     | 
| version_compile_os  | debian-linux-gnu  | 
+-------------------------+-------------------------+ 
7 rows in set (0.04 sec) 

Спасибо за любую помощь.

ответ

1

Ответы на оба ваши вопросы:

  1. Первое решение медленнее, чем второй, потому что в первом растворе новое случайное значение вычисляется для каждой записи, в то время как во втором растворе он рассчитан только для записи, необходимые для поиска одного матча. Отметим также, что условие для второго решения гораздо менее строгое.
  2. В первом решении вы можете иметь несколько возвращаемых значений, потому что для каждой записи вычисляется новое случайное значение, и у вас нет оператора предельных значений. По той же логике вы также можете получить 0 результатов.

Посмотрите на this answer для лучшего решения.

0


SELECT 
    a.id 
FROM 
    tableA a 
     INNER JOIN 
    (SELECT 
     (ROUND((RAND() * (MAX(id) - MIN(id))) + MIN(id)) - 1) r 
    FROM 
     tableA) x 
WHERE 
    a.id > x.r 
LIMIT 1; 


 
Смежные вопросы