在过去的几天里,我注意到了一些奇怪的优化我的查询。 我有一个简单的查询,它可以执行以下操作:
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 ;
答案 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)
内的任何其他值(据我所知,它不仅仅是1
或0
,是吗? ?)。
答案 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
上的索引视为可能的选项。