读高性能MySQL(第4版)笔记12_查询性能优化(下)

news2025/6/5 17:44:13

1. “快速、精确和实现简单”

1.1. 三者永远只能满足其二,必须舍掉一个

2. 排序优化

2.1. 无论如何排序都是一个成本很高的操作,所以从性能角度考虑,应尽可能避免排序或者尽可能避免对大量数据进行排序

2.2. 文件排序(filesort)

2.2.1. MySQL需要自己进行排序,如果数据量小则在内存中进行,如果数据量大则需要使用磁盘

2.2.2. 完全是在内存中排序不需要任何磁盘文件时也是如此

2.3. 排序算法

2.3.1. 两次传输排序(旧版本使用)

2.3.1.1. 读取行指针和需要排序的字段,对其进行排序,然后再根据排序结果读取所需要的数据行
2.3.1.2. 即需要从数据表中读取两次数据,第二次读取数据的时候,因为是读取排序列进行排序后的所有记录,这会产生大量的随机I/O,所以两次传输排序的成本非常高

2.3.2. 单次传输排序(新版本使用)

2.3.2.1. 先读取查询所需要的所有列,然后再根据给定列进行排序,最后直接返回排序结果
2.3.2.2. 不再需要从数据表中读取两次数据,对于I/O密集型的应用来说,这样做的效率高了很多
2.3.2.3. 只需要一次顺序I/O就可读取所有的数据,而无须任何的随机I/O

2.4. MySQL在进行文件排序时需要使用的临时存储空间可能会比想象的要大得多

2.5. 如果使用utf8mb4字符集,那么MySQL将会为每个字符预留4字节

2.6. 如果查询中有LIMIT的话,LIMIT也会在文件排序之后应用,所以即使需要返回较少的数据,临时表和需要排序的数据量仍然会非常大

3. 将结果返回给客户端

3.1. 执行查询的最后一个阶段是将结果返回给客户端

3.2. MySQL将结果集返回客户端是一个增量且逐步返回的过程

3.2.1. 服务器端无须存储太多的结果,也就不会因为要返回太多结果而消耗太多内存

4. MySQL查询优化器的局限性

4.1. MySQL查询优化器只对少部分查询不适用,而且我们往往可以通过改写查询让MySQL高效地完成工作

4.2. UNION的限制

4.2.1. MySQL无法将限制条件从UNION的外层“下推”到内层,这使得原本能够限制部分返回结果的条件无法应用到内层查询的优化上

4.2.2. 从临时表中取出数据的顺序并不是一定的,所以如果想获得正确的顺序,还需要在最后的LIMIT操作前加上一个全局的ORDER BY操作

4.3. 等值传递

4.3.1. 优化器通过将列表复制到所有相关表中的相应列来“共享”列表

4.4. 并行执行

4.4.1. MySQL无法利用多核特性来并行执行查询

5. 优化特定类型的查询

5.1. 多数优化技巧都和特定的版本有关,所以对于未来MySQL的版本未必适用

5.2. 优化COUNT()查询

5.2.1. COUNT()是一个特殊的函数

5.2.1.1. 可以统计某列的值的数量
5.2.1.2. 可以统计行数

5.2.2. 用COUNT()的时候,这种情况下通配符并不会像我们猜想的那样扩展成所有的列,实际上,它会忽略所有的列而直接统计所有的行数

5.2.2.1. 如果想要知道结果中的行数,应该始终使用COUNT(*),这样可以更清晰地传达意图,避免糟糕的性能表现

5.2.3. 常见的错误之一是当需要统计行数时,在COUNT()函数的括号内指定了列名

5.2.4. 计算精确值非常复杂,而计算近似值则非常简单

5.2.4.1. 可以增加类似Memcached这样的外部缓存系统

5.3. 优化联接查询

5.3.1. 确保ON或者USING子句中的列上有索引

5.3.1.1. 没有用到的索引只会带来额外的负担

5.3.2. 确保任何GROUP BY和ORDER BY中的表达式只涉及一个表中的列,这样MySQL才有可能使用索引来优化这个过程

5.3.3. 当升级MySQL的时候需要注意:联接语法、运算符优先级等其他可能会发生变化的地方

5.3.4. 使用WITH ROLLUP优化GROUP BY

5.3.4.1. 分组查询的一个变种就是要求MySQL对返回的分组结果再做一次超级聚合
5.3.4.2. 在应用程序中做超级聚合是更好的,虽然这需要给客户端返回更多的结果
5.3.4.3. 最好的办法是尽可能地将WITH ROLLUP功能转移到应用程序中处理

5.4. 优化LIMIT和OFFSET子句

5.4.1. 在系统中需要进行分页操作的时候,我们通常会使用LIMIT加上偏移量的办法实现,同时加上合适的ORDER BY子句

