Как оптимизировать запросы mysql, содержащие DATE_ADD()?

#mysql #indexing #query-optimization

#mysql #индексирование #оптимизация запросов

Вопрос:

Вот запрос, который необходимо оптимизировать:

 Scans: 527676 records...
Returns: 496 records...

SELECT * FROM customers c
WHERE DATE_ADD(c.`custdate` ,INTERVAL -5 HOUR) BETWEEN '2011-09-14 00:00:00' AND '2011-09-14 23:59:59'
AND c.`custtype`='L'
  

Это то же самое без использования DATE_ADD:

 Scans: 801 records...
Returns: 481 records...

SELECT * FROM customers c
WHERE c.`custdate` BETWEEN '2011-09-14 00:00:00' AND '2011-09-14 23:59:59'
  

Вопрос в том, как мне оптимизировать этот запрос с помощью функции DATE_ADD()? Без использования DATE_ADD он подбирает мои индексы, и запрос в порядке.

Ожидаю помощи по этому вопросу.

Спасибо,

Рахиль

Ответ №1:

Поскольку вы просто добавляете постоянный временной интервал c.custdate , вместо этого следует вычесть этот временной интервал из BETWEEN значений, чтобы получить запрос, который логически эквивалентен, но позволяет MySQL использовать индекс. В общем случае, если запрос требует вычисления функции значений индекса, сканирование диапазона не может быть использовано.

То есть: вместо WHERE предложения, являющегося

 DATE_ADD(c.`custdate` ,INTERVAL -5 HOUR) BETWEEN '2011-09-14 00:00:00' AND '2011-09-14 23:59:59'
  

сделайте это

 c.`custdate` BETWEEN '2011-09-14 05:00:00' AND '2011-09-15 04:59:59'
  

Комментарии:

1. Полностью согласен — MySQL не может использовать индексы, когда вы выполняете функцию для рассматриваемого поля, поэтому всегда старайтесь выполнять функцию для критериев фильтрации, а не для поля. Затем MySQL может использовать доступные индексы

2. … кроме того, вполне возможно выполнить функцию «DATE_ADD» для каждого из значений в предложении «BETWEEN», поскольку MySQL будет оптимизировать их, где это возможно. Например. «c. custdate МЕЖДУ DATE_ADD (‘2011-09-14 00:00:00’ ИНТЕРВАЛ 5 ЧАСОВ) И DATE_ADD(‘2011-09-14 23:59:59’ ИНТЕРВАЛ 5 ЧАСОВ)»

3. Да, это работает.. Поскольку вы предлагаете добавить 5 часов к обоим предложениям dates in between, чтобы получить аналогичные результаты по состоянию на GMT-5, знаете ли вы удобную функцию для добавления 5 часов к datetime, чтобы я мог реорганизовать все запросы, используя date_add .

4. Как вы и предлагали, теперь я использую функцию DATE_ADD в критериях, а не в поле, однако, пока я использовал интервал -5 часов в поле, теперь я использую интервал 5 часов в критериях… ВЫБЕРИТЕ * ИЗ customers c, ГДЕ c. custdate МЕЖДУ DATE_ADD(‘2011-09-14 00:00:00’ , ИНТЕРВАЛ 5 ЧАСОВ) И DATE_ADD(‘2011-09-14 23:59:59’ , ИНТЕРВАЛ 5 ЧАСОВ) Большое спасибо за помощь…