MySQL之查询性能优化(七)

news2024/11/16 11:53:21

查询性能优化

在这里插入图片描述

排序优化

无论如何排序都是一个成本很高的操作,所以从性能角度考虑,应尽可能避免排序或者尽可能避免对大量数据进行排序。前面已经提到了,当不能使用索引生成排序结果的时候,MySQL需要自己进行排序,如果数据量小则在内存种进行,如果数据量大则需要使用磁盘,不过MySQL将这个过程统一称为文件排序(filesort),即使完全是内存排序不需要任何磁盘文件时也是如此。如果需要排序的数据量小于"排序缓冲区",MySQL使用内存进行"快速排序"操作。如果内存不够排序,那么MySQL会先将数据分块,对每个独立的块使用"快速排序"进行排序,并将各个块的排序结果存放在磁盘上,然后将各个排好序的快进行合并(merge),最后返回排序结果。MySQL有如下两种排序算法:

  • 1.两次传输排序(旧版本使用)(也称双路排序)
    读取行指针和需要排序的字段,对其进行排序,然后再根据排序结果读取所需要的数据行。这需要进行两次数据传输,即需要从数据表中读取两次数据,第二次读取数据的时候,因为是读取排序列进行排序后的所有记录,这回产生大量的随机IO,所以两次数据传输的成本非常高。当使用的是MyISAM表的时候,成本可能会更高,因为MyISAM使用系统调用进行数据的读取(MyISAM非常依赖操作系统对数据的缓存)。不过这样做的优点是,在排序的时候存储尽可能少的数据,这就让"排序缓冲区"(内存)中可能容纳尽可能多的行数进行排序
  • 2.单次传输排序(新版本使用)
    先读取查询所需要的所有列,然后再根据给定列进行排序,最后直接返回排序结果。这个算法只在MySQL4.1和后续更新的版本中引入。因为不再需要从数据表中读取两次数据,对于IO密集型的应用,这样做的效率高了很多。另外,相比两次传输排序,这个算法只需要一次顺序IO读取所有的数据,而无须任何的随机IO.缺点是,如果需要返回的列非常多、非常大、会额外占用大量的空间,而这些列对排序操作本身来说是没有任何作用的。因为单条排序记录很大,所以可能会有更多的排序块需要合并.

很难说哪个算法效率更高,两种算法都有各自最好和最糟的场景。当查询需要所有列的总长度不超过参数max_length_for_sort_data时,MySQL使用"单次传输排序",,可以通过调整这个参数来影响MySQL排序算法的选择

MySQL在进行文件排序的时候需要使用的临时存储空间可能会比想象的要大得多。原因在于MySQL在排序时,对每一个排序记录都会分配一足够长的定长空间来存放。这个定长空间必须足够长以容纳其中最长的字符串,例如,如果是VARCHAR列则需要分配其完整长度;如果使用UTF-8字符集,那么MySQL将会为每个字符预留两个字节。曾经在一个库表结构设计不合理的案例中看到,排序消耗的临时空间比磁盘上的原表要大很多倍。
在关联查询的时候如果需要排序,MySQL会分两种情况来处理这样的文件排序。如果ORDER BY 子句中的所有列都来自关联的第一个表,那么MysQL在关联处理第一个表的时候就进行文件排序。如果是这样,那么在MySQL的EXPLAIN结果中可以看到Extra字段会有"Using filesort".除此之外的所有情况,MySQL都会先将关联的结果存放到一个临时表中,然后在所有的关联都结束后,再进行文件排序。这种情况下,在MySQL的EXPLAIN结果的Extra字段可以看到"Using temporary;Using filesort",如果查询中有LIMIT的话,LIMIT也会在排序之后应用,所以即使需要返回较少的数据,临时表和需要排序的数据量仍然会非常大。MySQL5.6在这里做了很多重要的改进。当只需要返回部分排序结果的时候,例如使用了LIMIT子句,MySQL不再对所有的结果进行排序,而是根据实际情况,选择抛弃不满足条件的结果,然后再进行排序

查询执行引擎

