Возможны многие улучшения:
- Во-первых, давайте поговорим о внешнем запросе (основной запрос SELECT) к таблице
oc_subject
.Этот запрос может использовать ORDER BY
Оптимизация с использованием составного индекса: (status, created)
.Итак, определите следующий индекс (если он еще не определен):
ALTER TABLE oc_subject ADD INDEX (status, created);
- Во-вторых, ваш подзапрос для получения Count не является Sargeable из-за использования
Date()
функция в столбце внутри WHERE
предложения.Из-за этого он не может правильно использовать индексы.
Кроме того, DATE(oc_details.created) > DATE(NOW() - INTERVAL 1 DAY)
просто означает, что вы пытаетесь рассмотреть те детали, которые созданы на текущую дату (сегодня).Это может быть просто записано как: oc_details.created >= CURRENT_DATE
.Хитрость в том, что даже если столбец created
имеет тип datetime, MySQL будет имплицитно преобразовывать значение CURRENT_DATE
в CURRENT_DATE 00:00:00
.
Поэтому измените внутренний подзапрос следующим образом:
SELECT COUNT(sid)
FROM oc_details
WHERE oc_details.created >= CURRENT_DATE
AND oc_details.sid = oc_subject.id
- Теперь все улучшения внутреннего подзапроса будут полезны, только если у вас есть правильный индекс, определенный для
oc_details
Таблица.Итак, определите следующий составной (и охватывающий) индекс в таблице oc_details
: (sid, created)
.Обратите внимание, что здесь важен порядок столбцов, поскольку created
является условием Range, поэтому оно должно появляться в конце.Итак, определите следующий индекс (если он еще не определен):
ALTER TABLE oc_details ADD INDEX (sid, created);
- В-четвертых, в случае многостоловых запросов целесообразно использовать Aliasing для ясности кода (улучшенная читаемость) и избежания однозначного поведения.
Итак, как только вы определили все индексы (как обсуждалось выше), вы можете использовать следующий запрос:
SELECT s.*,
(SELECT COUNT(d.sid)
FROM oc_details AS d
WHERE d.created >= CURRENT_DATE
AND d.sid = s.id) as totalDetails
FROM oc_subject AS s
WHERE s.status='1'
ORDER BY s.created DESC LIMIT " . (int)$start . ", " . (int)$limit;