繁体   English   中英

MYSQL - NOT vs var = false

[英]MYSQL - NOT vs var=false

在过去的几天里,我发现了一些奇怪的优化我的查询。 我有一个简单的查询,它具有以下特点:

   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 ...

结果相同! 当我将其更改为“cancelled = 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 ;

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

它的描述如下:

“字段的不同值是多少。它是0-1的数字,但您也可以将其视为百分比。值1或100%表示字段中的每个值都是唯一的”

重要的是要考虑因为:

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

简单明了:

如果您正在查找的数据具有或多或少20%的相同值(例如,取消了您的表的40%),则只需执行表扫描即可。

编辑:

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

看看这个:

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

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'

因此,在第一种情况下,似乎将trueint ,然后在可查找谓词中使用,而在第二种情况下,列值是隐式转换的。 隐式演员通常会使条件无法实现。

使用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的索引视为可能的选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM