В чем разница между! Col и col = false в MySQL? - PullRequest
9 голосов
/ 25 марта 2010

Два оператора имеют совершенно разную производительность:

mysql> explain select * from jobs  where createIndexed=false;
+----+-------------+-------+------+----------------------+----------------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys        | key                  | key_len | ref   | rows | Extra |
+----+-------------+-------+------+----------------------+----------------------+---------+-------+------+-------+
|  1 | SIMPLE      | jobs  | ref  | i_jobs_createIndexed | i_jobs_createIndexed | 1       | const |    1 |       | 
+----+-------------+-------+------+----------------------+----------------------+---------+-------+------+-------+
1 row in set (0.01 sec)

mysql> explain select * from jobs  where !createIndexed;
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | jobs  | ALL  | NULL          | NULL | NULL    | NULL | 17996 | Using where | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+

Определение столбца и связанный индекс для вспомогательного анализа:

createIndexed tinyint(1) NOT NULL DEFAULT 0,
create index i_jobs_createIndexed on jobs(createIndexed);

Ответы [ 4 ]

5 голосов
/ 25 марта 2010

Логически эти операции одинаковы, но оптимизатор MySQL не настолько умен, чтобы видеть createIndexed = 0 в NOT createIndexed.

FALSE в MySQL это просто синоним для 0, а TRUE это синоним для 1.

Это условие ложно:

SELECT  2 = TRUE

--
0

, поэтому первый запрос - это просто чистый индекс ref по сравнению с 0, о котором знает MySQL, тогда как второй содержит более сложную логику, которую MySQL не может представлять как выражение sargable.

3 голосов
/ 25 марта 2010

MySQL не может использовать индекс для WHERE !createIndexed, потому что он должен оценивать NOT createIndexed для каждой строки при сканировании таблицы.

0 голосов
/ 25 марта 2010

В MySQL ключевое слово FALSE не является логическим фрагментом данных: это целая константа , равная нулю . Напротив, ! ( aka NOT ) - это логический оператор, который:

Значение равно 1, если операнд равен 0, 0, если операнд ненулевой, а НЕ NULL возвращает NULL.

Полагаю, что практической разницы не так много:

mysql> select 1=0, 0=0, 33=0, null=0, not 1, not 0, not 33, not null;
+-----+-----+------+--------+-------+-------+--------+----------+
| 1=0 | 0=0 | 33=0 | null=0 | not 1 | not 0 | not 33 | not null |
+-----+-----+------+--------+-------+-------+--------+----------+
|   0 |   1 |    0 |   NULL |     0 |     1 |      0 |     NULL |
+-----+-----+------+--------+-------+-------+--------+----------+
1 row in set (0.00 sec)

Но это не идентичные операции.

0 голосов
/ 25 марта 2010

Я думаю, что разница заключается в обработке нулевых значений - (независимо от оператора NOT NULL в вашем случае). Может быть, эти разделы руководства могут помочь?

http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html http://dev.mysql.com/doc/refman/5.1/en/logical-operators.html#operator_not

...