2012-01-27 3 views
1

Когда я запустил SQL-запрос ниже, производительность очень медленная.Улучшение производительности SQL

В таблице указано более 400 000 строк, и у меня есть индекс CheckDate.

CheckDate тип datetime

SELECT username, COUNT(*) AS TotalUser 
FROM table 
     WHERE DATE(CheckDate) = CURDATE() 

Как это исправить?

+0

Это единственный вопрос, который медленный? как насчет других запросов, возвращающих почти такой же объем данных? каково текущее время отклика? – Bhushan

+1

Вы должны запустить функцию 'DATE' на каждом столбце' CheckDate', после чего вам нужно проверить, что соответствует 'CURDATE()'. Это 400 000 дат, которые обрабатываются, а затем (без индекса) по сравнению со стоимостью. Неэффективное использование функций 'DATE' /' CURDATE'. –

+0

@Bhushan Я обновил запрос. Потребуется около 3 секунд, чтобы получить результат даже при обнаружении только одной записи. –

ответ

3

Попробуйте использовать сравнение диапазона вместо прямого равенства. Другими словами, переписать запрос в

SELECT username, COUNT(*) AS TotalUser 
    FROM table 
    WHERE CheckDate BETWEEN CURDATE() AND ADDDATE(CURDATE(), INTERVAL 1 DAY) 

или, возможно,

SELECT username, COUNT(*) AS TotalUser 
    FROM table 
    WHERE CheckDate >= CURDATE() AND 
     CheckDate < ADDDATE(CURDATE(), INTERVAL 1 DAY) 

Смотрите, если это помогает.

EDIT: Или первый запрос может быть переработан в

SELECT username, COUNT(*) AS TotalUser 
    FROM table 
    WHERE CheckDate BETWEEN CURDATE() AND 
          ADDDATE(ADDDATE(CURDATE(), INTERVAL 1 DAY), INTERVAL -1 SECOND) 

но начинает становиться довольно уродливыми, и я не уверен, что отрицательные числа допускаются в ИНТЕРВАЛЬНЫХ спецификаторах.

В любом случае, если вы обнаружите, что хотите усечь дату, чтобы увидеть, совпадает ли она с какой-либо другой датой, лучшим вариантом является использование дальнего сравнения. В более общем плане, старайтесь избегать использования функций в значениях столбцов в предложении WHERE, если есть способ избежать этого.

Делитесь и наслаждайтесь.

+0

Это работает и быстро! Благодарю. Это будет проверять текущую дату и НЕ на следующий день? –

+0

+1: Используя эту структуру, вы не выполняете никаких операций с фильтруемым значением. Вы просто говорите «все значение в этом диапазоне». Это означает, что оптимизатор может использовать индекс и обрабатывать только соответствующие записи * (где, поскольку запрос OPs может сканировать каждую запись во всем индексе) *. Никаких изменений в вашей модели, только изменение вашего запроса. * [Используйте версии '> =' и '<', чтобы избежать включения записей, отмеченных ровно в полночь на следующий день ...] * – MatBailie

+0

user791022 - вышеперечисленные * должны * находить значения только для текущего дня, но запускать некоторые тесты и убедитесь, что это то, что вы получаете. Если это не так, настройте по мере необходимости. Поделитесь и наслаждайтесь. –

1

Вы не работаете с функциональным индексом. В вашем пункте WHERE используется функция DATE(), которая не будет использовать индекс. Используйте столбец CheckDate в качестве прямого компаратора.

Это не значит, что он пойдет быстрее, но будет моим первым стартом.

+0

Вы говорите, что у меня должны быть отдельные поля? Например: CheckDate ('DATE') и CheckTime (' TIME')? –

+0

НЕТ! Не используйте функцию вокруг вашего атрибута. Используйте прямые атрибуты comarisons, например 'CheckDate = f1 (f2 (foo))' – Xailor

1

Индекс в поле CheckDate не используется из-за функции DATE.

Каждый раз, когда вы используете какую-либо функцию в столбце, индексы в этом столбце не будут использоваться.

Это ситуация, когда вам следует подумать о создании вычисленного столбца в таблице с помощью выражения DATE (CheckDate), а затем создать индекс в вычисленном столбце (да, он будет сохраняться в базе данных, но я уверен тогда будет использоваться индекс.)

+0

ой, кстати, я не рассматривал, действительно ли вам нужно вызвать функцию DATE в поле. Логика действительна для любой функции. – Diego

Смежные вопросы