【数据库】聊聊常见的索引优化-下

news2024/11/25 6:56:10

分页查询优化

主键排序
在这里插入图片描述
在实际的使用中,通过limit 10000,10 查询第10000记录到10010记录,mysql执行的时候是按照将前10010记录全部统计出来,然后剔除前10000条记录,选择后10条记录。这样来看的话,效率不高。

在这里插入图片描述
如果数据是有序的,那么可以直接使用上面这种方式,发现使用了索引,在于这种方式是通过id选择大于10000的数据。两种方式不同。但是如果数据有删除的可能,那么不推荐使用这种方式。并且这种方式需要主键连续才可以。

非主键排序
在这里插入图片描述
但是如果使用 order by name limit,发现没有走索引,具体原因就是mysql优化器发现走索引之后的成本还不如全表查询,放弃了索引。

如何优化呢?

关键点其实就是尽可能使用较少的字段排序。如下只使用主键id排序。指向效率大大高于上面这个。
在这里插入图片描述

Join关联查询优化


-- 示例表:
CREATE TABLE `t1` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `a` int(11) DEFAULT NULL,
 `b` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `idx_a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 create table t2 like t1;
-- 插入一些示例数据
-- 往t1表插入1万行记录
drop procedure if exists insert_t1; delimiter ;;
create procedure insert_t1()
begin
   declare i int;
   set i=1;
   while(i<=10000)do
     insert into t1(a,b) values(i,i);
     set i=i+1;
   end while;
 end;;
 delimiter ;


call insert_t1();
-- 往t2表插入100行记录
drop procedure if exists insert_t2; delimiter ;;
create procedure insert_t2()
begin
  declare i int;
  set i=1;
  while(i<=100)do
    insert into t2(a,b) values(i,i);
    set i=i+1;
  end while;
end;;
delimiter ;
call insert_t2();

上述的SQL 我们创建了两个结构一样的表T1和T2,T1插入1W行数据。T2插入100条记录。

 EXPLAIN select * from t1 inner join t2 on t1.a= t2.a;

那么针对上述的这个SQL,MySQL内部是怎么执行的?
有两种执行算法,决定选择哪个算法取决于关联字段是否有索引。

  • Nested-Loop Join算法 (关联字段有索引)
  • Block Nested-Loop Join算法 (关联字段没有索引)

嵌套循环连接 Nested-Loop Join(NLJ) 算法

嵌套循环执行其实就是每次驱动表拿出一条记录,在这样记录找到关联的字段,根据关联字段在另一张表(驱动表)取出满足条件的行。然后汇总结果。
在这里插入图片描述
从图中可以看出,以下信息

  • 因为id相同,所以T2就是驱动表,T1是被驱动表,小表驱动大表。inner join前的表不一定就是驱动表,mysql会优化。
  • 对于 left join来说,左表是驱动表,右表是被驱动表。right join相反。所以需要合理选择驱动表。
  • 使用了NLJ算法,在join语句中,没有显示Using join buffer,表示使用的join算法是NLJ。

上述的整体流程其实就是
1.T2每次从表中取出一条记录。在和T1中符合条件的数据匹配,将结果存储起来。最后直到执行完毕所有的结果。T2扫描100行。T1扫描100行。一共是200行。

基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法

本算法其实就是将驱动表T2全部数据拉到内存 join buffer中,然后扫描被驱动表,将被驱动表的每一行都取出来根join_buffer的数据进行对比。 图中显示的是using join buffer说明使用的是BNL算法。
在这里插入图片描述
上述的整体流程
其实就是将T2中的全部100行数据拉到join buffer中,然后把表T1中每一行数据都取出来,进行对比。我们来分析下扫描的行数。T2是100行,T1是1W行,在内存中执行需要 100 * 10000 = 100万次比较。
因为join_buffer_size是有限制的,默认是256K,如果超过这个范围,就是分段放。

思考
为什么对于没有索引的关联字段使用BNL算法,而不是Nested-Loop Join算法呢。
我们来分析,如果采用Nested-Loop Join算法,因为关联的b 字段没有索引,所以也就是T2和T1在次盘层面扫描100 * 10000 = 100W次。这个效率很慢的,相比于BNL算法在内存中比较100W次效率肯定更快。


好了,这里简单总结下,其实对于join的方式,不建议3张表以上的操作,并且对于关联字段要使用索引,选择NLJ算法,而不是BNL算法。小表驱动大表。straight_join 知道哪个是小表,可以使用straight_join进行指定。

 EXPLAIN select * from t1 straight_join t2 on t1.a= t2.a;

straight_join 就制定了一个大表T1。
在这里插入图片描述

 EXPLAIN select * from t2 straight_join t1 on t1.a= t2.a;

执行了T2,明显比上面的性能更好
在这里插入图片描述

  • straight_join只适用于inner join,并不适用于left join,right join。(因为left join,right join已经代表指 定了表的执行顺序)

小表的定义
在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。

in和exsits优化

in : 表B的数据集小于A表的数据集时,in由于exists

select * from A where id in (select id from B)
#等价于:
for(select id from B){
 select * from A where A.id = B.id 5
}

exists:当A表的数据集小于B表的数据集时,exists优于in

select * from A where exists (select 1 from B where B.id = A.id) 2 #等价于:
 
for(select * from A){
	 select * from B where B.id = A.id
}

#A表与B表的ID字段应建立索引

count(*) 查询优化

 EXPLAIN SELECT count(1) FROM employees;
 EXPLAIN SELECT count(*) FROM employees;
 EXPLAIN SELECT count(name) FROM employees;
 EXPLAIN SELECT count(id) FROM employees;

字段有索引:count( * ) ≈ count(1) > count(字段) >count(主键 id) 字段有索引,count(字段)统计走二级索引,二 级索引存储数据比主键索引少,所以 count(字段)>count(主键 id)

字段无索引:count( * )≈count(1)>count(主键 id)>count(字段) //字段没有索引count(字段)统计走不了索引, count(主键 id)还可以走主键索引,所以count(主键 id)>count(字段)

count(1) : 其实就是把每一行的数据取出来,然后填充1 进行累加。
count(id) : 将每一行的主键id拿出来,累加。
count(*) : 不会将每一行的数据直接取出来,而是做了优化。累加。
coungt(字段):其实统计的是字段不为空的数据。

有什么统计总行数的解决方案?
1.如果存储引擎是MyISAM,会存储在磁盘可以直接获取。但是InnoDB中的MVCC机制,会导致记录的行数不准确,所以没有。
2.show table status

 SHOW TABLE STATUS LIKE 'employees';

3.通过redis或者数据技术表进行统计

阿里MySQL规范

在MySQL中选择正确的数据类型,可以减少磁盘空间,以及对查询性能有一定的提高。
1.确定合适的大类型:数值、字符串、时间、二进制等
2.选择具体的类型:有无符号,取值范围,变长定长等。
尽量把字段定义为not null ,不要null

数值类型

在这里插入图片描述

  • 1.如果整形数据没有负数,如ID号,建议指定为UNSIGNED无符号类型,容量可以扩大一倍。
  • 2.DECIMAL最适合保存准确度要求高,而且用于计算的数据,比如价格。

时间类型

在这里插入图片描述

  • 建议用DATE数据类型来保存日期。MySQL中默认的日期格式是yyyy-mm-dd。
  • 当数据格式为TIMESTAMP和DATETIME时,可以用CURRENT_TIMESTAMP作为默认(MySQL5.6以后), MySQL会自动返回记录插入的确切时间

字符串类型

在这里插入图片描述

  • char 定长字符串、varchar 非定长字符串,
  • 如果存储的字符串长度几乎相等,使用char,比如存储 UUID这种,但是如果不是固定的,那么使用varchar。

小总结

本篇从limit、join 、count 、以及对应的数据类型 介绍了如何优化SQL。结合上一篇。
常见的索引SQL优化就介绍完毕了。

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

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

相关文章

Java桶排序、基数排序、剪枝算法

桶排序算法 桶排序的基本思想是&#xff1a; 把数组 arr 划分为 n 个大小相同子区间&#xff08;桶&#xff09;&#xff0c;每个子区间各自排序&#xff0c;最后合并 。计数排序是桶排序的一种特殊情况&#xff0c;可以把计数排序当成每个桶里只有一个元素的情况。 1.找出待…

企鹅目标检测数据集VOC格式400张

企鹅&#xff0c;一种可爱而独特的鸟类&#xff0c;以其圆滚滚的身体、黑白相间的羽毛和独特的行走方式而备受人们喜爱。 企鹅是鸟纲、企鹅科的动物&#xff0c;它们生活在南半球&#xff0c;特别是南极地区。企鹅的体型短而肥胖&#xff0c;有着流线型的身体和黑白相间的羽毛…

24/1/8

传奇登录界面&#xff1b; #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {//窗口设置this->setWindowTitle("传奇");//窗口名this->setWindowIcon(QIcon("C:\\Users\\21528\\Desktop\\图标.png"));//窗口图标th…

【Flutter 开发实战】Dart 基础篇:最基本的语法内容

在深入了解 Dart 这门编程语言之前&#xff0c;我们需要了解一些关于 Dart 的最基本的知识&#xff0c;像是常量、变量、函数等等&#xff0c;这样才能够让我们的开发效率更上一层楼。在本节&#xff0c;我们将探讨一些基础语法&#xff0c;包括入口方法 main、变量、常量以及命…

ERA5和GNSS站点不并址的处理方法二:垂直补偿(获得GNSS站点高度的PWV、温度和气压,基于matlab)

0. 码字不易&#xff0c;点赞加关注&#xff08;公众号&#xff1a;WZZHHH&#xff0c;部分资料在公众号可以下载&#xff09; Part1 垂直补偿的原因 我们在获取GNSS站点位置的PWV有很多方法&#xff0c;其中一个是利用ERA5数据进行积分得到。由于ERA5格网位置和GNSS不并址&am…

信息安全监管

安全政策 中央办公厅2003的27号文件 《国家信息化领导小组关于加强信息安全保障工作的意见》 方针&#xff1a;积极防御&#xff0c;综合防范 目标、要求&#xff1a;全面提高信息安全防护能力&#xff0c;保护公众利益&#xff0c;维护国家安全 4大原则&#xff1a; 立足…

为什么建筑设计师选择网络渲染“效果图“

网络渲染一般是指&#xff1a;云渲染&#xff0c;建筑设计行业通常需要渲染室内、室内等场景的效果图&#xff0c;一般大型场景渲染时非常消耗电脑算力&#xff0c;并且渲染时长也会通过效果图的场景、尺寸等来决定&#xff0c;本文为用户整理建筑设计师选择网络渲染的原因&…

孪生神经网络MATLAB实战[含源码]

​一、算法原理 孪生神经网络&#xff08; Siamese neural network&#xff09;是一种深度学习网络&#xff0c;它使用两个或多个具有相同架构、共享相同参数和权重的相同子网。孪生网络通常用于寻找两个可比较事物之间的关系的任务。孪生网络的一些常见应用包括面部识别、签名…

3.9 EXERCISES

矩阵加法需要两个输入矩阵A和B&#xff0c;并产生一个输出矩阵C。输出矩阵C的每个元素都是输入矩阵A和B的相应元素的总和&#xff0c;即C[i][j] A[i][j] B[i][j]。为了简单起见&#xff0c;我们将只处理元素为单精度浮点数的平方矩阵。编写一个矩阵加法内核和主机stub函数&am…

用红葡萄酿造的白葡萄酒是怎样的?

“由黑变白”这是“黑葡萄”的直译&#xff0c;代表一种由深蓝到黑葡萄制成的白葡萄酒&#xff0c;这种酿酒方式起源于法国&#xff0c;黑皮诺和莫尼尔的红葡萄一直被加工成白葡萄酒&#xff0c;作为香槟的基础。这是可能的&#xff0c;因为红色浆果通常果肉较轻。红色素&#…

TypeScript 从入门到进阶之基础篇(八)函数篇

系列文章目录 TypeScript 从入门到进阶系列 TypeScript 从入门到进阶之基础篇(一) ts基础类型篇TypeScript 从入门到进阶之基础篇(二) ts进阶类型篇TypeScript 从入门到进阶之基础篇(三) 元组类型篇TypeScript 从入门到进阶之基础篇(四) symbol类型篇TypeScript 从入门到进阶…

Java课程设计团队博客 —— 基于网页的时间管理系统

博客目录 1.项目简介2.项目采用的技术3.功能需求分析4.项目亮点5.主要功能截图6.Git地址7.总结 Java团队博客分工 姓名职务负责模块孙岚组长 资源文件路径和tomcat服务器的相关配置。 前端的页面设计与逻辑实现的代码编写。 Servlet前后端数据交互的编写。 用户登录和断开连接…

独立式键盘控制的4级变速流水灯

#include<reg51.h> // 包含51单片机寄存器定义的头文件 unsigned char speed; //储存流水灯的流动速度 sbit S1P1^4; //位定义S1为P1.4 sbit S2P1^5; //位定义S2为P1.5 sbit S3P1^6; //位定义S3为P1.6 sbit S4P1^7; //位…

熟悉HBase常用操作

1. 用Hadoop提供的HBase Shell命令完成以下任务 (1)列出HBase所有表的相关信息,如表名、创建时间等。 启动HBase: cd /usr/local/hbase bin/start-hbase.sh bin/hbase shell列出HBase所有表的信息: hbase(main):001:0> list(2)在终端输出指定表的所有记录数据。 …

鸿蒙原生应用/元服务开发-消息通知整体说明

应用/元服务可以通过通知接口发送通知消息&#xff0c;终端用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用。 通知常见的使用场景&#xff1a;显示接收到的短消息、即时消息等。显示应用的推送消息&#xff0c;如广告、版本更新等。显示当前正在进行的事…

CCF模拟题 202309-1 坐标变换(其一)

问题描述 试题编号&#xff1a; 202309-1 试题名称&#xff1a; 坐标变换&#xff08;其一&#xff09; 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 问题描述&#xff1a; 对于平面直角坐标系上的坐标&#xff08;x,y&#xff09;&#xff0c;小P定义了一个包含…

代码随想Day60 | 84.柱状图中最大的矩形

84.柱状图中最大的矩形 这道题和接雨水遥相呼应&#xff0c;接雨水是求外部凹槽&#xff0c;这道题是求内部面积&#xff0c;这道题的整体思路是某一个元素&#xff0c;找到其左边的第一个小于该数的位置&#xff0c;右边的第一个小于该数的位置&#xff0c;然后以当前索引的高…

CodeWave智能开发平台--03--目标:应用创建--07供应商数据表格02

摘要 本文是网易数帆CodeWave智能开发平台系列的第10篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成07供应商数据表格下 CodeWave智能开发平台的10次接触 CodeWave参考资源 网易数帆CodeWave开发…

202312 青少年软件编程等级考试Scratch一级真题(电子学会)

2023年12月 青少年软件编程等级考试Scratch一级真题&#xff08;电子学会&#xff09; 试卷总分数&#xff1a;100分 试卷及格分&#xff1a;60 分 考试时长&#xff1a;60 分钟 第 1 题 单选题 观察下列每个圆形中的四个数&#xff0c;找出规律&#xff0c;在括…

鸿蒙原生应用/元服务开发-短时任务

概述 应用退至后台一小段时间后&#xff0c;应用进程会被挂起&#xff0c;无法执行对应的任务。如果应用在后台仍需要执行耗时不长的任务&#xff0c;如状态保存等&#xff0c;可以通过本文申请短时任务&#xff0c;扩展应用在后台的运行时间。 约束与限制 申请时机&#xf…