数据库SQL优化技巧

news2024/11/25 16:44:35

作为程序员,主要的工作任务就是curd,和数据库打交道是无可避免的。掌握一些数据库的优化技巧是非常有必要的

一、减少数据访问

1、使用索引
  索引的原理是利用额外的空间建立了一个平衡的搜索树,大大缩短了查询的时间,使得查询的时间复杂度从O(n)降低到O(log(n)),但是在进行插入、修改、删除操作的时候,同时要对搜索树进行相对应的维护,需要带来额外的开销

在这里插入图片描述
例如上面的搜索树,需要查询6的时候,步骤如下
(1)6和10比较,10大,那么往左边下去,到4
(2)6和4比较,6大,那么往右边下去,到6
(3)6和6比较,相等,那么6就是想要查询的数据

如果没有索引,那么每个元素都要比较一下才可以查出目标数据,这点可以比喻二分查找元素的案例

上面的搜索树只是一个类比,mysql的索引使用的是b+树,思想和上面的例子是差不多的,只不过b+树是多叉平衡树,并且数据存在叶子节点,这样可以方便查找相邻的元素

使用索引需要注意的是,只有当索引符合一定条件的时候索引才会生效,因为索引并不能解决100%的问题,例如两个字段id、name,id列建立了一个索引,假如判断条件为where id = name,每一行的name是会变化的,那么就无法使用索引,必须每一行都进行判断才可以得到结果,并不是数据库设计者故意不让索引生效的,而是索引本身不能解决这个问题

查询条件不能使用索引原因
INDEX_COLUMN <> ?不等于操作不能使用索引
INDEX_COLUMN not in (?,?,…,?)不等于操作不能使用索引
function(INDEX_COLUMN) = ?经过普通运算或函数运算后的索引字段不能使用索引
INDEX_COLUMN || ‘a’ = ?经过普通运算或函数运算后的索引字段不能使用索引
INDEX_COLUMN like ‘%’||?含前导模糊查询的Like语法不能使用索引
INDEX_COLUMN like ‘%’||?||‘%’含前导模糊查询的Like语法不能使用索引
INDEX_COLUMN is nullB-TREE索引里不保存字段为NULL值记录,因此IS NULL不能使用索引
CHAR_INDEX_COLUMN=12345Oracle在做数值比较时需要将两边的数据转换成同一种数据类型,如果两边数据类型不同时会对字段值隐式转换,相当于加了一层函数处理,所以不能使用索引。
a.INDEX_COLUMN=a.COLUMN_1给索引查询的值应是已知数据,不能是未知字段值。

在使用联合索引还有个最左匹配原则,例如有联合索引a、b、c,a没生效,那么b和c就无法生效,反过来,c如果要生效,那么a、b必须生效

2、分库分表
分库分表又有垂直划分和水平划分两种,先看一下定义:
(1)垂直分库
一般是为了解耦,将一个整体划分为多个部分,同时这样做也可以平衡数据库的压力,每个数据库管理一部分数据
在这里插入图片描述
(2)水平分库
一般用于解决单个数据库压力过大的问题,例如一百万个人同时访问学生数据库,会导致数据库瘫痪,那么可以考虑水平分库,下面举一个例子进行理解

例如下面将学生数据库分为了3个,那么可以根据学生的id去分配学生数据,例如常见的mod法,假如id为10,10%3=0,那么这个学生的数据库存在第一个数据库中,反过来看,数据库1存放学生id为0,3、6、9…的学生数据,数据2存放的是1、4、7、10…的学生数据,数据3存放的是2、5、8、11…的学生数据
在这里插入图片描述
(3)垂直分表

把存储数据多的或者不常用的字段分离出来,可以提高查询的速度,因为在查找的时候不用额外扫描不需要的数据,例如下面,简介可以储存1000个字,那么在查找的时候是相对耗时的,即使我们没有去查该字段的数据,分离之后,查找学生姓名的时候就不需要扫描简介字段了
在这里插入图片描述