在解析和优化阶段,MySQL将生成查询对应的执行计划,MySQL的查询执行引擎根据这个执行计划来完成整个查询。这里执行计划是一个数据结构,而不是和其他的关系型数据库那样生成对应的字节码。相对于查询优化阶段,查询执行阶段不是那么复杂:MySQL只是简单地根据执行计划给出的指令逐步执行。在根据执行计划逐步执行的过程中,有大量的操作需要通过调用存储引擎实现的接口来完成,这些接口也就是我们成为"handler API"的接口。查询中的每一个表由一个handler的实例表示。实际上,MySQL在优化阶段就为每个表创建了一个handler实例,优化器根据这些实例的接口可以获取表的相关信息,包括表的所有列名、索引统计信息,等等。
存储引擎接口有着非常丰富的功能,但是底层接口却只有几十个,这些接口像"搭积木"一样能够完成查询的大部分操作。例如,有一个查询某个索引的第一行的解耦,再有一个查询某个索引条目的下一个条目的功能,有了这两个功能我们就可以完成全索引扫描的操作了。这种简单的接口模式,让MySQL的存储引擎插件式架构成为可能,但是正如前面的讨论,也给优化器带来了一定的限制。
并不是所有的操作都有handler完成。例如,当MySQL需要进行表锁的时候,handler可能会实现自己的级别的、更细粒度的锁,如InnoDB就实现了自己的行基本锁,但这并不能代替服务器层的表锁。如果是所有存储引擎共有的特性则由服务器层实现,比如时间和日期函数、视图、触发器等等。
为了执行查询,MySQL只需要重复执行计划中的各个操作,知道完成所有的数据查询。

返回结果给客户端

查询执行的最后一个阶段是将结果返回给客户端。即使查询不需要返回结果集给客户端,MySQL仍然会返回这个查询的一些信息,如该查询影响到的行数。如果查询可以被缓存,那么MySQL在这个阶段也会将结果存放到查询缓存中。MySQL将结果集返回客户端是一个增量、逐步返回的过程。例如,我们回头看看前面的关联操作,一旦服务器处理完成最后一个关联表,开始生成第一条结果时,MySQL就可以开始向客户端逐步返回结果集了。这样处理有两个好处:服务器端无须存储太多的结果,也就不会因为要返回太多结果而消耗太多内存。另外,这样的处理也让MySQL客户端第一时间获得返回的结果。结果集中的每一行会以一个满足MySQL客户端/服务器通信协议的封包发送,再通过TCP协议进行传输,在TCP传输的过程中,可能对MySQL的风暴进行缓存然后批量传输。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1809539.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02-JAVA面向对象编程

一、面向对象编程 1、面向过程编程思想(Process Oritented Programming) 将实现一个功能的一组指令组合在一起,成为一个函数。这个函数就能实现这一个功能,是对功能实现的一种抽象。通过这种抽象方式,将代码实现复用。…

Jmeter分布式、测试报告、并发数计算、插件添加方式、常用图表

Jmeter分布式 应用场景 当单个测试机无法模拟用户要求的业务场景时,可以使用多台测试机进行模拟,就是Jmeter的分布 式测试。 Jmeter分布式执行原理 Jmeter分布测试时,选择其中一台作为控制机(Controller)&#xff0c…

Python框架scrapy有什么天赋异禀

Scrapy框架与一般的爬虫代码之间有几个显著的区别,这些差异主要体现在设计模式、代码结构、执行效率以及可扩展性等方面。下面是一些关键的不同点: 结构化与模块化: Scrapy:提供了高度结构化的框架,包括定义好的Spider…

【InternLM实战营第二期笔记】07:OpenCompass :是骡子是马,拉出来溜溜

文章目录 课程实操 课程 评测的意义是什么呢?我最近也在想。看到这节开头的内容后忽然有个顿悟:如果大模型最终也会变成一种基础工具(类比软件),稳定或可预期的效果需要先于用户感知构建出来,评测 case 就…

jquery.datetimepicker无法添加清除按钮的问题

项目场景: 自从决定用现有新技术实现CRM老项目起,就开始了我的折腾之路,最近一直在折腾前端页面,不像后端Java,写的有问题运行会报错,大多数报错一搜就能找到解决方案,前端这个倒好&#xff0c…

《TCP/IP网络编程》(第十四章)多播与广播

当需要向多个用户发送多媒体信息时,如果使用TCP套接字,则需要维护与用户数量相等的套接字;如果使用之前学习的UDP,传输次数也需要和用户数量相同。 所以为了解决这些问题,可以采用多播和广播技术,这样只需要…

storage存储模块-vuex持久化处理

