MYSQL - НЕ против var = false - PullRequest
       3

MYSQL - НЕ против var = false

11 голосов
/ 07 ноября 2011

В последние дни я заметил странную оптимизацию моего запроса. У меня есть простой запрос, который делает что-то вроде:

   SELECT id,name,amount FROM reservations WHERE NOT canceled ORDER BY name ASC

Я заметил, что mysql не использовал никаких индексов, поэтому я начал проводить некоторые эксперименты. Случайно я заменил «НЕ отменено» на «отменено = ложь», а затем Mysql начал использовать «отменено» в качестве индекса. После этого я попытался использовать противоположное:

   SELECT ... FROM reservations WHERE canceled ORDER BY ...

Тот же результат! Когда я изменяю это на «cancelled = true», индекс снова работает.

Мой вопрос: КАК ПРИХОДИТЬ ?! Разве использование «НЕ» не является «элегантным» способом? Во всяком случае, я не ожидал, что это что-то изменит.

Я использую InnoDB в качестве движка, но я получаю тот же результат, используя MyISAM. Может кто-нибудь прояснить ситуацию? Спасибо.

Редактировать: Структура таблицы

CREATE TABLE `reservations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `trip_code` varchar(10) DEFAULT NULL,
  `departure_date` date DEFAULT NULL,
  `amount` float DEFAULT NULL,
  `name` varchar(45) DEFAULT NULL,
  `canceled` tinyint(1) NOT NULL DEFAULT '0',
  `created_date` date NOT NULL,
  `creator_user` int(11) NOT NULL DEFAULT '1',
  `last_update_user` int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `trip_code` (`trip_code`),
  KEY `departure_date` (`departure_date`),
  KEY `created_date` (`created_date`),
  KEY `canceled` (`canceled`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=123181 ;

Ответы [ 3 ]

3 голосов
/ 07 ноября 2011

Даже если он использует индекс, индекс (верите или нет) может замедлить ваш запрос. Это немного странно, но это связано с селективностью индекса. Обычно он представлен в столбцах типа boolean.

Это расшифровывается как:

"Как различны значения поля. Это число от 0-1, хотя вы также можете думать об этом в процентах. Значение 1 или 100% означает, что каждое значение в поле уникально "

Важно учитывать, потому что:

"MySQL имеет оптимизатор на основе затрат. Это означает, что MySQL рассчитывает затраты на различные способы выполнения запроса, а затем выбирает самый дешевый. Ну, расчет затрат - это неточная наука. Так что оценка сделана, а оценка иногда неверна. "

Простой простой:

Если данные, которые вы просматриваете, имеют более или менее 20% одного и того же значения (например, у отмененных - 40% таблицы), то просто выполнить сканирование таблицы.

EDIT:

Что касается вашего вопроса, EXPLAIN сообщает, что MySQL использует индекс. Но, возможно, это нехорошо, единственный способ определить, насколько лучше ваша оптимизация, - это проверить производительность. Кроме того, рассмотрите стоимость операций INSERT, UPDATE и DELETE, чтобы сохранить этот индекс. Выполните профилирование с индексом и без него.

Взгляните на это:

2 голосов
/ 07 ноября 2011

Я не знаком с MYSQL, но, думая логически, я понимаю это так:
Индекс похож на телефонную книгу, когда вы ищете «Коэн», вы можете получить его сразу.
Но если вы ищете NOT «Коэн», вам придется просмотреть каждую запись и проверить, не отличается ли она от «Коэна».
Поэтому, когда вы ищете конкретное значение , оно ищет именно его. И когда вы используете NOT , он ищет любое другое значение, которое может поместиться в tinyint(1) (насколько я понимаю, это не только 1 или 0, не так ли?).

1 голос
/ 07 ноября 2011
SELECT *
FROM 
(SELECT 1 AS C, 0 AS X UNION ALL
SELECT 2 AS C, 1 AS X UNION ALL
SELECT 3 AS C, 2 AS X ) T
WHERE X=true

Возвращает

'2', '1'

И

SELECT *
FROM 
(SELECT 1 AS C, 0 AS X UNION ALL
SELECT 2 AS C, 1 AS X UNION ALL
SELECT 3 AS C, 2 AS X ) T
WHERE X

Возвращает

'2', '1'
'3', '2'

Таким образом, в первом случае true приводится к int, а затем используется в предикате с возможностью поиска, тогда как во втором случае значение столбца неявно приводится. Неявные приведения, как правило, делают условие невыносимым.

Просмотр плана объяснения для вашего запроса с помощью WHERE canceled = true дает

+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+
| id | select_type |    table     | type | possible_keys |   key    | key_len |  ref  | rows |            Extra            |
+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | reservations | ref  | canceled      | canceled |       1 | const |    1 | Using where; Using filesort |
+----+-------------+--------------+------+---------------+----------+---------+-------+------+-----------------------------+

Принимая во внимание, что WHERE canceled вы получаете

+----+-------------+--------------+------+---------------+-----+---------+-----+------+-----------------------------+
| id | select_type |    table     | type | possible_keys | key | key_len | ref | rows |            Extra            |
+----+-------------+--------------+------+---------------+-----+---------+-----+------+-----------------------------+
|  1 | SIMPLE      | reservations | ALL  |               |     |         |     |    2 | Using where; Using filesort |
+----+-------------+--------------+------+---------------+-----+---------+-----+------+-----------------------------+

Похоже, что в данном случае он даже не может рассматривать индекс canceled как возможную опцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...