(4)水平分表

水平分表和水平分库是类似的,单个表的数据量过大,那么查询的时间就会长,如果建立了索引,对插入、修改和删除操作就会有严重的影响

水平划分数据可以解决这个问题,可以按一定的逻辑去划分数据,不一定使用mod法,例如下面的例子:

由于业务需求,可能需要对各个年级的学生数据进行维护,例如划分课程等等,就可以按学生年级、专业这些相关字段去划分
在这里插入图片描述
(5)总结
水平分库、垂直分表、水平分表都使用了减少数据访问的原理对数据库操作做了优化,而垂直分库可解耦合,使得数据库变得更加灵活易维护

二、返回更少的数据

数据的传输是需要花费时间的,传输越多的数据,那么花费的时间就越多

(1)分页
一般来说,展示给用户的数据都会有分页的,那么查询的时候可以根据一些推荐算法对数据进行排序,用户需要更多数据的时候再查需要的数据,而不是将查到的数据一下子全部发送到客户端

(2)只返回需要的字段
通过去除不必要的返回字段可以提高性能,例:
调整前:select * from product where company_id=?;
调整后:select id,name from product where company_id=?;

优点:
1、减少数据在网络上传输开销
2、减少服务器数据处理开销
3、减少客户端内存占用
4、字段变更时提前发现问题,减少程序BUG
5、如果访问的所有字段刚好在一个索引里面,则可以使用纯索引访问提高性能。

缺点:增加编码工作量

三、减少交互次数
1、batch DML
如果插入1000条数据

通过for循环一条一条进行操作,那么需要和数据库建立1000次连
假如每次插入10条数据,那么需要建立100次连接接
假如每次插入100条数据,那么需要建立10次连接
那么是不是每次插入的数据量越多越好呢?不是的,批量插入的时候需要建立临时表,批量插入的数据越多,那么占用的空间越大,有内存溢出的风险

总的来说,适当地调节插入、修改、删除的批量操作的数量,可以降低数据库的连接次数,减少了网络通信使用的时间

mybatis plus也提供了批量操作的接口,默认单次处理的数据为1000条
在这里插入图片描述

2、In List
尽量不循环查询数据库,可以使用in条件批量查询,如果需要分离数据,可以使用程序分离,这样不仅减低数据库的连接次数,而且在没有索引的情况下降低了扫描数据库的次数

3、设置Fetch Size
数据查询出来需要从数据库传输到实体类中存储起来,这中间传输的时候需要建立连接通道,传输的速率有通道的大小决定,通道的大小可以通过调整Fetch Size调节,如果通道太小,传输数据就会很慢,如果过大,会浪费空间,有内存溢出的风险。所以调整Fetch Size优化性能的时候需要对数据量进行评估

mybatis可以使用fetchSize属性调节大小,网络上大家都说fetchSize设置在40-100比较合适,oracle默认是10,所以取10000条数据的时候就需要花费10秒钟,需要适当提高fetchSize来提高传输速度
在这里插入图片描述

4、使用存储过程

使用存储过程可以在一次连接做许多复杂的逻辑操作,查出的数据直接在数据库中处理,由此可以去掉连接和传输的时间花销,例如将一个表的数据处理后存到另一个表,传统的做法是取出数据到客户端,处理后再用insert语句插入到另一个表中,而存储过程却可以一步到位,直接取数据,处理,插入。最大的优点就是减少了数据在网络上传输开销

存储过程的收益并没有很大,又不容易维护,所以在实际的生产中很少使用,定时性的ETL任务或报表统计函数使用得比较多

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

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

相关文章

鉴源实验室丨SOME/IP协议安全攻击

作者 | 张昊晖 上海控安可信软件创新研究院工控网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 引 言 随着汽车行业对于数据通信的需求不断增加&#xff0c;SOME/IP作为支持汽车以太网进程和设备间通信的一种通信协议应…

