2010-08-19 3 views
3
SELECT count(*) c FROM full_view WHERE verified > (DATE (NOW()) - INTERVAL 30 DAY) 

Если я запустил этот запрос, он занимает секундную долю секунды, но если я переключу оператор сравнения вокруг него, он берет эоны. Теперь первый способ count = 0 и второй способ count = 120000, но если я просто подсчитаю всю таблицу, которая также занимает микросекунды.MySQL - Почему COUNT с «больше, чем» быстро, но «меньше» занимает навсегда?

Но есть что-то фанки, потому что, если запрос когда-либо заканчивается, он быстро запускается быстрее. MySQL кэширует запрос или что-то в этом роде? Ну, я не хочу зависеть от кешей, чтобы убедиться, что сайт не висит.

Это кажется бессмысленным: если он может быстро подсчитать все, что будет больше, чем определенная дата, почему это должно занять больше времени, чтобы считать противоположное? В любом случае, он должен смотреть всю таблицу прямо? И все, что ему нужно вернуть, - это номер, поэтому пропускная способность не должна быть проблемой.

Объясните по запросу:

1, 'SIMPLE', 'b', 'range', 'updated,verified_index', 'updated', '3', '', 28, 'Using where'`  
1, 'SIMPLE', 'l', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'xyz_main.b.loc_id', 1, 'Using index' 
1, 'SIMPLE', 'f', 'ALL', '', '', '', '', 2214, '' 

EDIT:

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

Handler_read_rnd_next:

  • 254436689 (whe п делать меньше)
  • 2 (для больше)

Key_read_requests: 314393 против 33 (33 является самым большим числом для всех статистике при использовании более)

Handler_read_key: 104303 vs 1

В обход зрения и выполнение запроса непосредственно на главном столе исключается медлительность. Итак, что мне нужно сделать, чтобы ускорить его? Мнение по существу, как это:

SELECT x, y, z, verified FROM table1 LEFT JOIN table2 on tab2_ID = table2.ID LEFT JOIN table3 on tab3_ID = table3.ID 

РЕШИТЬ: Фрэнки привели Мои в правильном направлении. Вторая объединенная таблица (таблица компании) была объединена через полное текстовое название компаний. Я только недавно решил добавить целочисленный ключ к этой таблице. Столбец имени должен был быть проиндексирован, но я, возможно, это испортил. В любом случае я все реорганизовал. Я преобразовал внешний ключ в основную таблицу, чтобы соответствовать целочисленному идентификатору таблицы компании, а не полному названию компании. Я повторно проиндексировал эти столбцы в каждой таблице, а затем обновил представление, чтобы отразить новую точку соединения. Теперь он работает мгновенно в обоих направлениях. :) Итак, я думаю, что ключевыми являются ключевые слова. Проблема ушла, но все же, я не чувствую, что мой оригинальный вопрос был действительно решен.

Спасибо за помощь.

+0

Я предполагаю, что «full_view» - это представление, каково его определение? –

+1

Что говорит вам «объяснение плана»? –

+0

full_view содержит основную таблицу (с проверенным столбцом) слева, соединенную с двумя другими таблицами. Главная таблица - это люди, а две другие таблицы объединяются в местоположение и информацию о компании. Это довольно прямолинейно. – Moss

ответ

3

Пожалуйста, запустите следующий запрос и опубликуйте результаты.

EXPLAIN SELECT count(*) c 
FROM full_view 
WHERE verified > (DATE (NOW()) - INTERVAL 30 DAY) 

Давно забыто EXPLAIN почти всегда приносит что-то! ;)


Edit 1:
Это, вероятно, наступательная линия:

1, 'SIMPLE', 'f', 'ALL', '', '', '', '', 2214, '' 

ALL там говорится, что существует полное сканирование таблицы.

Вы можете копать дальше в Explain syntax on this diagram.

ли попытаться увидеть, где различия идут ...


Edit 2:
This doc will sure make things much clearer on the Explain output. Please check it out.


Edit 3:
Шаг за шагом Analys команды объяснения.

1, 'SIMPLE', 'b', 'range', 'updated,verified_index', 'updated', '3', '', 28, 'Using where'`  
1 - id 
SIMPLE - simple select, not using sub-queries 
b - table name 
range - only rows that are in a given range are retrieved, using an index 
updated,verified_index - are both possible keys 
updated - was the key eventually used 
3 - key lenght 
'' - this is the ref column and would show which columns or constants are compared to the index name in the key column to select rows from the table. 
28 - number of rows mysql believes it must examine to execute the query 
Using where - self explanatory 
2

Я предполагаю, что вычитание из Date(Now()) - это то, что занимает много времени для обработки. При значениях verified, которые уже меньше Date(Now()), оценка может быть короткозамкнутой, так как в этот момент она ДОЛЖНА быть ложной (при сравнении «больше»).

В ситуации, когда вы сравниваете «меньше», время даты должно быть вычтено в каждом случае независимо от текущего значения, поскольку оно не имеет логического завершения выражения, которое должно быть истинным или ложным до оценка вычитания даты и времени

Это только предположение, однако - возьмите его с солью.

+0

Использование явной даты также берет навсегда. – Moss

+0

@Moss Интересно, может быть, моя идея вне базы. Как насчет того, чтобы просто изменить порядок сравнения? Вместо 'A < B', do 'B > A' и посмотрите, требуется ли это так долго - он должен выполняться точно так же (я бы догадался) –

+0

Интересная мысль, но слишком поздно, чтобы попробовать ее сейчас. Я решил проблему с более качественными ключами/индексацией. – Moss

0

Если у вас есть указатель на verified в таблице, тем более строгий COUNT (> один) будет быстрее. COUNT (*) без предложения WHERE может быстро возвращаться, поскольку счет можно почерпнуть из статистики таблицы/индекса.

+0

Помещение сравнения внутри подсчета является более приятным синтаксисом, но оно не ускоряет его. И у меня есть индекс на 'проверенный'. – Moss

+0

На самом деле этот метод замедляет работу в обоих направлениях. – Moss

1

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

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

  • Нет связанных вопросов^_^