MySQL进阶-----limit、count、update优化

目录

前言

一、limit优化

1. 未优化案例

 2.优化后案例

二、count优化

count用法

三、update优化

 1.锁行情况(有索引)

2.锁表情况(无索引)


前言

        上一期我们学习了order by优化和group by优化,本期我们就继续学习sql语句的优化,分为以下三个部分MySQL进阶-----limit、count、update优化。正文如下:

一、limit优化

这里我有一张表tb_sku 里面有400w条数据,以这个表作为案例对象

在数据量比较大时,如果进行 limit 分页查询,在查询时,越往后,分页查询效率越低。
我们一起来看看执行 limit 分页查询耗时对比:

1. 未优化案例

(1)查询起始索引0后面10条记录
select * from tb_sku limit 0,10;

可以看出耗时几乎为0,一下子就完成了 

(2)查询起始索引100w后的10条记录 

select * from tb_sku limit 1000000,10;

这里耗时要3秒多,需要的时间变长了

(3) 查询起始索引300w后的10条记录 

select * from tb_sku limit 3000000,10;

这里耗时几乎翻倍,要11秒多。所以越往后需要的时间就越多。

通过测试我们会看到,越往后,分页查询效率越低,这就是分页查询的问题所在。
因为,当在进行分页查询时,如果执行 limit 2000000,10 ,此时需要 MySQL 排序前 2000010
录,仅仅返回 2000000 - 2000010 的记录,其他记录丢弃,查询排序的代价非常大 。
优化思路 : 一般分页查询时,通过创建 覆盖索引 能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。

 2.优化后案例

已知当前表的主键为id,其已有索引,那么我们试一下把上面的*换为查询id

select id from tb_sku limit 3000000,10;

下面我们通过子查询的形式来去优化分页查询 

select * from tb_sku a , (select id from tb_sku order by id limit 3000000,10) b where a.id = b.id;

这里查询只需要6秒多 ,查询同样的数据,相较于上面的直接查询少了5秒,将近一半。

二、count优化

在之前的测试中,我们发现,如果数据量很大,在执行 count 操作时,是非常耗时的。
select count(*) from tb_user ;

  • MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个 数,效率很高; 但是如果是带条件的countMyISAM也慢。
  • InnoDB 引擎就麻烦了,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出 来,然后累积计数。
我们都知道MySQL一般主要用到的引擎就是InnoDB 引擎,如果说要大幅度提升InnoDB 表的 count 效率,主要的优化思路:自己计数 ( 可以借助于 redis 这样的数据库进行, 但是如果是带条件的 count 又比较麻烦了 ) 。所以下面我们要进一步了解count聚合函数的使用。

count用法

count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是
NULL ,累计值就加 1 ,否则不加,最后返回累计值。
用法: count * )、 count (主键)、 count (字段)、 count (数字)

count用

含义

count(主

键)

InnoDB 引擎会遍历整张表,把每一行的 主键id 值都取出来,返回给服务层。

服务层拿到主键后,直接按行进行累加(主键不可能为null)

count(字

段)

没有not null 约束 : InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null,不为null,计数累加。

有not null 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接按行进行累加。

count(数

字)

InnoDB 引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1” 进去,直接按行进行累加。

count(*)

InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。

按照效率排序的话,count(字段) < count(主键 id) < count(1) ≈ count(*),所以尽
量使用 count(*)。

三、update优化

下面有一张表courses,数据如下,这里就以这个表作为案例对象

在finalshell这里我们开启两个窗口,然后分别登录MySQL

然后开启事务,执行语句

 1.锁行情况(有索引)

A.左边窗口

update courses set c_name='JavaScript' where id=2;

 B .右边窗口

update courses set c_name='htmlcss' where id=1;

 好了,上面两个表都开启了事务,执行update语句,从结果可以看出这两个并发的事务并没有发生冲突,然后下面我们把两边窗口事务进行提交。

再次查询更新后表数据: 执行到这里是没问题的,没有发送阻塞情况,最终表也是更新完成。这是因为这里使用的是行锁,也就是where语句后面定位到的是id字段,这

update courses set c_name='C++' where c_name='JavaScript';

个字段是有索引的,故会把这一行锁住,但我们去执行其他行的时候与本行无关,所以不会发生冲突阻塞。所以当我们在执行删除的SQL语句时,会锁定id为1这一行的数据,然后事务提交之后,行锁释放。

2.锁表情况(无索引)

同样的我们还是用两个窗口看看锁表情况的案例:

A.左边窗口

update courses set c_name='msyql' where c_name='htmlcss';

B.右边窗口 

update courses set c_name='C++' where c_name='JavaScript';

右边窗口的执行结果跟我们预期的不一样,并没有继续执行下去,而是卡在这里了,这是因为出现了锁表的情况,也就是说左边窗口执行的事务没有提交之前,整个表都是被锁住的,所以其他事务是无法对这个表进行操作的。

当我们去提交了左边窗口的事务后,再看看右边窗口的执行情况。

 表锁释放了,所以执行成功。然后我们把右边窗口的事务进行提交。最后查看更新后的表数据。

