我有一张非常大的桌子(425+百万行)。
CREATE TABLE `DummyTab` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(48) NOT NULL,
`BeginDate` datetime DEFAULT NULL,
`EndDate` datetime NOT NULL,
......
......
KEY `BeginDate_index` (`dBegDate`),
KEY `id` (`id`),
) ENGINE=MyISAM
选择是根据“ BeginDate”和此表上的其他条件完成的
select * from DummyTab where Name like "%dummyname%" and BeginDate>= 20141101
现在,在这种情况下,仅提供datetime过期的日期字段(尽管它将用作2014-11-01 00:00:00)。
问题是,即使在这种情况下仅提供日期,优化器是否也会正确使用DATETIME索引?还是应该在“日期”字段上设置索引以更有效地使用而不是“日期时间”
是的,BeginDate_index
当使用仅DATE过滤器指定查询时,仍可以使用该查询(也对施加其他条件Name
也不会取消索引的资格)。
如果查看此SqlFiddle随机数据,并Execution plan
在底部展开,则会看到类似以下内容的内容:
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS FILTERED EXTRA
1 SIMPLE DummyTab range BeginDate_index BeginDate_index 6 17190 100 Using index condition; Using where
(具体KEY
是BeginDate_index
)。但是请注意,不能保证使用索引,例如,如果您针对更广泛的日期条件执行相同的查询,则可能会使用不同的计划(例如,如果您对使用相同的小提琴> 20140101
,BeginDate_index
则不再使用它,因为它没有提供足够的选择性)。
编辑,回复:关于精确性的注释
由于BeginDate
是日期时间,因此文字20141101
也会被转换为日期时间(一次)。从文档:
如果参数之一是TIMESTAMP或DATETIME列,而另一个参数是常量,则在执行比较之前,该常量将转换为时间戳。
再次,是的,根据您的最后一段,过滤器中的文字BeginDate >= 20141101
将转换为确切的日期时间20141101000000
(2014-11-01 00:00:00
),并将考虑任何符合条件的索引(但同样,永远不能保证)。
不能使用索引的一个常见问题是,因为过滤器谓词不可保留,是因为将函数应用于过滤器中的列,因为引擎将需要对查询中所有其余行求值。这里有一些例子。
因此,稍微修改一下示例,以下查询会执行相同的操作,但是第二个查询要慢得多。该查询是可查询的:
SELECT * FROM DummyTab
WHERE BeginDate < 20140101; -- Good
而这不是:
SELECT * FROM DummyTab
WHERE YEAR(BeginDate) < 2014; -- Bad
在这里更新了SqlFiddle-再次查看Execution Plans
底部的,以了解不同之处。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句