- Попробуйте использовать дату и время вместо отметки времени
Если единственной причиной использования отметки времени является автоматическое значение по умолчанию при вставке и обновлении, используйте вместо этого дату и вставьте now () в вставки.и обновления или использовать триггеры.Отметка времени дает вам дополнительное преобразование для часовых поясов, но если у вас нет клиентов, подключающихся к вашей базе данных из разных часовых поясов, вы просто теряете время на преобразования.Одно это должно дать вам ускорение на 15-30%.
- Это может быть один из редких случаев, когда оптимизатор может выбрать неправильный индекс
И индекс кода продукта в этом неверендело.Поскольку вы группируете по коду продукта и используете где для другого столбца, который не очень избирателен, оптимизатор может подумать, что использование индекса для кода продукта может ускорить процесс.Но с использованием этого индекса он дает вам очень случайное сканирование с помощью поиска по индексу, но все же с довольно большим количеством строк, вместо более быстрого последовательного полу-полного сканирования без него, но с индексом order_date, чтобы ограничить число сканируемых строк.Оптимизатор просто не знает, что можно ожидать, что строки будут в основном отсортированы по порядку_даты на диске, а не по коду продукта.Конечно, чтобы индекс order_date работал, вы должны изменить свой запрос, чтобы при каждом сравнении с использованием имени столбца order_date было с одной стороны от =, <,> или BETWEEN, а с другой стороны - постоянные значения, как это предложил Боб Джавис в своем ответе.(+1 к нему).Так что вы можете попробовать его запрос слегка модифицированным, с исправленными форматами даты и принудительным использованием индекса order_date - при условии, что он у вас есть, если нет, вам действительно нужно добавить его с помощью
ALTER TABLE `order` ADD INDEX order_date( order_date );
Так что итоговый запрос должен выглядетьнапример:
SELECT thismonth.productcode,
(thismonth.ordercount-lastmonth.ordercount)/lastmonth.ordercount as riserate
FROM ( (SELECT productcode,
sum(quantity) as ordercount
FROM `order` FORCE INDEX( order_date )
WHERE order_date BETWEEN '2010-12-01' AND '2010-12-31'
GROUP BY productcode) as thismonth,
(SELECT productcode,
sum(quantity) as ordercount
FROM `order` FORCE INDEX( order_date )
WHERE order_date BETWEEN '2010-11-01' AND '2010-11-30'
group by productcode) as lastmonth)
WHERE thismonth.productcode = lastmonth.productcode
ORDER BY riserate;
Если не использовать индекс productid, это даст вам некоторую скорость (полное сканирование должно быть быстрее), а использование индекса order_date еще больше, в зависимости от того, сколько строк удовлетворяет условиям order_date по сравнению со всеми строками в таблице.