为什么MySQL不使用索引?

为什么MySQL不使用索引?,mysql,indexing,Mysql,Indexing,我有一张桌子: CREATE TABLE `ais`.`last_location` ( `timestamp` timestamp NOT NULL default '0000-00-00 00:00:00', `message_type` tinyint(4) NOT NULL default '0', `repeat_indicator` tinyint(4) NOT NULL default '0', `mmsi` int(11) NOT NULL default '0

我有一张桌子:

CREATE TABLE  `ais`.`last_location` (
  `timestamp` timestamp NOT NULL default '0000-00-00 00:00:00',
  `message_type` tinyint(4) NOT NULL default '0',
  `repeat_indicator` tinyint(4) NOT NULL default '0',
  `mmsi` int(11) NOT NULL default '0',
  `navigation_status` tinyint(4) NOT NULL default '0',
  `rot` tinyint(4) NOT NULL default '0',
  `sog` smallint(6) NOT NULL default '0',
  `position_accuracy` tinyint(4) NOT NULL default '0',
  `longitude` int(11) NOT NULL default '0',
  `latitude` int(11) NOT NULL default '0',
  `cog` smallint(6) NOT NULL default '0',
  `hdg` smallint(6) NOT NULL default '0',
  `time_stamp` tinyint(4) NOT NULL default '0',
  `maneuver_indicator` tinyint(4) NOT NULL default '0',
  `spare` tinyint(4) NOT NULL default '0',
  `raim_flag` tinyint(4) NOT NULL default '0',
  `sotdma_sync_state` tinyint(4) NOT NULL default '0',
  `sotdma_slot_timeout` tinyint(4) NOT NULL default '0',
  `sotdma_slot_offset` smallint(6) NOT NULL default '0',
  PRIMARY KEY  USING BTREE (`mmsi`),
  KEY `Index_2` (`timestamp`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"
我会向大家解释:

EXPLAIN SELECT * 
FROM last_location 
WHERE `timestamp` BETWEEN '2013-01-01 12:00:00' AND '2013-06-03 11:30:00'

1, 'SIMPLE', 'last_location', 'range', 'Index_2', 'Index_2', '4', '', 83, 'Using where'

EXPLAIN SELECT * 
FROM last_location 
WHERE `timestamp` BETWEEN '2013-01-01 12:00:00' AND '2013-06-03 11:40:00'

1, 'SIMPLE', 'last_location', 'ALL', 'Index_2', '', '', '', 478, 'Using where'

谁能告诉我搜索到11:30和11:40的区别?使用11:30时,我认为一切都正常?但是当使用11:40时,它不再使用索引了

如果统计数据表明您将访问整个表以获取匹配的行,则查询计划人员保留忽略索引的权利


原因是,在筛选所需行的同时逐个顺序读取磁盘页比按索引指示的顺序在磁盘页上来回跳转要便宜。

索引扫描每个记录需要更多的I/O(因为它需要在嵌套循环中访问表本身,这通常是随机访问I/O)但允许使用较少的记录(仅限于满足可搜索条件的记录)

表扫描不可避免地扫描整个表,但每个记录占用的I/O要少得多(它是对一个
.MYD
文件的顺序扫描)

MySQL的优化器意识到这一点,并可能根据可搜索条件的选择性选择一条或另一条访问路径:选择性越高的条件可能会从索引扫描中受益,选择性越低的条件在全表扫描中效率越高

这就是你所观察到的

请注意,优化器的解决方案可能效率低下,特别是如果您有一些特定的数据分布、I/O子系统布局等。您可能会强制执行索引扫描:

SELECT  *
FROM    last_location FORCE INDEX (Index_2)
WHERE   `timestamp` BETWEEN '2013-01-01 12:00:00' AND '2013-06-03 11:40:00'

如果您认为索引更有效。

mysql可能会根据表中的统计数据发现,在这种情况下不值得使用索引。执行时间是否存在显著差异?表中有多少行可能存在重复?使用索引获取需要00213秒,而不使用索引的查询需要00801秒。此时表中有478行(请参见第二个解释)。我想我理解不同的行为,MySQL只是决定索引是否值得使用。我的问题太快了,数据库现在已经满了,索引现在一直在使用(就我所见)。结论是MySQL正在自我优化,结果索引没有被少量行使用。