5.4.2. 在页面中限制分页的数量

5.4.3. 优化大偏移量的性能

5.4.4. 尽可能地使用索引覆盖扫描,而不是查询所有的行

5.4.5. 将LIMIT查询转换为已知位置的查询,让MySQL通过范围扫描获得对应的结果

5.4.6. OFFSET的问题

5.4.6.1. 会导致MySQL扫描大量不需要的行然后再抛弃掉
5.4.6.2. 可以使用书签记录上次取数据的位置,那么下次就可以直接从该书签记录的位置开始扫描,这样就可以避免使用OFFSET
5.4.6.2.1. 无论翻页到多么靠后,其性能都会很好
5.4.6.3. 冗余表,冗余表只包含主键列和需要做排序的数据列

5.5. 更好的设计

5.5.1. 将具体的页数换成“下一页”按钮

5.5.1.1. 假设每页显示20条记录,那么我们每次查询时都是用LIMIT返回21条记录并只显示20条
5.5.1.2. 如果第21条存在,那么就显示“下一页”按钮,否则就说明没有更多的数据,也就无须显示“下一页”按钮了

5.5.2. 先获取并缓存较多的数据

5.5.2.1. 缓存1000条——然后每次分页都从这个缓存中获取
5.5.2.2. 如果结果集小于1000,就可以在页面上显示所有的分页链接,因为数据都在缓存中,所以这样做不会对性能造成影响
5.5.2.3. 如果结果集大于1000,则可以在页面上设计一个额外的“找到的结果多于1000条”之类的按钮

5.5.3. 比每次生成全部结果集再抛弃不需要的数据的效率高很多

5.6. 优化SQL CALC FOUND ROWS

5.6.1. 在LIMIT语句中加上SQL_CALC_FOUND_ROWS提示(hint),这样就可以获得去掉LIMIT以后满足条件的行数,因此可以作为分页的总数

5.6.2. 加上这个提示以后,不管是否需要,MySQL都会扫描所有满足条件的行,然后再抛弃掉不需要的行,而不是在满足LIMIT的行数后就终止扫描

5.6.3. 该提示的代价可能非常高

5.6.4. 当需要精确结果的时候,再单独使用COUNT(*)来满足需求,这时如果能够使用索引覆盖扫描则通常也会比SQL_CALC_FOUND_ROWS快得多

5.7. 优化UNION查询

5.7.1. 经常需要手工地将WHERE、LIMIT、ORDER BY等子句“下推”到UNION的各个子查询中,以便优化器可以充分利用这些条件进行优化

5.7.2. 除非你确实需要服务器消除重复的行,否则一定要使用UNION ALL

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

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

相关文章

数组和指针笔试题解析之【指针】

目录 🍂笔试题1: 🍂笔试题2: 🍂笔试题3: 🍂笔试题4: 🍂笔试题5: 🍂笔试题6: 🍂笔试题7: 🍂笔试题…

实施主品牌进化战略(一):确立主品牌进化架构

主品牌进化战略,即以主品牌为核心创造、巩固、转化竞争优势应对竞争环境变化,避免衰退,回归增长,让主品牌进化的方法论体系。主品牌进化战略制定要从 4 个方面出发:确立主品牌进化架构、更新和明确主品牌竞争方向、建立…

Java高级-注解

