#mysql #performance
#mysql #Производительность
Вопрос:
Мне было интересно, нужно ли мне вводить условный оператор для удаления критерия, если этот критерий таков, что он охватывает все возможные значения в столбце. Пример выглядит следующим образом:
SELECT product FROM Table where condition = 'condition' AND class <= 255;
Допустим, столбец класса имеет значение TINYINT unsigned NOT NULL DEFAULT 0
. Будет ли MySQL по-прежнему точно сканировать столбец, чтобы проверить, если class <= 255
? Как приведенный выше запрос выполняется по отношению к этому заявлению ниже, предполагая, что у меня 10 миллионов строк?
SELECT product FROM Table where condition = 'condition';
После некоторого тестирования в моей собственной базе данных я понимаю, что MySQL точно сканирует весь столбец, хотя очевидно, что поиск вернет весь столбец. Разница в производительности для моего случая составляет порядка нескольких секунд. Между двумя планами запросов нет разницы.
Я хотел бы дополнительно добавить, что сканирование также будет выполнено для запроса ниже:
SELECT product FROM Table where condition = 'condition' AND class >= 0;
Я не уверен, почему такой запрос не оптимизирован MySQL. Я надеюсь, что кто-нибудь сможет просветить меня ответом. Спасибо 🙂
Комментарии:
1.
tinyint(1)
совпадает сtinyint
и может хранить значения от -128 до 127: dev.mysql.com/doc/refman/5.0/en/numeric-types.html2. В консоли MySQL запустите
EXPLAIN SELECT product FROM Table where condition = 'condition' AND class <= 9;
иEXPLAIN SELECT product FROM Table where condition = 'condition';
и посмотрите, получите ли вы другой план выполнения.3. @ michael, я вижу, что вы правы в этом. Позвольте мне пересмотреть мой вопрос, чтобы сделать его более применимым.
4. @ Asaph, план запроса точно такой же.
5. Столбец должен быть
NOT NULL
forclass <= 255
, чтобы гарантированно совпадать со всеми строками. Кстати, я тестировал в SQL Server, и это тоже не обнаруживает этого, если в столбец не добавлено явно избыточное ограничение проверки.CREATE TABLE #T(X TINYINT NOT NULL PRIMARY KEY,Y TINYINT NOT NULL CHECK (Y BETWEEN 0 AND 255),Z INT UNIQUE);SELECT Z FROM #T WHERE Y <= 255
Ответ №1:
MySQL не устраняет бессмысленные критерии, например, class >= 0
для столбца целых чисел без знака.
Вот список всех where
оптимизаций, которые выполняет MySQL:
http://dev.mysql.com/doc/refman/5.0/en/where-optimizations.html
Однако MySQL обнаруживает, что class >= 0
будет много обращений, и не будет пытаться использовать индекс.
Что касается condition = 'condition'
предложения, использует ли он индекс, определяется мощностью этого столбца.
Более чем, скажем, 20% строк соответствуют условию, будет выполнено полное сканирование таблицы, если не будет использоваться индекс.
Если оба критерия могут использовать индекс, будет использоваться индекс с наибольшей ожидаемой мощностью.
MySQL будет использовать только один индекс для каждой таблицы для каждого подвыбора / объединения.
MySQL не исключает критерии where из оценки, но выполняет логическую оценку короткого замыкания для AND и OR .
Таким образом, это позволит избежать полного сканирования таблицы, если он может использовать индекс on condition
.
Если MySQL выполняет полное сканирование таблицы
Ему нужно будет выполнить другой тест class
только для тех строк, которые совпадают condition
, но не для всех строк.
Оптимизатор запросов будет оценивать предложения в порядке, который дает самые быстрые результаты, поэтому он должен condition
сначала оценить (потому что это =
сравнение), а затем class
(потому что его a> тест с низким значением).
Комментарии:
1. как обсуждалось с Avi, независимо от того, включен индекс или нет
condition
, MySQL все равно выполняет проверкуclass
столбца. С индексом этот процесс ускоряется. На эту часть вопроса был дан ответ. Вторая часть о том, почему такая оптимизация не была выполнена, отсутствует.