这⾥需要注意的是,为了避免对结论造成⼲扰,我把internal_tmp_disk_storage_engine设置成MyISAM。否则,select @b-
@a的结果会显示为4001。
这是因为查询OPTIMIZER_TRACE这个表时,需要⽤到临时表,⽽internal_tmp_disk_storage_engine的默认值是InnoDB。如
果使⽤的是InnoDB引擎的话,把数据从临时表取出来的时候,会让Innodb_rows_read的值加1。
rowid排序
在上⾯这个算法过程⾥⾯,只对原表的数据读了⼀遍,剩下的操作都是在sort_buffer和临时⽂件中执⾏的。但这个算法有⼀个
问题,就是如果查询要返回的字段很多的话,那么sort_buffer⾥⾯要放的字段数太多,这样内存⾥能够同时放下的⾏数很少,
要分成很多个临时⽂件,排序的性能会很差。
所以如果单⾏很⼤,这个⽅法效率不够好。
那么,如果MySQL认为排序的单⾏⻓度太⼤会怎么做呢?
接下来,我来修改⼀个参数,让MySQL采⽤另外⼀种算法。
max_length_for_sort_data,是MySQL中专⻔控制⽤于排序的⾏数据的⻓度的⼀个参数。它的意思是,如果单⾏的⻓度超过这
个值,MySQL就认为单⾏太⼤,要换⼀个算法。
city、name、age 这三个字段的定义总⻓度是36,我把max_length_for_sort_data设置为16,我们再来看看计算过程有什么改
变。
新的算法放⼊sort_buffer的字段,只有要排序的列(即name字段)和主键id。
但这时,排序的结果就因为少了city和age字段的值,不能直接返回了,整个执⾏流程就变成如下所示的样⼦:
1. 初始化sort_buffer,确定放⼊两个字段,即name和id;
2. 从索引city找到第⼀个满⾜city='杭州’条件的主键id,也就是图中的ID_X;
3. 到主键id索引取出整⾏,取name、id这两个字段,存⼊sort_buffer中;
4. 从索引city取下⼀个记录的主键id;
5. 重复步骤3、4直到不满⾜city='杭州’条件为⽌,也就是图中的ID_Y;
6. 对sort_buffer中的数据按照字段name进⾏排序;
7. 遍历排序结果,取前1000⾏,并按照id的值回到原表中取出city、name和age三个字段返回给客户端。
这个执⾏流程的示意图如下,我把它称为rowid排序。