Как я могу оптимизировать мой запрос MySQL? поскольку для получения записей требуется 45 секунд

0

Моя таблица базы данных "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
  • 0
    Вам нужно добавить индексы на вашу таблицу, создать индекс для всех таблиц. Для создания индексов используйте столбцы, которые вы указываете в предложении WHERE.
  • 0
    Очень полезно, спасибо!
Теги:
mysqli
query-optimization

2 ответа

1

Ваш запрос в порядке! Это сама таблица, которая является проблемой.

Обязательно добавьте индексы в столбцы, с помощью которых вы находите записи (например, ringtunes.Deleted = 0, ваш индекс должен идти в столбце "Удаленные"). То же самое касается других столбцов, которые вы проверяете для значений.

https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html

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')

Ещё вопросы

Сообщество Overcoder
Наверх
Меню