echarts中如何给柱状图增加滚动条

需求:当后台传递过来的数据过多的时候 页面的柱图就会很拥挤 如下图: 所以我们需要有一个横向的滚动条,让所有的柱子都能够展示 1.echarts中有一个dataZoom属性 可以给图形增加一个横向的滚动条 dataZoom:[ {type: slider, //滑动条型数据区域缩放组件realtime: true, //拖动…

第6章 C控制语句:循环

本章介绍以下内容&#xff1a; 关键字&#xff1a;for、while、do while 运算符&#xff1a;<、>、>、<、!、、、*、-、/、% 函数&#xff1a;fabs() C语言有3种循环&#xff1a;for、while、do while 使用关系运算符构建控制循环的表达式 其他运算符 循环常用的数…

Linux tun虚拟网卡通信初识

什么是linux tun设备 Linux TUN 设备是一种虚拟网络设备&#xff0c;用于在用户空间和内核空间之间建立数据通道&#xff0c;使用户空间程序可以通过这个设备与内核网络栈进行交互。TUN 设备是一种通用的网络隧道设备&#xff0c;常用于实现虚拟专用网络&#xff08;VPN&#…

适配器模式-java实现

意图 复用已经存在的接口&#xff0c;与所需接口不一致的类。即将一个类&#xff08;通常是旧系统中的功能类&#xff09;&#xff0c;通过适配器转化成另一个接口的实现。&#xff08;简单来说&#xff0c;就是复用旧系统的功能&#xff0c;去实现新的接口&#xff09; 我们举…

Python Web开发 Jinja2模板引擎

在之前的文章中&#xff0c;简单介绍了Python Web开发框架Flask&#xff0c;知道了如何写个Hello World&#xff0c;但是距离用Flask开发真正的项目&#xff0c;还有段距离&#xff0c;现在我们目标更靠近一些 —— 学习下Jinja2模板。 模板的作用 模板是用来做什么的呢&…

C 语言高级3--函数指针回调函数,预处理,动态库的封装

目录 1.函数指针和回调函数 1.1 函数指针 1.1.1 函数类型 1.1.2 函数指针(指向函数的指针) 1.1.3 函数指针数组 1.1.4 函数指针做函数参数(回调函数) 2.预处理 2.1 预处理的基本概念 2.2 文件包含指令(#include) 2.2.1 文件包含处理 2.2.2 #incude<>和#include&q…

数据结构:栈的实现(C实现)

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》 文章目录 前言一、栈的实现思路1. 结构的定义2. 初始化栈(StackInit)3. 入栈(StackPush)4. 出栈(StackPop)5. 获取栈顶元素(StackTop)6. 检查栈是否为空(StackEmpty)7. 销毁栈(StackDestroy) 二、…

踩坑 视觉SLAM 十四讲第二版 ch13 编译及运行问题

一、安装Geset 库 sudo apt-get install libgtest-dev cd /usr/src/gtest sudo mkdir build cd build sudo cmake .. //一定要以sudo的方式运行&#xff0c;否则没有写入权限 sudo make //这个也一样要以sudo的方式 sudo cp libgtest*.a /usr/local/lib //将生成…

python表白代码大全可复制,python表白代码大全简单

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python表白代码大全可复制&#xff0c;python表白程序代码完整版&#xff0c;现在让我们一起来看看吧&#xff01; 今天是20230520&#xff0c;有人说&#xff1a;5代表的是人生五味&#xff0c;酸甜苦辣咸&#xff1b;…

设备管理平台:采用以可靠性为中心的维护策略的优势

在如今的工业领域&#xff0c;以可靠性为中心的维护策略正逐渐成为企业数字化转型的核心。无论是混合还是离散自动化应用&#xff0c;优化维护和工作流程实践已经成为提高利润、降低停机时间、增强运营和生产性能的不可或缺的一环。在这个过程中&#xff0c;设备管理系统与物联…

Harbor部署--使用 Harbor 安装包

一、Harbor安装准备条件 这里以 harbor 2.8.3 版本为例 1.1 硬件要求 Harbor 安装对硬件资源CPU、内存和硬盘的要求如下表&#xff1a; 资源 最小要求 推荐配置 CPU 2 CPU 4 CPU Mem 4 GB 8 GB Disk 40 GB 160 GB 使用如下命令分别查看服务器的物理CPU和逻辑CPU个数…

LCD1602相关

一.概述 LCD1602是一种工业字符型液晶&#xff0c;能够同时显示16*02即32字符&#xff08;16列2行&#xff09; 二.引脚接口说明表 第 1 脚 : VSS 为电源地 第 2 脚 : VDD 接 5V 正电源 第 3 脚 : VL 为液晶显示器对比度调整端 , 接正电源时对比度最弱&#xff…

第三章 图论 No.8最近公共祖先lca, tarjan与次小生成树

文章目录 lcaTarjan板子题&#xff1a;1172. 祖孙询问lca或tarjan&#xff1a;1171. 距离356. 次小生成树352. 闇の連鎖 lca O ( m l o g n ) O(mlogn) O(mlogn)&#xff0c;n为节点数量&#xff0c;m为询问次数&#xff0c;lca是一种在线处理询问的算法 自己也是自己的祖先 倍…

XML方式AOP快速入门XML方式AOP配置详解

目录 1.XML方式AOP快速入门 1&#xff1a;导入AOP相关坐标 2&#xff1a;准备目标类&#xff0c;准备增强类&#xff0c;并配置给Spring管理 3&#xff1a;配置切点表达式&#xff08;那些方法要被增强&#xff09; 4&#xff1a;配置织入&#xff08;切点被哪些方法增强&…

漫画算法做题笔记

诸神缄默不语-个人CSDN博文目录 哦这是我三年前写的&#xff0c;我现在Java语法都快忘光了…… 反正之前的博文也发一下好了。这个因为我当年是用有道云笔记而不是直接用CSDN编辑器写的&#xff0c;所以后面有些内容写乱了&#xff0c;因为我现在猛的一看有点看不懂&#xff0…

一文读懂|RDMA原理

什么是DMA DMA全称为Direct Memory Access&#xff0c;即直接内存访问。意思是外设对内存的读写过程可以不用CPU参与而直接进行。我们先来看一下没有DMA的时候&#xff1a; 无DMA控制器时I/O设备和内存间的数据路径 假设I/O设备为一个普通网卡&#xff0c;为了从内存拿到需要…

事务的隔离级别与Spring事务的传播机制

目录 事务的隔离性 事务的隔离级别 读未提交 读已提交 可重复读 串行化 Spring事务的传播机制 支持当前事务 不支持当前事务 嵌套事务 事务的隔离性 事务的隔离性是事务的四大特性之一&#xff0c;数据库允许多个事务并发操作数据&#xff0c;为了尽可能地避免并发操…

【JAVA】-【IO流】

文章目录 FileReader读入数据的基本操作FileReader中使用reader()FileWrite写出数据的操作使用FileInputStream、FileOutputStream操作图片缓冲流&#xff08;字节型&#xff09;实现非文本文件的复制 复制文本文件也可以使用字节流&#xff0c;但是不要在内存中读出来&#xf…

【Matlab】Elman神经网络遗传算法(Elman-GA)函数极值寻优——非线性函数求极值

往期博客&#x1f449; 【Matlab】BP神经网络遗传算法(BP-GA)函数极值寻优——非线性函数求极值 【Matlab】GRNN神经网络遗传算法(GRNN-GA)函数极值寻优——非线性函数求极值 【Matlab】RBF神经网络遗传算法(RBF-GA)函数极值寻优——非线性函数求极值 本篇博客将主要介绍Elman神…