2014-10-13 3 views
0

следующий запрос mysql занял 40 секунд, и его слишком многоОптимизация медленного запроса mysql

как я могу его оптимизировать?

SELECT 
    downloads.*, 
    COUNT(DISTINCT comment.id) AS commentsNum, 
    AVG(users_votes.rate) AS score, 
    COUNT(DISTINCT users_votes.id) AS rateNum, 
    COUNT(DISTINCT users_download.id) AS downloadsNum 
FROM downloads 
LEFT JOIN (
    SELECT * FROM comment WHERE type='download' 
) comment ON downloads.id = comment.typeID 
LEFT JOIN (
    SELECT * FROM users_votes WHERE section='download' AND rate>0 
) users_votes ON downloads.id = users_votes.voteID 
LEFT JOIN (
    SELECT id,downloadID FROM users_download GROUP BY userID,downloadID 
) users_download ON downloads.id = users_download.downloadID 
GROUP BY downloads.id 

результат EXPLAIN:

enter image description here

+0

@FatihK что я должен делать? –

+0

индексируется столбец 'downloads.id'? это indexex при использовании в качестве fk также (например, 'users_download.downloadID')? – Paolo

+0

@Paolo да, это первичный ключ –

ответ

1

Вы должны группа результирующие наборы в соединим download_id.

SELECT 
    downloads.*, 
    comment.commentsNum, 
    users_votes.AvgScore, 
    users_votes.rateNum, 
    users_download.downloadsNum 
FROM downloads 
LEFT JOIN (
    SELECT TypeID,COUNT(*) AS commentsNum FROM comment WHERE type='download' GROUP BY TypeID 
) comment ON downloads.id = comment.typeID 

LEFT JOIN (
    SELECT voteID,AVG(rate) AS AvgScore,COUNT(*) AS rateNum FROM users_votes WHERE section='download' AND rate > 0 GROUP BY voteID 
) users_votes ON downloads.id = users_votes.voteID 

LEFT JOIN (
    SELECT downloadID,COUNT(userID) AS downloadsNum FROM users_download GROUP BY downloadID 
) users_download ON downloads.id = users_download.downloadID 
1

Из вашего объяснения, это выглядит как users_download таблица является виновником. Запрос вынужден сканировать 100k строк из этой таблицы, я предполагаю, что это из-за GROUP BY в сочетании с не ударом индекса.

«Использование filesort» является предупреждающим знаком, так как он должен писать части вашей таблицы на диск, чтобы иметь возможность сортировать (возможно, снова группировать). Диск, как мы все знаем, очень медленный.

Я не уверен, что вы пытаетесь сделать точно, но GROUP BY часто дорого, поэтому, если вы можете переписать свой запрос, не используя GROUP BY, это может быть полезно для производительности. В противном случае попробуйте создать индекс, который поможет MySQL найти правильные строки без сканирования такой большой части таблицы.

0

это оптимизированный запрос

почему этот запрос выполняется очень быстро?

но старый запрос выполняется очень медленно?

эксперт программисты анализируют, что :)

SELECT 
    downloads.*, 
    comment.commentsNum AS commentsNum, 
    users_votes.AvgScore AS score, 
    users_votes.rateNum AS rateNum, 
    users_download.downloadsNum AS downloadsNum 
FROM downloads 
LEFT JOIN (
    SELECT typeID,COUNT(id) AS commentsNum FROM comment WHERE type='download' GROUP BY typeID 
) comment ON downloads.id = comment.typeID 

LEFT JOIN (
    SELECT voteID, AVG(rate) AS AvgScore,COUNT(id) AS rateNum FROM users_votes WHERE section='download' AND rate > 0 GROUP BY voteID 
) users_votes ON downloads.id = users_votes.voteID 

LEFT JOIN (
    SELECT id,downloadID,COUNT(id) AS downloadsNum FROM users_download WHERE id IN (SELECT MIN(id) FROM users_download GROUP BY userID,downloadID) GROUP BY downloadID ORDER BY downloadID 
) 
users_download ON downloads.id = users_download.downloadID 
Смежные вопросы