1:存储登录用户信息到vuex中 在store文件夹下面,创建modules文件夹在文件夹下创建user.js文件 user.js文件 const state {userInfo: {userId: ,token: } } const mutations {setUserInfo (state, obj) {console.info(obj)state.userInfo.userId obj…

字符串常量简单介绍

C/C内存四区介绍 如前文所示,字符串常量存储在静态存储区的字符串常量区,这样做的好处是 当程序使用到多个相同的字符串常量时,实际上都是使用的同一份,这样就可以减小程序的体积。注意字符串常量是只读的不能被修改。 如图所示&…

通用信息提取数据预处理

train_data./datasets/duuie output_folder./datasets/duuie_pre ignore_datasets["DUEE", "DUEE_FIN_LITE"] schema_folder./datasets/seen_schema # 对CCKS2022 竞赛数据进行预处理 import shutil # shutil.copytree(train_data,output_folder) impor…

「网络原理」三次握手四次挥手

🎇个人主页:Ice_Sugar_7 🎇所属专栏:计网 🎇欢迎点赞收藏加关注哦! 三次握手&四次挥手 🍉连接管理🍌三次握手🍌意义🍌四次挥手🍌TCP 状态转换…

电路防护-贴片陶瓷气体放电管

贴片陶瓷气体放电管 GDT工作原理GDT主要特性参数典型电路压敏电阻与 TVS 管的区别 GDT工作原理 陶瓷气体放电管是一种电子器件,其工作原理基于气体放电现象。这种管子的内部填充了一种特定的气体,通常是氖气或氩气。当管子两端施加足够的电压时&#xf…

vue3-使用富文本编辑器-wangEditor-文章发表1

最近在搞项目:我们组内几位成员正在搞一个网站搭建,以后更新会比较缓慢 引言:如果要网站要用的富文本编辑器的话,这边推荐用wangEditor 官网地址传送 : wangEditorhttps://www.wangeditor.com/ 我现在还在扩展我的写文章用的富文本编辑器 现在我将简单介绍一下其基本使用方…

Python的return和yield,哪个是你的菜?

目录 1、return基础介绍 📚 1.1 return用途:数据返回 1.2 return执行:函数终止 1.3 return深入:无返回值情况 2、yield核心概念 🍇 2.1 yield与迭代器 2.2 生成器函数构建 2.3 yield的暂停与续行特性 3、retur…

在 Android App 里使用 C 代码 - NDK

原生开发套件 (NDK) 是一套工具,使能够在 Android 应用中使用 C 和 C 代码,并提供众多平台库,可使用这些平台库管理原生 activity 和访问实体设备组件,例如传感器和触控输入。 NDK 可能不适合大多数 Android 编程初学者&#xff…

使用 Jetpack Compose 实现 Android 偏好设置分类界面

使用 Jetpack Compose 实现 Android 偏好设置分类界面 Jetpack Compose 提供了一种现代且声明式的构建 Android 用户界面的方法,使其非常适合实现偏好设置分类界面。以下是如何实现的逐步指南: 1. 定义数据模型: 首先,定义数据模型来表示…

集成学习模型对比优化—银行业务

1.Data Understanding 2.Data Exploration 3.Data Preparation 4.Training Models 5.Optimization Model 集成学习模型对比优化—银行业务 1.Data Understanding import pandas as pd from matplotlib import pyplot as plt import seaborn as sns df pd.read_csv(&quo…

表的设计与查询

目录 一、表的设计 1.第一范式(一对一) 定义: 示例: 2.第二范式(一对多) 定义: 要求: 示例: 3.第三范式(多对多) 定义: 要求…

Bio-Info每日一题:Rosalind-06-Counting Point Mutations

🎉 进入生物信息学的世界,与Rosalind一起探索吧!🧬 Rosalind是一个在线平台,专为学习和实践生物信息学而设计。该平台提供了一系列循序渐进的编程挑战,帮助用户从基础到高级掌握生物信息学知识。无论你是初…

每日算法——归并排序

什么是归并排序 归并排序是一种分治算法。它将数组不断地分成两半,对每一半进行排序,然后再将排序好的两半合并起来。通过不断重复这个过程,最终得到完全排序的数组。 归并排序的注意点: 空间复杂度:归并排序需要额…

javascript动态绑定

介绍 先来看看ai的解释 动态绑定机制是面向对象编程中的一个核心概念,特别是在Java这样的语言中。它允许在运行时根据对象的实际类型来决定调用哪个方法,而不是在编译时。这是多态性的关键特性之一。 在Java中,动态绑定是通过方法调用和方法…