【MySQL高级】SQL优化

news2024/11/29 10:56:20

5. SQL优化

5.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 命令导入数据的时候,适当的设置可以提高导入的效率。

 

load data local infile 'E:/sql1.log' into table tb_user_2 fields terminated by ',' lines terminated by '\n';
​
load data local infile 'E:/sql2.log' into table tb_user_2 fields terminated by ',' lines terminated by '\n';

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

1) 主键顺序插入

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

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

插入ID顺序排列数据:

 

插入ID无序排列数据:

 

注意出现:【LOAD DATA语法上传数据】

具体解法见 【Mysql中出现的问题】 这个笔记

2) 关闭唯一性校验

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

 

3) 手动提交事务

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

 

5.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');

5.3 优化order by语句

5.3.1 环境准备

CREATE TABLE `emp2` (
  `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 `emp2` (`id`, `name`, `age`, `salary`) values('1','Tom','25','2300');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('2','Jerry','30','3500');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('3','Luci','25','2800');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('4','Jay','36','3500');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('5','Tom2','21','2200');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('6','Jerry2','31','3300');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('7','Luci2','26','2700');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('8','Jay2','33','3500');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('9','Tom3','23','2400');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('10','Jerry3','32','3100');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('11','Luci3','26','2900');
insert into `emp2` (`id`, `name`, `age`, `salary`) values('12','Jay3','37','4500');
​
create index idx_emp_age_salary on emp2(age,salary);

5.3.2 两种排序方式

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

 

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

 

多字段排序

 

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

5.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 系统变量,来增大排序区的大小,提高排序的效率。

 

5.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 emp2;
​
explain select age,count(*) from emp2 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.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不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作。

5.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 。

5.7 优化分页查询

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

 

5.7.1 优化思路一

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

 

5.7.2 优化思路二

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

 

5.8 使用SQL提示

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

5.8.1 USE INDEX

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

create index idx_seller_name on tb_seller(name);

 

5.8.2 IGNORE INDEX

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

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

 

5.8.3 FORCE INDEX

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

create index idx_seller_address on tb_seller(address);

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

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

相关文章

【数据库】实验五 数据库综合查询|多表查询、聚集函数、orderby、groupby

文章目录参考文章本文在实验四的基础上增加了orderby、聚集函数、groupby、多表查询的知识点,相较于上一次实验的难度变大了,嵌套表达更多了,逐渐开始套娃…… 其实可以看成一个偏正短语来拆分,再写成SQL语句,比如查询…

微信小程序|基于小程序实现人脸数量检测

一、文章前言二、具体流程及准备三、开发步骤四、完整代码一、文章前言 此文主要通过小程序实现检测图片中的人脸数量并标记出位置信息。 当近视的小伙伴看不清远处的人时,用小程序一键识别就可以在手机上看清楚啦,是不是很实用呢。 典型应用场景&#x…

2022年还在做手动测试?是该好好反思了

为什么会写这篇文章呢?主要是前段时间有个朋友在QQ上和我交流,说他干了10年的手工测试了,现在还能不能转行。 说实话,当时我听完非常惊讶!由此,我写了今天这篇文章。内容纯属个人观点,如果对你…

STM32CubeMX学习笔记(46)——USB接口使用(HID自定义设备)

一、USB简介 USB(Universal Serial BUS)通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、…

浅刷牛客链表题,逐步深入链表,理解链表

作者:渴望力量的土狗 博客主页:渴望力量的土狗的博客主页 专栏:手把手带你刷牛客 工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器——牛客网 点击免费注册和我一起刷题吧 目录 1、反转链表 2、删除链表的倒数第n个…

RocketMQ 消息重新投递 解析——图解、源码级解析

🍊 Java学习:Java从入门到精通总结 🍊 深入浅出RocketMQ设计思想:深入浅出RocketMQ设计思想 🍊 绝对不一样的职场干货:大厂最佳实践经验指南 📆 最近更新:2022年11月4日 &#x…

35、Java——一个案例学会Dao+service层对数据表的增删改查

✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:乐趣国学的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:Java案例分…

deployment html--->JDBC--->mysql

spec: 相关属性定义 spec.selector: 符合该条件的收到该deployment管理 #spec.selector.matchLables 和 spec.template.metadata.labels 标签要一致 mysql Service metadata.name: Service的服务名 spec.ports: 虚拟端口 spec.selector: 哪些pod(实列&…

《Java》深浅拷贝解析(还不会区分深浅拷贝吗?快进来)

目录 一、深浅拷贝的意义 浅拷贝 深拷贝 二、深浅拷贝举例 浅拷贝 深拷贝 一、深浅拷贝的意义 首先我们来了解一下深浅拷贝的意义 浅拷贝 浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用&#xff0c…

全网最全【数据结构与算法】408真题实战(含代码+详解)—— 线性表专题(持续更新...)

线性表专题 每道题目均有对应的代码&#xff0c;大家自行查看哦&#xff01; 顺序表 ADT&#xff1a;SeqList 文件名&#xff1a;SeqList.hpp #include <iostream> #include <cstdlib> using namespace std; // 以上是实际运行所需依赖&#xff0c;考试不用写t…

怎样编写裸片启动程序-ARMv8的Boot Code和ROM程序

ROM程序就是固化在芯片的ROM里面&#xff0c;把应用程序从存储器里加载/搬移到RAM中并使处理器开始执行应用程序的一段程序 1 Boot Code和ROM程序 从多普通单核MCU&#xff08;如STM32&#xff09;的使用者的角度来看&#xff0c;只需要把编译好的hex文件烧写到片上Flash中&am…

JavaScript(WebAPI) (前端)

文章目录前言一、WebAPI二、DOM1.选中元素2.事件3.获取/修改元素内容4.获取/修改元素属性5.获取/修改表单元素属性6.操作复选框7.获取/修改样式属性①行内样式②通过css class 指定的样式8.新增节点9.删除节点总结前言 虽然学了一些js的语法,但是仍然无法写出页面的动态效果~~…

【JavaScript高级进阶】构造函数和原型,学会prototype

目录 前言 1.构造函数和原型 1.1使用prototype解决内存浪费的问题 1.2constructor构造函数构造器构造函数 2.原型链 2.1js中成员查找规则 2.2原型对象this指向 2.3扩展内置对象 3.call作用 4.继承 4.1利用原型对象继承 写在最后 前言 哈喽哈喽大家好&#xff0c;因为…

【Day1】零基础学java--》记事本运行java程序,通熟语言让你彻底明白为什么配置java环境变量

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#xff0c;从今天开始我将协同大家一起从零基础学习Java&#xff0c;期待与君为伴&#xff0c;走向海的彼岸。&#x1f495;&#x1f495;&#x1f495; &#x1f9d1;个人主页&#xff1a;良辰针不戳 &#x1f4d6;所属专栏&a…

C语言之数组练习题

第1关&#xff1a;数组插入元素 300 任务要求参考答案评论106 任务描述相关知识 数组数组元素的表示方法编程要求测试说明任务描述 本关需要你将一个数插入到一组已经排好序的数组并输出。 相关知识 数组在程序设计中&#xff0c;为了处理方便&#xff0c; 把具有相同类型…

【C++】多态 — 多态的原理 (下篇)

文章目录&#x1f4d6; 前言1. 虚函数表1.1 虚函数表的引入&#xff1a;1.2 基类的虚表&#xff1a;1.3 派生类虚表&#xff1a;2. 多态的原理2.1 多态虚函数的调用和普通函数的调用&#xff1a;2.1 - 1 到底什么是多态&#xff08;重点&#xff09;2.1 - 2 父类的指针实现多态…

Allegro基本规则设置指导书之Analysis Modes

Allegro基本规则设置指导书之Analysis Modes 下面介绍基本规则设置指导书之Analysis Modes 点击set-up-constrains-Modes 调出Analysis Modes,这个是所有DRC的总开关 下面介绍常用的一些开关设置 Design Options (Soldermask) 从上往下 阻焊到阻焊的间距 阻焊到pad和走线…

EasyCVR及智能分析网关在校园视频融合及明厨亮灶项目中的应用方案设计

随着校园智能化需求的不断增长&#xff0c;越来越多的校园逐渐开始升级校园监控视频平台&#xff0c;将原先传统的视频监控系统&#xff0c;逐渐升级转变为灵活性强、视频能力丰富、具备AI检测能力、并能支持视频汇聚与统一管理的智能化校园综合管理平台。 在某学校的视频监控…

MapReduce概述

MapReduce概述 MapReduce是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在一个Hadoop集群上。 MapReduce…

【优化算法】鹈鹕优化算法(POA)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…