Оптимизируйте MySQL ORDER BY RAND () для отфильтрованного запроса GROUP BY, чтобы избежать временного / индексного соединения - PullRequest
1 голос
/ 24 сентября 2011

Счетчик «соединения без индекса» MySQL увеличивается, как показано в различных инструментах анализа, таких как mysql-tuner.pl и т. Д., Отслеживая запрос, который выбирает случайный продукт с помощью RAND (), я хотел бы оптимизировать, чтобы избежать это приращение.

Запрос выглядит так:

select p.*, count(u.prodid) as count from prods p 
left outer join usage u on p.prodid=u.prodid 
where p.ownerid>0 and p.active=1
group by p.prodid
order by rand() limit 1;

Я тоже пытался использовать этот стиль ...

select p.*, count(u.prodid) as count from prods p
left outer join usage u on p.prodid=u.prodid
where prodid in 
(select prodid from prods 
where ownerid>0 and active=1 
group by prodid order by rand() limit 1);

но MySQL не поддерживает LIMIT в подзапросе 'in' ...

Объяснение / описание выглядит так ...

+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                        |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
|  1 | SIMPLE      | p     | range | ownerid       | ownerid | 4       | NULL |   11 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | u     | index | NULL          | userid  | 8       | NULL |   52 | Using index                                  | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+

2 строки в наборе (0,00 с)

Хотя некоторые из вас могут подумать: «Ну и что, если он выполняет соединение без индекса», возможно, это скорее раздражение, чем что-то, что может стать проблемой, но я ценю, что может быть лучший способ достичь того, что нужно в любом случае особенно когда количество строк в таблице растет ...

Так что любые идеи приветствуются!

1 Ответ

1 голос
/ 26 сентября 2011

Обычно быстрее выполнить несколько запросов, чем сортировать таблицу по rand().Сначала получите случайное число строки:

select floor( count(*) * rand() ) random_number
from prods
where ownerid > 0 and active = 1

А затем получите конкретную строку:

select p.*, count(u.prodid) as count 
from prods p
left outer join usage u on p.prodid = u.prodid
where prodid = (
    select prodid from prods 
    where ownerid > 0 and active = 1 
    limit {$random_number}, 1
)

Кстати, ваш подзапрос возвращает только одно поле, поэтому вы можетеиспользуйте = вместо in оператора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...