mysql 通过使用文件排序来选择顺序,不使用索引

标签 mysql indexing temporary filesort

抱歉,帖子太长了,但这真的很奇怪,我快要放弃了。 2 个表:

CREATE TABLE `endu_results` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `base_name` varchar(200) NOT NULL,
 `base_nr` int(11) DEFAULT NULL,
 `base_yob` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `endu_results_206a6355` (`base_name`),
 KEY `endu_results_63df4402` (`base_nr`),
 KEY `base_yob` (`base_yob`)
 ) ENGINE=InnoDB AUTO_INCREMENT=3424028 DEFAULT CHARSET=utf8;enter code here

和第二个:

CREATE TABLE `endu_resultinterest` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `result_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `endu_resultinterest_3b529087` (`result_id`),
  CONSTRAINT `result_id_refs_id_19e24435` FOREIGN KEY (`result_id`) REFERENCES `endu_results` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=48590 DEFAULT CHARSET=utf8;

endu_resultstable 中约有 200 万条记录,而 endu_resultinterest 中则少于 100K。我的查询速度很慢:

explain select base_yob from endu_resultinterest 
inner join endu_results 
on (endu_results.id = endu_resultinterest.result_id) 
order by endu_results.base_yob;

1   SIMPLE  endu_resultinterest index   endu_resultinterest_3b529087    endu_resultinterest_3b529087    4   NULL    47559   Using index; Using temporary; Using filesort

问题是:为什么mysql使用这个索引:endu_resultinterest_3b529087 - 但它应该使用base_yob - 这是请求排序的地方?

为了进一步测试它,我手动创建了 2 个额外的相同表 endu_testresultsendu_testresultintrest 并用一些记录填充了这些表:

CREATE TABLE `endu_testresults` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `base_yob` int(11) DEFAULT NULL,
 `base_name` varchar(200) NOT NULL,
 `base_nr` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
KEY `endu_testresults_a65b2616` (`base_yob`),
KEY `endu_testresults_ba0ab39c` (`base_name`),
KEY `endu_testresults_d75ba04d` (`base_nr`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;

所以我再次解释一下:

explain select base_yob from endu_testresultinterest 
inner join endu_testresults 
on (endu_testresults.id = endu_testresultinterest.result_id) 
order by endu_testresults.base_yob;

惊喜惊喜:

 1  SIMPLE  endu_testresults    index   PRIMARY    endu_testresults_a65b2616    5   NULL    19  Using index

现在使用索引排序列base_yob (endu_testresults_a65b2616)。

为什么在一种情况下使用索引,而在另一种情况下我得到“使用文件排序;使用临时”?大小重要吗?我将尝试将记录从一个复制到另一个,但不使用索引来获取它。 MySql 是 5.6.16

最佳答案

简短回答:因为它更快。

长答案...

你的解释似乎不完整——我希望每条都有两行。

第一个表的大小是第二个表的 20(70?)倍。优化器首先选择较小的表。因此,它最初只完成 1/20 的工作量。后面的排序 (ORDER BY ...) 的工作量比开始时必须执行 20 倍的工作量要少得多。

输出只有 48K 行,对吗?这就是第二个表中有多少行,对吗?

您的测试表没有相同的更大/更小比率,是吗?因此有不同的EXPLAIN

关于mysql 通过使用文件排序来选择顺序,不使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30438318/

相关文章:

MySQL服务器消失了

python - 将索引连同列值从一个数据帧插入到另一个数据帧

mongodb - 为什么 Mongo 提示会使查询运行速度提高 10 倍?

MySQL 执行 "No impact"临时 INSERT 并避免复制锁定

c++ - 引用未命名的临时对象(生命周期)

mysql - 复合键 - 一个外键,另一个自动递增

php - 如何为从数据库查询数据的选择下拉列表设置标题

mysql - 如何给jsreport传参数根据参数生成报表

Mysql - 估计删除索引的时间

java - PreparedStatement 只对数据库进行临时更改还是可以将其永久更改?