2012-06-08 2 views
1

У меня есть проблемы со следующим запросом, который очень медленно:MySQL оптимизации запросов с группой по и порядке рандов

 
    SELECT A.* FROM B 
    INNER JOIN A ON A.id=B.fk_A 
    WHERE A.creationDate BETWEEN '20120309' AND '20120607' 
    GROUP BY A.id 
    ORDER BY RAND() 
    LIMIT 0,5 

объясняет:

 

    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE B index fk_A fk_A 4 \N 58962 Using index; Using temporary; Using filesort 
    1 SIMPLE A eq_ref PRIMARY,creationDate PRIMARY 4 B.fk_A 1 Using where 

INDEXES:

 

    A.id (int) = PRIMARY index 
    A.creationDate (date) = index 
    B.fk_A = index 

Вы видите что-то для оптимизации?

Большое спасибо за ваши советы

+0

ли это MyISAM или InnoDB таблицы? –

+0

Сколько строк возвращается - если вы удалите 'LIMIT'? –

ответ

1

Я думаю, что функция RAND() будет создавать ценности в Rand() для каждой строки (именно поэтому using temporary показывает вверх, и filesort, потому что он не может использовать индекс .

лучшим способом было бы SELECT MAX(id) FROM a, чтобы получить максимальное значение. затем создать 5 случайных чисел от 1 до MAX (ID) и сделать SELECT ... WHERE a.id IN (...) запрос.

Если результат имеет менее 5 строк (потому что запись была удалена) повторите процедуру (или изначально создайте 100 случайных чисел и LIMIT запрос на 5.

Это не 100% -ное решение mysql, потому что вам нужно сделать логику в своем коде, но будет намного быстрее, я верю ,

Update Просто Обнаружил интересную статью в интернете, что в основном говорит то же: http://akinas.com/pages/en/blog/mysql_random_row/

+0

Очень интересно, спасибо! – heisenberg

1

Одним из возможного переписывания запроса:

SELECT A.* 
FROM A 
WHERE A.creationDate BETWEEN '20120309' AND '20120607' 
    AND EXISTS 
     (SELECT * 
     FROM B 
     WHERE A.id = B.fk_A 
    ) 
ORDER BY RAND() 
LIMIT 0,5 
+0

Отлично! большое спасибо – heisenberg

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