我们主要需要注意一下 update语句执行时的注意事项。 当我们开启多个事务,在执行上述的 SQL 时,我们发现行锁升级为了表锁。 导致该 update 语句的性能 大大降低。所以假如我们对c_name字段创建一个索引的话就不会出现锁表情况,如果要执行更新操作的话,我们要提前去看看where后面的字段有没有索引。
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁 ,并且该索引不能失效,否则会从行锁升级为表锁 。

以上就是本期的全部内容了,我们下次见!

分享一张壁纸:

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序员接单的渠道有没有可靠介绍?

程序员接单的渠道有很多&#xff0c;但总结下来无非就是个人介绍和程序员接单平台。 这里就不多说废话了&#xff0c;直接上当前市面上靠谱且稳定的程序员接单平台list。 程序员客栈 近100w程序员都在使用的程序员接单平台。作为一个靠谱的线上接单渠道&#xff0c;程序员客栈…

SSRF靶场

SSRF概述 ​ 强制服务器发送一个攻击者的请求 ​ 互联网上的很多web应用提供了从其他服务器&#xff08;也可以是本地)获取数据的功能。使用用户指定的URL&#xff0c;web应用可以获取图片&#xff08;载入图片&#xff09;、文件资源&#xff08;下载或读取)。如下图所示&…

笔试题1 -- 吃掉字符串中相邻的相同字符(点击消除_牛客网)

吃掉字符串中相邻的相同字符 文章目录 吃掉字符串中相邻的相同字符题目重现解法一&#xff1a;(基于 erase() 函数实现)解法二&#xff1a;&#xff08;利用 栈 辅助实现&#xff09;总结 题目链接&#xff1a; 点击消除_牛客网 题目重现 牛牛拿到了一个字符串。 他每次“点击…

关联规则挖掘(一)

目录 一、关联规则的概念&#xff08;一&#xff09;基本概念&#xff08;二&#xff09;项集的性质 二、关联规则的Apriori算法&#xff08;一&#xff09;发现频繁项集&#xff08;二&#xff09;产生关联规则 一、关联规则的概念 &#xff08;一&#xff09;基本概念 事务数…

byobu

byobu 终端多路复用器 一、byobu 安装二、byobu 使用三、其他终端多路复用器四、ssh byobu 远程协作 系统环境: linux(ubuntu,debian,kali) 一、byobu 安装 byobu 是包装过的tmux #sudo apt install tmux sudo apt install byobubyobu二、byobu 使用 创建窗口: Ctrl a c…

windows编译xlnt,获取Excel表里的数据

用git拉取项目 这个文件是空的 要用git拉下来&#xff0c;使用终端编译xlnt库 点击解决方案 运行生成 然后新建项目&#xff0c;配置好库&#xff0c; #include <iostream> #include <xlnt/xlnt.hpp>int main() {// 打开 Excel 文件xlnt::workbook workbook;workb…

Redis从入门到精通(十九)多级缓存(四)Nginx共享字典实现本地缓存

文章目录 前言6.5 实现多级缓存6.5.6 Nginx本地缓存6.5.6.1 代码实现6.5.6.2 功能测试 6.6 缓存同步6.6.1 缓存同步策略6.6.2 异步通知策略 前言 Redis多级缓存系列文章&#xff1a; Redis从入门到精通(十六)多级缓存(一)Caffeine、JVM进程缓存 Redis从入门到精通(十七)多级缓…

EPSON两款新的加速器M-A552AC1和M-A552AR1

老化的社会基础设施以及基础设施维护、监控和更新成本的飙升被认为是国家和社区面临的严重社会问题&#xff0c;在有着高度城市化的国家尤为明显。在这样的环境和认识推动下,利用传感器监测结构健康的技术需求的日益增长。爱普生推出了两款新的高性能加速器M-A552AC1和M-A552AR…

【C++】开始使用stack 与 queue

送给大家一句话&#xff1a; 忍受现实给予我们的苦难和幸福&#xff0c;无聊和平庸。 – 余华 《活着》 开始使用queue 与 stack 1 前言2 stack与queue2.1 stack 栈2.2 queue 队列2.3 使用手册 3 开始使用Leetcode 155.最小栈牛客 JZ31 栈的弹出压入序列Leetcode 150.逆波兰表达…

tailwindcss在manoca在线编辑智能感知

推荐一下monaco-tailwindcss库&#xff0c;它实现在monaco-editor网页在线编辑器中对tailwindcss的智能感知提示&#xff0c;在利用tailwindcss实现html效果布局。非常的方便。 生成CSS

freertos作业day1

1.总结keil5下载代码和编译代码需要注意的事项 1.&#xff09;仿真器设置&#xff1a; 点击魔术棒&#xff0c;选择debug选项&#xff0c;找到使用的仿真器&#xff0c;选择ST-LINK仿真器&#xff0c;点击setting&#xff0c;选择flash download ,勾选reset and run,选择pack…

基于zookeeper安装Kafka集群

操作系统&#xff1a;centOS 9 Stream&#xff0c;6台&#xff0c;基于vmware虚拟机创建 准备工作 确认系统环境&#xff1a; 确保所有服务器已安装了最新更新。安装Java Development Kit (JDK) 8或更高版本&#xff0c;因为ZooKeeper和Kafka都是基于Java开发的。例如&#x…