Моя таблица базы данных "ringtune_history" содержит 40 тыс. Записей, а "ringtunes" - 4 тыс. Записей, и запрос занимает слишком много времени для обработки.
SELECT 'ringtunes'.*,
count(case when ringtune_history.Action = 'Download' then ringtune_history.Action end) as Org_Downloads,
count(case when ringtune_history.Action = 'View' then ringtune_history.Action end) as Org_Views,
count(case when ringtune_history.Action = 'Play' then ringtune_history.Action end) as Total_Plays,
count(case when ringtune_history.Action = 'Like' then ringtune_history.Action end) as Total_Likes,
'categories'.'Name' as 'Category_Name'
FROM 'ringtunes'
LEFT JOIN 'ringtune_history' ON 'ringtune_history'.'Ringtune_Id' = 'ringtunes'.'Id'
LEFT JOIN 'categories' ON 'categories'.'Id' = 'ringtunes'.'Category'
WHERE 'ringtunes'.'Deleted' = 0
AND 'ringtunes'.'Status' = 1
AND 'categories'.'Deleted' = 0
AND 'categories'.'Status' = 1
GROUP BY 'ringtunes'.'Id'
ORDER BY 'ringtunes'.'Id' DESC
LIMIT 20
Ваш запрос в порядке! Это сама таблица, которая является проблемой.
Обязательно добавьте индексы в столбцы, с помощью которых вы находите записи (например, ringtunes.Deleted = 0
, ваш индекс должен идти в столбце "Удаленные"). То же самое касается других столбцов, которые вы проверяете для значений.
Не используйте LEFT
если вам не нужны значения NULL, если отсутствует "правильная" таблица. Очевидно, что categories
не должны быть LEFT
. Неясно, можно ли изменить ringtune_history
на простой JOIN
.
Нужны индексы:
ringtune: (deleted, status, ID) or (status, deleted, ID)
ringtune_history: (Ringtune_Id, Action)
(Пожалуйста, предоставьте SHOW CREATE TABLE
если есть другие подсказки/подсказки.)
Кажется, у вас есть шаблон "взорвать-взорвать" - сначала вы JOIN
нескольким таблицам, что приводит к потенциально большему набору промежуточных строк. При этом эта таблица довольно громоздкая из-за большого количества столбцов. Затем вы свернете вещи с помощью GROUP BY
. Если возможно, сначала найдите идентификаторы таблицы, которую вы в конечном итоге GROUP BY
. Затем JOIN
это к другим таблицам и (возможно) вернитесь к исходной таблице - чтобы получить остальные столбцы.
Вы можете, по крайней мере, отложить просмотр ringtune_history
до ringtune_history
пор, пока не ringtune_history
20 нужных строк в двух других таблицах. Это ограничит количество поисков в нем только 20, а не "все".
Если deleted
и status
двух столбцов всегда совпадает, не проверяйте их по categories
. (Это облегчит достижение исправления взрыва-взрыва.) Если они обязательно независимы, тогда я предлагаю, чтобы каждая таблица была лучше, если вы действительно удалили нежелательные строки (или переместили их в архивную таблицу). Текущее WHERE
является сложным, поскольку оно фильтрует две разные таблицы.
(Не критично :) это
count(case when ringtune_history.Action = 'View' then ringtune_history.Action end)
можно сократить до
SUM(ringtune_history.Action = 'View')