MySQL深入——8

Order by语句是如何工作的?

首先我们来创建一个表

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `city` varchar(16) NOT NULL,
  `name` varchar(16) NOT NULL,
  `age` int(11) NOT NULL,
  `addr` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `city` (`city`)
) ENGINE=InnoDB;

全字段排序 

 scelect city, name ,age from t where city="杭州" order by name limit 1000;

为了避免全表扫描,我们需要给city加上一个索引,然后使用explain语句去查询,其中extra这个字段中的“using filesort”表示需要排序。MySQL深入——8_第1张图片

 Mysql对其分配出一块内存用于排序,内存成为sort_buffer,city=杭州找出来后,初始化sort_buffer放入city name id这三个字段,对sort_buffer中的name字段进行快速排序,取出前1000行返回给客户端。

按照name排序,可能在内存当中完成,也可能需要外部排序,这取决于所需内存及其参数sort_buffer_size,当name太大的时候,内存放不下,就得使用外部排序进行,就是Mysql开辟sort_buffer_size的大小。

那么如何判断一个文件是否使用了临时文件呢??

optimizer_trace='enabled=on'

开启优化跟踪,Mysql开启追踪查询优化器的决策过程,记录有关优化器如何选择执行计划的详细信息,information_schema是一个特殊的数据库,这个数据库存储了关于数据库,表,列,索引,权限等方面的信息,允许用户查询和了解数据库的结构和状态。

使用这个查询中number_of_tmp_files表示的是排序过程中使用临时文件数,那么为什么使用了12个临时文件呢,Mysql将其分为12份,每一份单独排序后存在于临时文件中,再将12个有序文件合并成为一个有序的大文件。

如果sort_buffer_size超过了需要排序的数据量大小,number_of_tmp_files的数值就为0,表示可以在内存中进行排序。

否则就需要在外部排序,sort_buffer_size 越小,需要分成的份数越多,number_of_tmp_files就越大。

rowid排序

在全排序当中,是对原表的数据读了一遍,剩下的操作都是在sort_buffer和临时表当中执行的,但是这存在着一个问题,就是当查询的时候要返回很多字段的时候,sort_buffer当中要存放的字段数太多,这样内存当中能同时放下的行数就很少,这样要分为很多个临时文件,排序的时候性能会很差,所以我们来使用rowid排序来解决这种问题。

当Mysql认为排序的单行长度太大的时候会采用另外一种算法即为rowid算法。流程是这样的,初始化sort_buffer确定放入两个字段name 和id。从索引city当中取出满足city=“杭州”的主键id,然后从这个主键id中取出整行,取出id和name存入sort_buffer,然后接着重复从索引city中取出满足条件的主键id,直到不满足为止。

因为只要排序的列name字段和主键id,少了city和age字段的值,不能直接返回了。存的是主键id的顺序,到时候遍历排序结果,取前1000行,并按照id的值到原表当中取出city,name和age三个字段返回客户端。

这样的话需要进行排序的内存就会变小,相应的临时文件也相应的变小了。

比较

Mysql在担心内存不够用的时候会使用第二种算法来进行排序,但是会增加磁盘访问,因为第二次返回值的时候,是从主键当中再次访问原表返回的,这就体现出来Mysql的一个思想:如果内存够就多利用内存,减少磁盘访问。

我们还可以使用覆盖索引和联合索引来解决,其实并不是所有的order by语句都要进行排序操作的,Mysql之所以要生成临时表做排序操作,是因为原来所有的数据都是无序的,但是如果它天然就是按照name递增排序的呢?

覆盖索引是指,索引上的信息足够满足查询请求,不需要再回到主键索引上去取数据。

按照这个概念,我们创建一个name ,city ,age 的联合索引,因为name是递增天然的,我们就不需要排序直接返回了,直到city不为杭州的时候结束。使用这个的时候,我们可以看extra下面的字段显示是不是需要排序来决定。因为不是每一个查询都能使用上覆盖索引,就需要把所有的字段都建立起联合索引,因为索引的维护也是有代价的,所以这是一个需要权衡的决定。

你可能感兴趣的:(Mysql数据库基础及深入理解,mysql,sql,数据库)