2010-11-11 3 views
1

Как я могу избежать использования временной таблицы для этого запроса и выполнения той же цели?Как избежать использования временной таблицы для этого простого запроса

EXPLAIN EXTENDED 
SELECT DISTINCT id, view_count 
    FROM 
     screenshot_udb_affect_assoc 
    INNER JOIN 
     screenshot ON id = screenshot_id 
    WHERE unit_id = 110 LIMIT 0, 6 

id select_type table type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE screenshot_udb_affect_assoc ref screenshot_id,unit_id unit_id 4 const 34 100.00 Using temporary 
1 SIMPLE screenshot eq_ref PRIMARY PRIMARY 4 source_core.screenshot_udb_affect_assoc.screenshot... 1 100.00 

Я обновил запрос не использовать RAND() больше и вместо LIMIT будут рандомизированы с помощью PHP. Хотя он по-прежнему показывает, что он использует временную таблицу

+0

Подходит ли 'unit_id' к' screensho't? Сколько скриншотов существует с 'unit_id = 110'? Сколько «screenshot_udb_affect_assoc' за« скриншот »? – Quassnoi

+0

Примерно 150 снимков экрана для данного устройства, возможно, 12-15 единиц на скриншот – Webnet

+0

Не могли бы вы привести пример того, как выглядит новый запрос, который вы создаете (желательно с EXPLAIN)? –

ответ

2
SELECT rnd_id, rnd_value 
FROM (
     SELECT @cnt := COUNT(*) + 1, 
       @lim := 6 
     FROM screenshot 
     JOIN screenshot_udb_affect_assoc 
     ON  screenshot_id = id 
     WHERE unit_id = 110 
     ) vars 
STRAIGHT_JOIN 
     (
     SELECT r.*, 
       @lim := @lim - 1 
     FROM (
       SELECT id, view_count 
       FROM screenshot 
       JOIN screenshot_udb_affect_assoc 
       ON  screenshot_id = id 
       WHERE unit_id = 110 
       ) r 
     WHERE (@cnt := @cnt - 1) 
       AND RAND() < @lim/@cnt 
     ) i 

пояснено более подробно в этой статье:

Это все еще нуждается в двух сканирований на всех строк, удовлетворяющих запросу, но не filesort.

Создайте следующие индексы:

screenshot (unit_id) 
screenshot_udb_affect_assoc (screenshot_id) 
+0

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

+0

@Webnet: вы можете заменить 'COUNT (*)' грубой оценкой. Случайность немного пострадает от нее, но она будет завершена только одним сканированием. – Quassnoi

2

ORDER BY RAND() автоматически вызывает временную таблицу для создания.

Он работает, создавая временную таблицу с новым столбцом, заполненным случайными числами. Затем он выполняет запрос к временной таблице, используя ORDER BY.

Чтобы избежать использования временной таблицы, вам нужно будет найти новый метод выбора случайных чисел.

Решение, которое я использовал ранее (которое полагается на строки, которые не удаляются), состоит в том, чтобы сделать SELECT COUNT на столе, а затем выбирать случайные числа в этом диапазоне и выбирать только эти строки.

Существует ряд других решений, но ORDER BY RAND() не является хорошим решением.

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