11、Mysql高级之SQL优化

news2024/12/27 22:53:37

11、Mysql高级之SQL优化

文章目录

  • 11、Mysql高级之SQL优化
  • 0 SQL优化
    • 1 大批量插入数据
    • 2 优化insert语句
    • 3 优化order by语句
      • 3.1 环境准备
      • 3.2 两种排序方式
      • 3.3 Filesort 的优化
    • 4 优化group by 语句
    • 5 优化嵌套查询
    • 6 优化OR条件
    • 7 优化分页查询
      • 7.1 优化思路一
      • 7.2 优化思路二
    • 8 使用SQL提示
      • 8.1 USE INDEX
      • 8.2 IGNORE INDEX
      • 8.3 FORCE INDEX
    • 7 优化分页查询
      • 7.1 优化思路一
      • 7.2 优化思路二
    • 8 使用SQL提示
      • 8.1 USE INDEX
      • 8.2 IGNORE INDEX
      • 8.3 FORCE INDEX

0 SQL优化

1 大批量插入数据

环境准备 :

CREATE TABLE `tb_user_2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL,
  `password` varchar(96) NOT NULL,
  `name` varchar(45) NOT NULL,
  `birthday` datetime DEFAULT NULL,
  `sex` char(1) DEFAULT NULL,
  `email` varchar(45) DEFAULT NULL,
  `phone` varchar(45) DEFAULT NULL,
  `qq` varchar(32) DEFAULT NULL,
  `status` varchar(32) NOT NULL COMMENT '用户状态',
  `create_time` datetime NOT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_user_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

当使用load 命令导入数据的时候,适当的设置可以提高导入的效率。

在这里插入图片描述

对于 InnoDB 类型的表,有以下几种方式可以提高导入的效率:

1) 主键顺序插入

因为InnoDB类型的表是按照主键的顺序保存的,所以将导入的数据按照主键的顺序排列,可以有效的提高导入数据的效率。如果InnoDB表没有主键,那么系统会自动默认创建一个内部列作为主键,所以如果可以给表创建一个主键,将可以利用这点,来提高导入数据的效率。

脚本文件介绍 :
	sql1.log  ----> 主键有序
	sql2.log  ----> 主键无序

插入ID顺序排列数据:

在这里插入图片描述

插入ID无序排列数据:

在这里插入图片描述

2) 关闭唯一性校验

在导入数据前执行 SET UNIQUE_CHECKS=0,关闭唯一性校验,在导入结束后执行SET UNIQUE_CHECKS=1,恢复唯一性校验,可以提高导入的效率。

在这里插入图片描述

3) 手动提交事务

如果应用使用自动提交的方式,建议在导入前执行 SET AUTOCOMMIT=0,关闭自动提交,导入结束后再执行 SET AUTOCOMMIT=1,打开自动提交,也可以提高导入的效率。

在这里插入图片描述

2 优化insert语句

当进行数据的insert操作的时候,可以考虑采用以下几种优化方案。

  • 如果需要同时对一张表插入很多行数据时,应该尽量使用多个值表的insert语句,这种方式将大大的缩减客户端与数据库之间的连接、关闭等消耗。使得效率比分开执行的单个insert语句快。

    示例, 原始方式为:

    insert into tb_test values(1,'Tom');
    insert into tb_test values(2,'Cat');
    insert into tb_test values(3,'Jerry');
    

    优化后的方案为 :

    insert into tb_test values(1,'Tom'),(2,'Cat')(3,'Jerry');
    
  • 在事务中进行数据插入。

    start transaction;
    insert into tb_test values(1,'Tom');
    insert into tb_test values(2,'Cat');
    insert into tb_test values(3,'Jerry');
    commit;
    
  • 数据有序插入

    insert into tb_test values(4,'Tim');
    insert into tb_test values(1,'Tom');
    insert into tb_test values(3,'Jerry');
    insert into tb_test values(5,'Rose');
    insert into tb_test values(2,'Cat');
    

    优化后

    insert into tb_test values(1,'Tom');
    insert into tb_test values(2,'Cat');
    insert into tb_test values(3,'Jerry');
    insert into tb_test values(4,'Tim');
    insert into tb_test values(5,'Rose');
    

3 优化order by语句

3.1 环境准备

CREATE TABLE `emp` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `age` int(3) NOT NULL,
  `salary` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

insert into `emp` (`id`, `name`, `age`, `salary`) values('1','Tom','25','2300');
insert into `emp` (`id`, `name`, `age`, `salary`) values('2','Jerry','30','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('3','Luci','25','2800');
insert into `emp` (`id`, `name`, `age`, `salary`) values('4','Jay','36','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('5','Tom2','21','2200');
insert into `emp` (`id`, `name`, `age`, `salary`) values('6','Jerry2','31','3300');
insert into `emp` (`id`, `name`, `age`, `salary`) values('7','Luci2','26','2700');
insert into `emp` (`id`, `name`, `age`, `salary`) values('8','Jay2','33','3500');
insert into `emp` (`id`, `name`, `age`, `salary`) values('9','Tom3','23','2400');
insert into `emp` (`id`, `name`, `age`, `salary`) values('10','Jerry3','32','3100');
insert into `emp` (`id`, `name`, `age`, `salary`) values('11','Luci3','26','2900');
insert into `emp` (`id`, `name`, `age`, `salary`) values('12','Jay3','37','4500');

create index idx_emp_age_salary on emp(age,salary);

3.2 两种排序方式

1). 第一种是通过对返回数据进行排序,也就是通常说的 filesort 排序,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。

在这里插入图片描述

2). 第二种通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。

在这里插入图片描述

多字段排序

在这里插入图片描述

了解了MySQL的排序方式,优化目标就清晰了:尽量减少额外的排序,通过索引直接返回有序数据。where 条件和Order by 使用相同的索引,并且Order By 的顺序和索引顺序相同, 并且Order by 的字段都是升序,或者都是降序。否则肯定需要额外的操作,这样就会出现FileSort。

3.3 Filesort 的优化

通过创建合适的索引,能够减少 Filesort 的出现,但是在某些情况下,条件限制不能让Filesort消失,那就需要加快 Filesort的排序操作。对于Filesort , MySQL 有两种排序算法:

1) 两次扫描算法 :MySQL4.1 之前,使用该方式排序。首先根据条件取出排序字段和行指针信息,然后在排序区 sort buffer 中排序,如果sort buffer不够,则在临时表 temporary table 中存储排序结果。完成排序之后,再根据行指针回表读取记录,该操作可能会导致大量随机I/O操作。

2)一次扫描算法:一次性取出满足条件的所有字段,然后在排序区 sort buffer 中排序后直接输出结果集。排序时内存开销较大,但是排序效率比两次扫描算法要高。

MySQL 通过比较系统变量 max_length_for_sort_data 的大小和Query语句取出的字段总大小, 来判定是否那种排序算法,如果max_length_for_sort_data 更大,那么使用第二种优化之后的算法;否则使用第一种。

可以适当提高 sort_buffer_size 和 max_length_for_sort_data 系统变量,来增大排序区的大小,提高排序的效率。

在这里插入图片描述

4 优化group by 语句

由于GROUP BY 实际上也同样会进行排序操作,而且与ORDER BY 相比,GROUP BY 主要只是多了排序之后的分组操作。当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数的计算。所以,在GROUP BY 的实现过程中,与 ORDER BY 一样也可以利用到索引。

如果查询包含 group by 但是用户想要避免排序结果的消耗, 则可以执行order by null 禁止排序。如下 :

drop index idx_emp_age_salary on emp;

explain select age,count(*) from emp group by age;

在这里插入图片描述

优化后

explain select age,count(*) from emp group by age order by null;

在这里插入图片描述

从上面的例子可以看出,第一个SQL语句需要进行"filesort",而第二个SQL由于order by null 不需要进行 “filesort”, 而上文提过Filesort往往非常耗费时间。

创建索引 :

create index idx_emp_age_salary on emp(age,salary);

在这里插入图片描述

5 优化嵌套查询

Mysql4.1版本之后,开始支持SQL的子查询。这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的SQL操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查询是可以被更高效的连接(JOIN)替代。

示例 ,查找有角色的所有的用户信息 :

 explain select * from t_user where id in (select user_id from user_role );

执行计划为 :

在这里插入图片描述

优化后 :

explain select * from t_user u , user_role ur where u.id = ur.user_id;

在这里插入图片描述

连接(Join)查询之所以更有效率一些 ,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。

6 优化OR条件

对于包含OR的查询子句,如果要利用索引,则OR之间的每个条件列都必须用到索引 , 而且不能使用到复合索引; 如果没有索引,则应该考虑增加索引。

获取 emp 表中的所有的索引 :
在这里插入图片描述

示例 :

explain select * from emp where id = 1 or age = 30;

在这里插入图片描述

建议使用 union 替换 or :

在这里插入图片描述

我们来比较下重要指标,发现主要差别是 type 和 ref 这两项

type 显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null  > index_merge > unique_subquery > index_subquery > range > index > ALL

UNION 语句的 type 值为 ref,OR 语句的 type 值为 range,可以看到这是一个很明显的差距

UNION 语句的 ref 值为 const,OR 语句的 type 值为 null,const 表示是常量值引用,非常快

这两项的差距就说明了 UNION 要优于 OR 。

7 优化分页查询

一般分页查询时,通过创建覆盖索引能够比较好地提高性能。一个常见又非常头疼的问题就是 limit 2000000,10 ,此时需要MySQL排序前2000010 记录,仅仅返回2000000 - 2000010 的记录,其他记录丢弃,查询排序的代价非常大 。

7.1 优化思路一

在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列内容。

在这里插入图片描述

7.2 优化思路二

该方案适用于主键自增的表,可以把Limit 查询转换成某个位置的查询 。

在这里插入图片描述

8 使用SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

8.1 USE INDEX

在查询语句中表名的后面,添加 use index 来提供希望MySQL去参考的索引列表,就可以让MySQL不再考虑其他可用的索引。

create index idx_seller_name on tb_seller(name);

在这里插入图片描述

8.2 IGNORE INDEX

如果用户只是单纯的想让MySQL忽略一个或者多个索引,则可以使用 ignore index 作为 hint 。

 explain select * from tb_seller ignore index(idx_seller_name) where name = '小米科技';

在这里插入图片描述

8.3 FORCE INDEX

为强制MySQL使用一个特定的索引,可在查询中使用 force index 作为hint 。

create index idx_seller_address on tb_seller(address);

在这里插入图片描述

type 显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null  > index_merge > unique_subquery > index_subquery > range > index > ALL

UNION 语句的 type 值为 ref,OR 语句的 type 值为 range,可以看到这是一个很明显的差距

UNION 语句的 ref 值为 const,OR 语句的 type 值为 null,const 表示是常量值引用,非常快

这两项的差距就说明了 UNION 要优于 OR 。

7 优化分页查询

一般分页查询时,通过创建覆盖索引能够比较好地提高性能。一个常见又非常头疼的问题就是 limit 2000000,10 ,此时需要MySQL排序前2000010 记录,仅仅返回2000000 - 2000010 的记录,其他记录丢弃,查询排序的代价非常大 。

[外链图片转存中…(img-2nrlnVtT-1671185727398)]

7.1 优化思路一

在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列内容。

[外链图片转存中…(img-z6wwTKOy-1671185727398)]

7.2 优化思路二

该方案适用于主键自增的表,可以把Limit 查询转换成某个位置的查询 。

[外链图片转存中…(img-rzR1zMO7-1671185727398)]

8 使用SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

8.1 USE INDEX

在查询语句中表名的后面,添加 use index 来提供希望MySQL去参考的索引列表,就可以让MySQL不再考虑其他可用的索引。

create index idx_seller_name on tb_seller(name);

[外链图片转存中…(img-s8qSM0zo-1671185727399)]

8.2 IGNORE INDEX

如果用户只是单纯的想让MySQL忽略一个或者多个索引,则可以使用 ignore index 作为 hint 。

 explain select * from tb_seller ignore index(idx_seller_name) where name = '小米科技';

[外链图片转存中…(img-reMW7xny-1671185727399)]

8.3 FORCE INDEX

为强制MySQL使用一个特定的索引,可在查询中使用 force index 作为hint 。

create index idx_seller_address on tb_seller(address);

[外链图片转存中…(img-7guRSK5Z-1671185727399)]

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

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

相关文章

【Budibase】搭建低代码开发平台

Budibase介绍 Budibase 是一套开源的低代码开发平台,支持一键数据库及API 接入,支持简单的 JS 关联前后端数据,有细致的权限访问管理,对移动端有良好的支持。它主打企业流程自动化,有完善的自动化流程设计&#xff0c…

NETDMIS5.0界面介绍

1.启动界面介绍 双击桌面快捷方式,打开NET.DMISS启动界面如下图,包含三个菜单是文件、设置语言、帮助。 2.工作界面介绍 默认测量界面包括主菜单,工具条,节点程序界面(显示测量过程),CAD视窗…

(免费分享)基于ssm简易网盘系统

开发工具:IDEA,mysql5.7 Tomcat8.0,jdk1.8 package cn.tangtj.clouddisk.web;import cn.tangtj.clouddisk.entity.User; import cn.tangtj.clouddisk.utils.UserUtil; import org.apache.logging.log4j.LogManager; import org.apache.loggi…

嵌入式应用开发|Linux文件I/O常用的四种访问方式

在Linux系统中&#xff0c;一切都可以看成"文件"<通常包含&#xff1a;普通文件、驱动文件、网络通信文件等等>&#xff0c;系统中所有的操作都可以通过文件I/O实现&#xff0c;因此&#xff0c;掌握文件常用接口很有必要。 0.前言 屏幕前的你如果懂得main函数…

SAP S4 如何快速配置一家公司

之前配置公司采用的方法是copy的方式来配置&#xff0c;后来在做其他配置的时候发现&#xff0c;copy的方法会把很多不需要的配置也copy进来了。所就我从新定义了一个公司来进行学习研究。配置一定空的公司很简单&#xff0c;只需要三步&#xff1a; 1 定义和分配公司 • 公司…

Java中的异常、IO与NIO面试题

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java面试题…

萤石网络通过注册:9个月净利2亿同比降28% 海康威视为大股东

雷递网 雷建平 12月19日杭州萤石网络股份有限公司&#xff08;简称&#xff1a;“萤石网络”&#xff09;日前通过注册&#xff0c;准备在科创板上市。萤石网络计划募资37.39亿元&#xff0c;其中&#xff0c;22亿元用于萤石智能制造重庆基地项目&#xff0c;8亿元用于新一代物…

论文投稿指南——中文核心期刊推荐(航空、航天)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

做Python网络爬虫需要掌握哪些核心技术?

在当下这个社会&#xff0c;如何有效地提取并利用信息成为一个巨大的挑战。基于这种巨大的市场需求&#xff0c;爬虫技术应运而生&#xff0c;这也是为什么现在爬虫工程师的岗位需求量日益剧增的原因。那么做Python网络爬虫需要掌握哪些核心技术呢&#xff1f;下面我们来一起看…

机器学习 特征工程及模型聚合

目录 一&#xff1a;什么是特征工程 二&#xff1a;特征工程方法 三&#xff1a;独热编码 四&#xff1a;归一化处理 五&#xff1a;特征工程方法 六&#xff1a;特征工程处理过程 七&#xff1a;Kaggle房价预测实际案例 一&#xff1a;什么是特征工程 1 是最大限度地从…

React源码分析6-hooks源码

本文将讲解 hooks 的执行过程以及常用的 hooks 的源码。 hooks 相关数据结构 要理解 hooks 的执行过程&#xff0c;首先想要大家对 hooks 相关的数据结构有所了解&#xff0c;便于后面大家顺畅地阅读代码。 Hook 每一个 hooks 方法都会生成一个类型为 Hook 的对象&#xff…

学习->C++篇十八:一文总结C++的异常

目录 C为什么要引入异常&#xff1f; 什么是异常&#xff1f; 怎么使用异常处理错误&#xff1f; 异常的抛出规则&#xff1a; 异常的匹配规则&#xff1a; 单个catch语句&#xff0c;不能完全处理掉异常&#xff1f;重新抛出异常 什么是异常安全问题&#xff1f; 什么…

一、绘制折线图

Origin-绘图 一、新建绘图表格 Add New Column&#xff1a;新建一列 Set as→Y Error设置新列为Y误差 Long Name&#xff1a;X轴和Y轴名称&#xff1b;Units&#xff1a;单位&#xff1b;Comments&#xff1a;注释&#xff1b; 二、绘图 绘制折线图&#xff1a; 选择X、Y、…

2022年,转行IT学哪些编程语言更容易拿高薪?

人们都说年头年尾都是给自己进行规划最好的时段&#xff0c;想要学习编程的你现在是不是也开始进行规划了呢&#xff1f; 不过对大部分人来说&#xff0c;最犹豫的问题也摆在面前&#xff0c;编程语言众多&#xff0c;不知道学什么才能对后续的就业和职业发展有更好的作用。 …

PyTorch 2.0 之 Dynamo: 窥探加速背后的真相

前言 PyTorch 2.0 算是正式官宣了&#xff0c;预计在明年 3 月和大家见面。官方的 blog 宣发了非常多的内容&#xff0c;但是阅读下来不难发现&#xff0c;几乎所有的性能提升、体验优化都源自于 PyTorch 新设计的即时编译工具&#xff1a;Dynamo。 PyTorch eager 模式极佳的…

Flink 在米哈游的应用实践

摘要&#xff1a;本文整理自米哈游大数据实时计算团队负责人张剑&#xff0c;在 Flink Forward Asia 2022 主会场的分享&#xff0c;本篇内容主要分为三个部分&#xff1a;发展历程和平台建设场景应用实践未来展望Tips&#xff1a;点击「阅读原文」获取演讲 ppt01发展历程和平台…

分享一种通信协议的应用编程原理和思路

已剪辑自: https://mp.weixin.qq.com/s/wy-flva6pCNqHV3ObeLPCQ 嵌入式开发过程中&#xff0c;UART、 CAN、 USB等通信基本离不开通信协议。 下面给大家分享一种通信协议&#xff08;MAVLink&#xff09;在应用编程中的编程原理和思路。 本节提供“MAVLink发送接收例程”例程下…

[FTP] ftp通信协议抓包分析

想在ESP32上用TCP来实现ftp服务器&#xff0c;抓一下ftp通信包分析一下。总的来说就是两个TCP通道&#xff0c;一个命令通道&#xff0c;一个数据通道&#xff1b;数据通道只有在遍历目录、下载、上传的时候才开启&#xff0c;其余时候均不开启&#xff1b;主要就是协议对接好就…

【认识】wireshark使用教程

本文章&#xff0c;是简单粗暴学习Wireshark的抓包功能后&#xff0c;记录的一些笔记。 1 Wireshark简介及抓包原理及过程 1.1 简介 Wireshark是1个网络封包分析软件。网络封包分析软件的功能是截取网络封包&#xff0c;并尽可能显示出最为详细的网络封包资料。Wireshark使用…

从盒马生鲜迫切转型升级有感而发,疫情之后,路在何方

据悉&#xff0c;针对浦东地区目前突增的需求&#xff0c;市民线上采买生活物资的订单激增&#xff0c;饿了么联合包括每日优鲜、大润发在内的主要生鲜买菜商户&#xff0c;一起增加运力配合&#xff1b;盒马生鲜也对接了上海之外的山东、云南等省外基地&#xff0c;以避免中间…