Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当我在字段列表中选择非索引字段时,为什么MySQL停止使用连接索引_Mysql_Performance_Indexing - Fatal编程技术网

当我在字段列表中选择非索引字段时,为什么MySQL停止使用连接索引

当我在字段列表中选择非索引字段时,为什么MySQL停止使用连接索引,mysql,performance,indexing,Mysql,Performance,Indexing,我有以下两个表格: CREATE TABLE `temporal_expressions` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dated_obj_type` varchar(255) DEFAULT NULL, `dated_obj_id` int(11) DEFAULT NULL, `start_date` datetime DEFAULT NULL, `end_date` datetime DEFAULT NULL, `start_time`

我有以下两个表格:

CREATE TABLE `temporal_expressions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dated_obj_type` varchar(255) DEFAULT NULL,
`dated_obj_id` int(11) DEFAULT NULL,
`start_date` datetime DEFAULT NULL,
`end_date` datetime DEFAULT NULL,
`start_time` int(11) DEFAULT NULL,
`end_time` int(11) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`lock_version` int(11) NOT NULL DEFAULT '0',
`wday` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `te_search` (`dated_obj_type`,`dated_obj_id`,`start_date`,`end_date`),
KEY `te_calendar`   (`dated_obj_type`,`dated_obj_id`,`start_date`,`end_date`,`start_time`,`end_time`),
KEY `te_search_wday` (`dated_obj_type`,`dated_obj_id`,`start_date`,`end_date`,`wday`),
KEY `te_calendar_wday` (`dated_obj_type`,`dated_obj_id`,`start_date`,`end_date`,`start_time`,`end_time`,`wday`),
KEY `te_index` (`wday`,`dated_obj_type`,`start_date`,`end_date`,`start_time`,`end_time`,`dated_obj_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8162445 DEFAULT CHARSET=latin1

CREATE TABLE `asset_blocks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`block_type` int(11) DEFAULT '0',
`spaces_left` int(11) DEFAULT NULL,
`provider_note` varchar(255) DEFAULT NULL,
`extra_data` text,
`lock_version` int(11) DEFAULT '0',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`type` varchar(255) DEFAULT NULL,
`service_provider_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `type` (`type`,`id`),
KEY `service_provider_id` (`service_provider_id`,`type`,`id`),
) ENGINE=InnoDB AUTO_INCREMENT=516867 DEFAULT CHARSET=latin1
如果我在这个查询上运行explain(注意,我只是从时态表达式中选择te_calendar_wday索引中的字段),它会像预期的那样使用连接索引

EXPLAIN SELECT asset_blocks.*, temporal_expressions.id,
temporal_expressions.dated_obj_type, temporal_expressions.dated_obj_id,
temporal_expressions.start_date, temporal_expressions.end_date,
temporal_expressions.start_time
FROM `asset_blocks`
LEFT OUTER JOIN `temporal_expressions`
ON `temporal_expressions`.dated_obj_id = `asset_blocks`.id 
  AND `temporal_expressions`.dated_obj_type = 'AssetBlock'
WHERE ( temporal_expressions.start_date <= '2010-11-25' 
AND temporal_expressions.end_date >= '2010-11-01'
AND temporal_expressions.start_time < 1000 AND temporal_expressions.end_time > 1200 
AND temporal_expressions.wday IN (1,2,3,4,5,6) 
AND asset_blocks.id IN (1,2,3,4,5,6,7,8,9) )

