注意:[]该系列是关于MySQL容易忽略的一些知识点。通过审查和补充,您还可以根据审查和补充来更系统地学习MySQL,以便更轻松地工作。
在开发过程中,需要根据指定字段进行分类以显示结果。
以先前的订单表为例,假设查询“张圣”的所有订单,并为订单价格排序以返回前1,000个订单号和价格。
此顺序表测试的结构是这样:
用户表数据:
上方订单表的UID与用户表的ID关联。
SQL语句可以像这样写:
上面的SQL语句看起来很清楚,但是其执行过程是否理解?让我们了解该语句如何执行以及哪些参数会影响执行。
为避免完整的表扫描,我们需要在UID字段上添加索引。
将UID字段添加到索引后,我们使用命令来查看此语句的执行。
额外字段中的“使用filesort”意味着需要对其进行排序。MySQL将为每个线程分配一个内存以进行排序,称为sort_buffer。
为了解释此SQL查询语句的执行过程,让我们看一下UID索引的示意图。如下所示:
通常,此陈述的执行过程如下:
“排序OID”的动作可以在内存或外部排序中完成,这取决于存储器和参数sort_buffer_size分类所需的。
sort_buffer_size是sort_buffer的mySQL的大小。如果要排序的数据量小于sort_buffer_size,则排序在内存中完成。用于协助分类临时文件。
您可以使用下面描述的方法来确定是否使用临时文件。
通过查看结果来确认此方法,您可以查看是否使用临时文件。
表示分类过程中使用的临时文件数量。您必须很奇怪。我在当前测试中需要0个文件,表明分类可以直接在内存中完成。如果是n,则意味着当无法存储内部存储时,必须使用外部排序。通常使用外部排序算法。可以简要理解,
注意:如果超过需要排序的数据量,则为0,这意味着可以直接在内存中完成排序。
接下来,我将解释上图中其他两个值的含义。
我们的示例表中有99972记录符合UID = 1,并检查了= 99972,表明参与线的数量为99972行。
sort_mode是额外的_ fields。
1. MySQL 4.1之前的相应“原始分类模式”。它显示排序缓冲元组包含排序键和原始表?的ID。分类后,需要将??ID制成板球。该算法也称为原始FileSort算法(返回排序算法);2.对应于相应的OneIT是MySQL 4.1之后引入的“修改分类模式”。排序缓冲区元组包含排序键值和查询所需的列。排序后,数据直接从缓冲元组中获取。这是MySQL 5.7.3.3.3.3.的进一步优化的“包装数据排序模式”。这与上层类型的形式相似,但是其他列(这样)由于VARCHAR类型)紧紧地包装在?中,并且?不是固定长度的编码。
同时,上一个查询语句的返回结果选择 @b- @a为99973。
那么为什么上面的99972不呢?
在这里应该注意的是,为了避免干扰,您可以将internal_tmp_disk_storage_engine设置为myisam。待使用,并且Internet_tmp_disk_storage_engine的默认值是Innodb。如果使用InnoDB引擎,则在从临时表中取出数据时,Innodb_rows_read的值将添加1。
上面的算法仅读取原始表的数据,其余操作是在sort_buffer和临时文件中执行的。但是,如果有很多字段要返回,则此算法存在问题,那么有太多字段可容纳很多字段。放置在sort_buffer中,以便可以同时放置在内存中的行数很小。这将是不好的。因此,如果单行很大,则此方法不够有效。
如果MySQL想到排序的顺序太多,该怎么办?
让我们修改一个参数以使MySQL采用另一种算法。
max_length_for_sort_data是一个在mySQL中专门控制的参数。这意味着,如果单行的长度超过此值,mySQL会认为单行太大,您需要更改算法。
OID和价格的两个字段的总长度为28。我将max_length_for_sort_data设置为16。让我们看看哪些更改已更改计算过程。
新算法放置在sort_buffer的字段中,仅列(即价格字段)和要排序的主要密钥ID。
但是目前,排序的结果是因为价格字段的价值丢失了,无法直接返回。整个执行过程如下所示:
与完整的字段排序流程图相比,RowID对访问测试的主要键索引进行了更多分类,即步骤7。
注意:最终的“结果集”只是一个逻辑概念。实际上,MySQL Server按顺序从Sort_buffer中取出ID,然后在原始表处找到OID和价格的两个字段的结果。存款存储的结果直接返回给客户端。
那么此时将执行什么结果?
首先,图中的usked_rows的值是99972,这表明用于排序的数据为99972行。因为除了此时的分类过程之外,分类过程完成后,原始表的值应根据id.ok获取)。
从Optimizer_Trace的结果来看,您还可以看到另一个信息已更改。
如果MySQL真的担心排序排序太小,则会影响分类效率,然后将使用ROWID排序算法。这样,可以在分类过程中对其进行排序,但是您需要返回原始表以拾取数据。
如果MySQL认为内存足够大,则将优先考虑整个字段排序,并且所需字段的需求将放置在sort_buffer中,以便在排序之后,查询结果将直接从内存中返回,而且无需返回原始表即可拾取数据。
这也反映了MySQL的设计思想:
对于InnoDB表,ROWID排序将需要返回表才能引起更多的磁盘读数,因此不会首选。
MySQL是一个相对较高的成本操作。所有需要排序操作都可以按订单?如果您可以在不进行排序的情况下获得正确的结果,那么系统的消耗将少得多,并且句子的执行时间将变得更短。,并非所有按语句订单都需要对操作进行排序。从上述分析的执行过程中,我们可以看到MySQL需要生成临时表并在临时表上进行排序操作的原因。
如果您可以保证从UID的索引中获取的线,那么根据价格上涨的排序是很自然的,您不再能对您进行排序吗?
因此,我们可以在此公民表上创建UID和价格的合并索引。相应的SQL语句是:
与UID索引相反,让我们看一下该索引的示意图。
在此索引中,我们仍然可以使用树搜索来定位满足UID = 1的第一个记录,并确保其他保证。接下来,在订单1中的“下一个记录”过程中。价格的价值必须有序。
这样,整个查询过程的过程就变成了:
此查询过程不需要临时表或排序。下一步,我们使用结果来确认。
从图可以看出,在额外字段中没有使用filesort,也就是说,无需对其进行排序。而且,(uid,price)组合索引本身是有序的,此查询无需读取所有99972行。只要您找到符合条件的前1,000条记录,就可以退出。换句话说,在我们的示例中,我们只需要扫描1,000次。
再次审查。
额外字段中添加了“使用索引”,这意味着使用盖子索引,并且性能将更快。
当然,这并不是说要涵盖每个查询的索引,声明中涉及的字段必须共同索引。毕竟,该指数仍然具有成本效益。这是需要权衡的决定。
结尾
如果您有任何疑问,请在下面留言。
或注意我的公共帐户“”(),输入”。寻求进一步的帮助。
原始:https://juejin.cn/post/71019497807934221