MYSQL - NOT vs var = false

时间:2011-11-07 10:08:25

标签: mysql sql

在过去的几天里,我注意到了一些奇怪的优化我的查询。 我有一个简单的查询,它可以执行以下操作:

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

我注意到mysql没有使用任何索引,所以我开始做一些实验。 无意中我将“NOT cancel”替换为“cancelled = false”,然后,Mysql开始使用“cancelled”作为索引。 之后我尝试使用相反的方法:

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

结果相同!当我将其更改为“cancellation = true”时,索引会再次起作用。

我的问题是:怎么样?!是不是使用“NOT”的“优雅”方式?无论如何,我没想到它会有任何不同。

我正在使用 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 个答案:

答案 0 :(得分:3)

即使它使用索引,索引(信不信由你)可能会使您的查询变慢。这有点奇怪,但它与索引选择性有关。它通常以boolean类型的列显示。

它被描述为:

  

"字段的不同值如何。它是0-1的数字,   虽然你也可以把它想象成一个百分比。值为1或   100%,表示该字段中的每个值都是唯一的"

考虑因为这一点非常重要:

  

" MySQL有一个基于成本的优化器。这意味着MySQL计算   执行查询的不同方式的成本,然后选择   最便宜的一个。那么,计算成本是一门不精确的科学。所以   估计是有的,有时估计是错误的。"

简单明了:

如果您查找的数据或多或少有相同价值的20%(例如,已取消的数据占您表格的40%)那么,只需进行一次表格扫描即可。< / p>

修改

关于你的问题,EXPLAIN告诉你MySQL正在使用索引。但是,它可能不太好,注意优化是否更好的唯一方法是测试性能。另外,考虑INSERT,UPDATE和DELETE操作的costo以保持该索引。使用和不使用索引进行一些分析。

看看这个:

答案 1 :(得分:2)

我不熟悉MYSQL,但从逻辑上思考,我理解如下:
索引就像电话簿,当你搜索“科恩”时,你可以马上得到它 但如果您正在寻找 NOT “Cohen”,则必须检查每个条目,并检查它是否与“Cohen”不同。
因此,当您正在寻找特定值时,它看起来就是它。当您使用 NOT 时,它会查找适合tinyint(1)内的任何其他值(据我所知,它不仅仅是10,是吗? ?)。

答案 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=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上的索引视为可能的选项。