1 SIMPLE temporal_expressions range    te_search,te_calendar,te_search_wday,te_calendar_wday,te_index te_calendar_wday 272 NULL 9 Using where; Using index
1 SIMPLE asset_blocks eq_ref PRIMARY PRIMARY 4 lb_production.temporal_expressions.dated_obj_id 1
EXPLAIN SELECT asset_blocks.*,temporal_expressions.id,
时间表达式。日期对象类型,时间表达式。日期对象id,
时态表达式。开始日期,时态表达式。结束日期,
时间表达式。开始时间
来自“资产”区块`
左外连接'temporal_表达式`
关于'temporal'u expressions`.dated\u obj\u id='asset\u blocks`.id
和`时态表达式'。日期对象类型='AssetBlock'
其中(temporal_expressions.start_date='2010-11-01'
时间表达式。开始时间<1000,时间表达式。结束时间>1200
(1,2,3,4,5,6)中的wday
和(1,2,3,4,5,6,7,8,9)中的资产id
1简单的时态表达式范围为te_搜索、te_日历、te_搜索、te_日历、te_索引te_日历、272 NULL 9,使用where;使用索引
1简单资产块eq_ref PRIMARY 4磅生产时间表达式日期对象id 1
但是,如果我运行此查询(请注意,我已将一个非索引字段添加到字段列表),它将不再使用索引(它使用联接缓冲区)。这是故意的还是我遗漏了什么

EXPLAIN SELECT asset_blocks.*, temporal_expressions.id,
temporal_expressions.dated_obj_type, temporal_expressions.dated_obj_id,
temporal_expressions.start_date, temporal_expressions.end_date,
temporal_expressions.start_time, temporal_expressions.created_at
FROM `asset_blocks`
LEFT OUTER JOIN `temporal_expressions`
ON `temporal_expressions`.dated_obj_id = `asset_blocks`.id 
  AND `temporal_expressions`.dated_obj_type = 'AssetBlock'
WHERE ( temporal_expressions.start_date <= '2010-11-25' 
AND temporal_expressions.end_date >= '2010-11-01'
AND temporal_expressions.start_time < 1000 AND temporal_expressions.end_time > 1200 
AND temporal_expressions.wday IN (1,2,3,4,5,6) 
AND asset_blocks.id IN (1,2,3,4,5,6,7,8,9) )


1 SIMPLE asset_blocks range PRIMARY PRIMARY 4 NULL 9 Using where
1 SIMPLE temporal_expressions range te_search,te_calendar,te_search_wday,te_calendar_wday,new_te_index te_search 272 NULL 9 Using where; Using join buffer
EXPLAIN SELECT asset_blocks.*,temporal_expressions.id,
时间表达式。日期对象类型,时间表达式。日期对象id,
时态表达式。开始日期,时态表达式。结束日期,
时间表达式。开始时间,时间表达式。创建时间
来自“资产”区块`
左外连接'temporal_表达式`
关于'temporal'u expressions`.dated\u obj\u id='asset\u blocks`.id
和`时态表达式'。日期对象类型='AssetBlock'
其中(temporal_expressions.start_date='2010-11-01'
时间表达式。开始时间<1000,时间表达式。结束时间>1200
(1,2,3,4,5,6)中的wday
和(1,2,3,4,5,6,7,8,9)中的资产id
1简单资源块范围主4空9使用where
1个简单的时间表达式范围为te_search、te_calendar、te_search_wday、te_calendar_wday、new_Teu索引Teu search 272 NULL 9,使用where;使用连接缓冲区

我不能确定这里的情况是否如此,但是:

如果只选择索引字段,MySQL可以在索引之外回答整个查询,甚至不加载表数据文件

如果选择未编制索引的字段,则必须加载表数据


在制定执行计划时,在某些情况下(请参阅注释),MySQL决定执行完整的表扫描,尽管存在索引。这是因为盲目地读取所有数据要比查找索引中的每个条目然后读取数据快得多。

好的,我删除了关于50%的陈述,因为我查找了它,上面说:查询每个表索引,并使用最佳索引,除非优化器认为使用表扫描更有效。曾经,根据最佳索引是否跨越表的30%以上使用扫描,但固定百分比不再决定使用索引还是扫描。优化器现在更加复杂,它的估计基于其他因素,如表大小、行数和I/O块大小。