注解 1.介绍2.元注解3.注解的解析4.注解的应用场景 1.介绍 注解 Annotation 就是Java代码里的特殊标记,作用是让其他程序根据注解信息来决定什么是执行该程序注解:注解可以在类上、构造器上、方法上、成员变量上、参数上等位置 自定义注解 /*** 自定…

【产品经理】深入B端SaaS产品设计核心理念

这几年各企业的B端业务都在做SaaS平台,但对SaaS的了解还不是完全全面,对于一些产品的定位以及设计还在探索中 本文讨论“为什么采用SaaS模式”、“SaaS产品有哪些”以及“如何做好SaaS产品设计”三个话题,核心是产品设计,主要从需…

Qt5开发及实例V2.0-第九章-Qt文件及磁盘处理

Qt5开发及实例V2.0-第九章-Qt文件及磁盘处理 第9章 Qt 5文件及磁盘处理9.1 读写文本文件9.1.1 QFile类读写文本9.1.2 QTextStream类读写文本 9.2 读写二进制文件9.3 目录操作与文件系统9.3.1 文件大小及路径获取实例9.3.2 文件系统浏览 9.4 获取文件信息9.5 监视文件和目录变化…

由于数字化转型对集成和扩展性的要求,定制化需求难以满足,百数低代码服务商该如何破局?

当政策、技术环境的日益成熟,数字化转型逐步成为企业发展的必选项,企业数字化转型不再是一道选择题,而是决定其生存发展的必由之路。通过数字化转型升级生产方式、管理模式和组织形式,激发内生动力,成为企业顺应时代变…

Nacos服务列表有服务,但是配置列表不起作用。

目录 bug现场解决思路POM文件启动日志排查完整pom文件nacos配置中心部署流程 想要重新再写一下springcloud alibaba 的组件配置,再另一个服务renren-product引入,nacos的注册发现和配置中心。前面都很顺利但是修改配置中心配置的时候不起作用&#xff01…

Spring Boot实现对超大文件进行异步压缩下载

在Web应用中,文件下载功能是一个常见的需求,特别是当你需要提供用户下载各种类型的文件时。本文将演示如何使用Spring Boot框架来实现一个简单而强大的文件下载功能。我们将创建一个RESTful API,通过该API,用户可以下载问价为ZIP压…

linux下CentOS安装mysql-5.7

linux下安装mysql只需要在root用户下安装,普通用户也能使用 1.检查: 通过以下两条命令查看改系统下是否已存在mysql。 ps ajx | grep mysql ps ajx | grep mariadb通过指令如果只显示如下两条信息,则当前系统下不存在MySQL。 就可以直接进…

蓝牙电话之HFP—电话音频

1 媒体音频: 播放蓝牙音乐的数据,这种音频对质量要求高,数据发送有重传机制,从而以l2cap的数据形式走ACL链路。编码方式有:SBC、AAC、APTX、APTX_HD、LDAC这五种编码方式,最基础的编码方式是SBC&#xff0…

手撕二叉树

前序遍历构建二叉树 二叉树的销毁 二叉树的结点个数 二叉树叶子节点个数 二叉树第k层节点个数 二叉树查找值为x的节点 二叉树前序遍历 二叉树中序遍历 二叉树后序遍历 二叉树的层序遍历 判断二叉树是否是完全二叉树 完整代码 test.c #define _CRT_SECURE_NO_WARNINGS 1#incl…

网络防御--防火墙

拓扑 Cloud 1 作为电脑与ENSP的桥梁 防火墙配置 登录防火墙 配置IP地址及安全区域 添加地址对象 配置策略 1、内网可以访问服务器 结果 2、内网可以访问公网 结果 配置NAT策略 结果

注入之SQLMAP(工具注入)

i sqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL和SQL注入漏洞,其广泛的功能和选项包括数据库指纹,枚举,数据库提权,访问目标文件系统,并在获取操作权限时执行任…

【Java 基础篇】Java多线程编程详解:线程创建、同步、线程池与性能优化

Java是一门强大的编程语言,其中最引人注目的特性之一是多线程支持。多线程允许我们在同一程序中同时执行多个任务,这大大提高了应用程序的性能和响应能力。本文将深入介绍Java线程的基础知识,无论您是初学者还是有一些经验的开发人员&#xf…

Qt5开发及实例V2.0-第八章-Qt模型/视图结构

Qt5开发及实例V2.0-第八章-Qt模型/视图结构 第8章 Qt 5模型/视图结构8.1 概述8.1.1 基本概念8.1.2 【实例】:模型/视图类使用 8.2 模型(Model)8.3 视图(View)8.4 代理(Delegate) 本章相关例程源…

2023.9.19 关于 数据链路层 和 DNS 协议 基本知识

目录 数据链路层 MTU DNS 协议 补充 DHCP协议 数据链路层 基本概念: 考虑相邻两个节点之间的传输(通过 网线 / 光纤 / 无线 直接相连的两个设备)以太网协议 规定了 数据链路层 和 物理层 的内容 IP地址 与 mac地址 的相互配合 IP地址 描…

ardupilot的编译过程

环境 树莓派4b ubuntu20.04 git 2.25.1 python3.8.10 pixhawk2.4.8 下载源码 (已经配置好git环境和ssh) git clone --recurse-submodules gitgithub.com:ArduPilot/ardupilot.gitcd ardupilotgit status使用git status检查是否下载完整 如果不完整&a…

Nuxt 菜鸟入门学习笔记:路由

文章目录 路由 Routing页面 Pages导航 Navigation路由参数 Route Parameters路由中间件 Route Middleware路由验证 Route Validation Nuxt 官网地址: https://nuxt.com/ 路由 Routing Nuxt 的一个核心功能是文件系统路由器。pages/目录下的每个 Vue 文件都会创建一…

hadoop测试环境sqoop使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Sqoop看这篇文章就够了_must contain $conditions in where clause._SoWhat1412的博客-CSDN博客 大数据环境 C:\Windows\System32\drivers\etc 修改ip和hostname的对应关系 1…

将本地项目上传至Github详解

目录 1 前言2 本地代码上传2.1 命令行方法2.2 图形界面法2.3 结果 1 前言 GitHub是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名GitHub 。开发者常常将github作为代码管理平台,方便代码存储、版本…