SQL高级优化

2023-05-16

知识回顾:

1)git版本控制工具,主要管理项目的代码文件

它相比CVS、SVN它特点,可支持分布式、外网、离线工作
主流代码管理工具

2)基本概念

工作空间
本地索引
本地仓库
远程仓库
就体积而言:远程仓库>本地仓库>工作空间


3)操作

把代码放在远程仓库上(上传)
把远程仓库上的代码获取(下载)

和网盘的差异:

1)网盘只是简单的复制文件,git管理文件,可以是一个链接
2)网盘文件之间没有依赖关系或者说没有具体联系,代码关系。
3)文件本质是一个一个,代码是一个项目

4)网盘是没有分支 branch树杈

mysql数据库(免费)、oracle收购mysql(收费) 在mysql旧版本上
开源新的产品:percona分支、MariaDB著名的分支
招商银行做项目,给包头银行做项目,,海南银行
大项目采用分支,git从基础建设时,就要提供这种分支机制,master主分支

5)网盘文件没有比较做法,代码可能多人编辑(团队)代码比较,代码冲突

6)git它会对一个文件进行多个版本的复制,v1.0、v1.1、v1.2,多个文件

网盘秒传,1个电影,第二个用户只分享这个文件链接地址,文件只存1份

7)使用git命令

git add . (提交改变(新增文件、修改文件内容、删除文件))
git commit -m “提交” (把这些改变操作日志记录下来,本地索引)
git push -u origin master (根据本地索引日志,进行提交操作,提交本地仓库,把本地仓库的内容提交到远程仓库)

git pull 拉取,git clone 克隆


1.SQL优化 面试题必考的内容,占10分,是看你的数据库功底

SQL优化是在很多小点上来优化:where,索引失效
索引中有很多类型:ALL全表扫描(最差 没有索引)、index全索引扫描(其次)、range(between)范围(不错)、const常量(缓存)(最好)、ref(join)
工作中先实现业务,实现业务之后,想办法优化 where or,in
如果数据量很小时,索引反而慢。
索引越多越好吗?频繁使用了索引,这时索引价值体现。如果这个几乎没用,删除。
表的数据如果变化,新增,修改,删除,索引都必须重构索引(重新建立)、
如果有大量索引的表,不适合数据频繁变更。


2.SQL优化

批量插入性能提升
需要事务的,mysql为每一句insert语句增加事务
事务自动提交

如果我有100w数据,每一句话都要开启事务,提交事务,关闭事务
如果操作一张表时,数据库会对这张表进行锁定。加lock

解决办法:
手工提交事务set @@autocommit = 0;

for (int i=0;i<100;i++){
          begin;
                  insert
                  commit;
}
mysql批量新增语句:

在一条insert SQL中提交多个记录

大量数据提交,上千,上万,批量性能非常快,mysql独有

多条提交:
INSERT INTO student (id,NAME) VALUES(4,‘张三’);
INSERT INTO student (id,NAME) VALUES(5,‘李四’);
批量提交:
INSERT INTO student (id,NAME) VALUES(4,‘张三’),(5,‘李四’);
理由:
默认新增SQL有事务控制,导致每条都需要事务开启和事务提交;而批量处理是一次事务开启和提交。
自然速度飞升 数据量小体现不出来

insert  into `student`(`id`,`NAME`,`sex`,`birthday`,`salary`) 
			values ('1','张慎政','男','2020-01-01','10000.00'),
			('2','刘沛霞','女','2020-01-02','10000.00'),
			('3','刘昱江','男','2020-01-03','10000.00'),
			('4','齐雷','男','2020-01-04','20000.00'),
			('5','王海涛','男','2020-01-05','20000.00'),
			('6','董长春','男','2020-01-06','10000.00'),
			('7','张久军','男','2020-01-07','20000.00'),
			('8','陈子枢','男','2020-10-11','3000.00');

批量删除优化(不用频繁开启和关闭事务)

避免同时修改或删除过多数据,因为会造成cpu利用率过高,会造成锁表操作,从而影响别人对数据库的访问。
反例:
#一次删除10万或者100万+?
delete from student where id <100000;

#采用单一循环操作,效率低,时间漫长

for(User user:list){
  delete from student;
}

正例:
//分批进行删除,如每次500

for(){
delete student where id<500;
}
delete student where id>=500 and id<1000;

理由:
一次性删除太多数据,可能造成锁表,会有lock wait timeout exceed的错误,所以建议分批操作


伪删除设计

商品状态(state):1-上架、2-下架、3-删除
给表增加一个是否删除标识字段isdel,tinyint,0未删除,1已删除
删除数据,不是真正执行delect语句,执行update

update student set isdel = 1 where id=100;
用户不能看见被删除的“记录”
select * from student where …and isdel=0;

理由:
这里的删除只是一个标识,并没有从数据库表中真正删除,可以作为历史记录备查
同时,一个大型系统中,表关系是非常复杂的,如电商系统中,商品作废了,但如果直接删除商品,其它商品详情,物流信息中可能都有其引用。
通过where state=1或者where state=2过滤掉数据,这样伪删除的数据用户就看不到了,从而不影响用户的使用
操作速度快,特别数据量很大情况下

优点:
a.修改标识的速度远高于删除语句
b.这些历史数据,可以用来数据分析,数据挖掘,用户画像,大数据杀熟


提高group by语句的效率

可以在执行到该语句前,把不需要的记录过滤掉

反例:先分组,再过滤

select job,avg(salary) from employee
group by job
having job =‘president’ or job = ‘managent’;

正例:先过滤,后分组

select job,avg(salary) from employee
where job =‘president’ or job = ‘managent’
group by job;

如果一个过滤条件,即可以放在where,也可以放在having来实现,优先放在where中,每一步操作都会在内存中形成一个临时表
原则:临时表越小越好


复合索引最左特性

创建复合索引,也就是多个字段

ALTER TABLE student ADD INDEX idx_name_salary (NAME,salary)

满足复合索引的左侧顺序,哪怕只是部分,复合索引生效

EXPLAIN
SELECT * FROM student WHERE NAME=‘陈子枢’

没有出现左边的字段,则不满足最左特性,索引失效

EXPLAIN
SELECT * FROM student WHERE salary=3000

复合索引全使用,按左侧顺序出现 name,salary,索引生效

EXPLAIN
SELECT * FROM student WHERE NAME=‘陈子枢’ AND salary=3000

虽然违背了最左特性,但MYSQL执行SQL时会进行优化,底层进行颠倒优化(交换律)

EXPLAIN
SELECT * FROM student WHERE salary=3000 AND NAME=‘陈子枢’
SQL优化为
EXPLAIN
SELECT * FROM student WHERE NAME=‘陈子枢’ AND salary=3000

复合索引特征:
最左特性原则,创建一个复合索引,相当于创建2个索引,(k,m) 创建了 (k)、(k、m)
左边依次拼接
( i , j , k ) 创建 ( i ) / ( i , j ) / ( i , j , k )

理由:
复合索引也称为联合索引
当我们创建一个联合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则
联合索引不满足最左原则,索引一般会失效,但是这个还跟Mysql优化器有关的


排序字段创建索引

什么样的字段才需要创建索引呢?原则就是where和order by中常出现的字段就创建索引。
#使用*,包含了未索引的字段,导致索引失效

EXPLAIN
SELECT * FROM student ORDER BY NAME;

EXPLAIN
SELECT * FROM student ORDER BY NAME,salary

#name字段有索引

EXPLAIN
SELECT id,NAME FROM student ORDER BY NAME

#name和salary复合索引

EXPLAIN
SELECT id,NAME FROM student ORDER BY NAME,salary

EXPLAIN
SELECT id,NAME FROM student ORDER BY salary,NAME

#排序字段未创建索引,性能就慢

EXPLAIN
SELECT id,NAME FROM student ORDER BY sex


删除冗余和重复的索引

SHOW INDEX FROM student

#创建索引index_name
ALTER TABLE student ADD INDEX index_name (NAME)

#删除student表的index_name索引
DROP INDEX index_name ON student ;

#修改表结果,删除student表的index_name索引
ALTER TABLE student DROP INDEX index_name ;

#主键会自动创建索引,删除主键索引
ALTER TABLE student DROP PRIMARY KEY ;


不要有超过5个以上的表连接

关联的表个数越多,编译的时间和开销也就越大
每次关联内存中都生成一个临时表
应该把连接表拆开成较小的几个执行,可读性更高
如果一定需要连接很多表才能得到数据,那么意味着这是个糟糕的设计了
阿里规范中,建议多表联查三张表以下


inner join 、left join、right join,优先使用inner join

三种连接如果结果相同,优先使用inner join,如果使用left join左边表尽量小

inner join 内连接,只保留两张表中完全匹配的结果集
left join会返回左表所有的行,即使在右表中没有匹配的记录 right
join会返回右表所有的行,即使在左表中没有匹配的记录

理由:

如果inner join是等值连接,返回的行数比较少,所以性能相对会好一点
同理,使用了左连接,左边表数据结果尽量小,条件尽量放到左边处理,意味着返回的行数可能比较少。
这是mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优


in子查询的优化

日常开发实现业务需求可以有两种方式实现:

一种使用数据库SQL脚本实现
一种使用程序实现

如需求:查询所有部门的所有员工:
#in子查询
SELECT * FROM tb_user WHERE dept_id IN (SELECT id FROM tb_dept);

#这样写等价于:
#先查询部门表
SELECT id FROM tb_dept

#再由部门dept_id,查询tb_user的员工
SELECT * FROM tb_user u,tb_dept d WHERE u.dept_id = d.id

假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下程序实现,可以抽象成这样的一个嵌套循环:

List<> resultSet;
for(int i=0;i<B.length;i++) {
  for(int j=0;j<A.length;j++) {
    if(A[i].id==B[j].id) {
      resultSet.add(A[i]);
      break;
    }
  }
}

上面的需求使用SQL就远不如程序实现,特别当数据量巨大时。
理由:

数据库最费劲的就是程序链接的释放。
假设链接了两次,每次做上百万次的数据集查询,查完就结束,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,就会额外花费很多实际,这样系统就受不了了,慢,卡顿


尽量使用union all替代union

反例:

SELECT * FROM student
UNION
SELECT * FROM student

正例:

SELECT * FROM student
UNION ALL
SELECT * FROM student

理由:

union和union all的区别是,union会自动去掉多个结果集合中的重复结果,而union
all则将所有的结果全部显示出来,不管是不是重复 union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序
union在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。
实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL高级优化 的相关文章

  • SQL 表别名 - 好还是坏? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在 SQL 中使用表别名有哪些优点和缺点 我个人会尽量避免使用它们 因为我认为它们会使代码的可读性降低 特别是在阅读大型 where and 语
  • 如何在Java中使用准备好的语句进行选择查询?

    我曾多次尝试使用准备好的语句 但它返回 SQL 异常 这是我的代码 public ArrayList
  • 对不同记录进行 PIVOT 查询

    我有下表 Id Code percentage name name1 activity 1 Prashant 43 43 James James Running 1 Prashant 70 43 Sam Sam Cooking 1 Pras
  • 如何将 ROW_NUMBER() 分配给列?

    看完之后这个问题 https stackoverflow com questions 1293390 sql to output line number in results of a query 我还有一个类似的问题 有没有一种简单的方法
  • SQL 外键引用

    Does FOREIGN KEY a REFERENCES A a FOREIGN KEY b REFERENCES A b 与以下含义相同 FOREIGN KEY a b REFERENCES A a b No 有两个references
  • SQL - 选择具有最大值的所有行

    我有这个 SQL 查询 SELECT id COUNT AS price FROM SELECT FROM rt WHERE somecondition AS st JOIN tt ON st id tt id GROUP BY id 现在
  • 尝试使用 PHP / Html 从注册表单将数据输入到 SQL 表中

    我尝试了很多不同的事情并进行了很多搜索但没有解决方案 我正在尝试使用 html 表单将数据提交到 sql 表 这是我的 register php 文件的代码 con mysqli connect localhost database nam
  • Django 多对多查询的逻辑或返回重复结果

    我有具有多对多关系的模型 如下所示 class Contact models Model name models TextField address models TextField class Mail models Model to m
  • SQL Server:十进制精度/小数位数产生奇怪的结果

    我正在为一个项目编写一些 SQL 我注意到 SQL Server 中一些看似奇怪的行为 涉及除以小数时的答案 以下是一些示例 说明了我所看到的行为 DECLARE Ratio Decimal 38 16 SET Ratio CAST 210
  • 将 Linq 表达式转换为 SQL Server 查询

    我正在使用一些 crm 框架 该框架没有任何内部 orm 并且不使用实体框架 仅使用纯 sql 查询 我在数据库中的每个表都有实体 所以我有例如 public class Customer public string FirstName g
  • Oracle数据库中的自增主键

    我想在 SQL Server 的列中实现标识或自动递增值 CREATE TABLE RollingStock Id NUMBER IDENTITY 1 1 Name Varchar2 80 NOT NULL 如何才能做到这一点 正如 Orb
  • SQL CASE 语句

    我有以下查询 我想将它们放入 sql CASE 语句中 这样我只有一个查询 但我不知道该怎么做 有人可以帮助我吗 IF SELECT EtlLoadId FROM ssislogs audit processcontrol WHERE Su
  • 有向图 SQL

    我有以下数据集 它表示有向图中的节点 CREATE TABLE nodes NODE FROM VARCHAR2 10 NODE TO VARCHAR2 10 INSERT INTO nodes VALUES GT TG INSERT IN
  • 有没有办法将应用程序上下文与非 Sybase DB 服务器中的数据库连接进行通信(类似于 Sybase 中的 set_appcontext)?

    Sybase 有一种让应用程序进行通信的方法 上下文 数据 http manuals sybase com onlinebooks group as asg1250e sag Generic BookTextView 38861 hf 0
  • 如何编辑表以启用级联删除?

    我有一个代表用户的表 当用户被删除时我得到 DELETE 语句与 REFERENCE 约束冲突 显然 CASCADE DELETE在SQL Server中并不像我想象的那么容易 需要将选项添加到表中 问题是 我不知道如何添加CASCADE
  • 对 SQL Server 2005 结果进行分页

    如何在 SQL Server 2005 中对结果进行分页 我在 SQL Server 2000 中尝试过 但没有可靠的方法来做到这一点 我现在想知道SQL Server 2005是否有任何内置方法 分页的意思是 例如 如果我按用户名列出用户
  • SQL COUNT(*) 返回错误答案

    以下脚本应返回部门名称以及这些部门中的员工人数 营销 行政和销售部门有 0 名员工 但返回值不是 0 而是 1 我怎样才能纠正它 select Department Departments DepartmentID count as Num
  • 计算行数并仅获取表中的最后一行

    我有一张桌子叫employeexam其结构和数据是这样的 id course id employee id degree date 1 1 3 8 2013 01 14 2 2 4 15 2013 01 14 3 2 4 17 2013 0
  • 左连接 SQL 求和

    我有两张桌子想要加入 比如说表 a 和表 b 表 b 有许多行指向表 a 表 b 包含价格 实际上是一个购物篮 所以我想要的是表a中的所有记录和表b中的价格之和 我努力了 select a sum b ach sell from booki
  • 更新查询时 ios 中出现“数据库锁定”错误

    我正在使用下面的代码更新查询 using sqlite 但我越来越 database is locked error 我尝试搜索一些 SO 链接 建议关闭数据库 但我再次执行此操作时遇到相同的错误 我已经提到过代码中出现错误的地方 cons

随机推荐

  • ubuntu lightdm test用户自动登陆

    1 编辑 etc lightdm lightdm conf d 50 myconfig conf 内容 SeatDefaults autologin user 61 test 注意此处是自己要登陆的用户名字
  • 猴小萌的博客开通啦

    多年痴迷计算机技术 xff0c 孜孜不倦地学习着计算机的一切 xff0c 享受着计算机带给我的乐趣和满足感 然而有一天 xff0c 突然发现我所获得的知识和问题的答案基本上全部都来自于网络 xff0c 却从来没有为社区奉献过 xff0c 上
  • Cesium入门(一):第一张Cesium页面

    本章主要讲述如何下载和使用Cesium xff0c 编写完成自己的第一张Cesium应用页面 主要从以下几个方面展开叙述 xff1a 下载和部署CesiumJS编写第一张Cesium页面 1 下载和部署CesiumJS CesiumJS是一
  • Cesium入门(二):Viewer控件参数与外观定制

    本章主要介绍Cesium Viewer控件的选项参数 xff0c 以及如何对Viewer的外观进行定制 主要包括以下内容 xff1a Viewer控件Viewer选项参数定制Viewer外观界面 1 Viewer控件 Viewer是构建Ce
  • Cesium入门(三):加载WMS地图服务

    本章介绍Cesium Viewer控件的是如何加载地图的 xff0c 并以GeoServer服务器为例演示了WMS服务的加载过程 主要包括以下内容 xff1a ImageryProvider加载GeoServer发布的WMS服务 在Cesi
  • Cesium入门(四):叠加显示多个图层

    本章介绍Cesium Viewer控件的imageryLayers容器 xff0c 了解添加和叠加显示多个图层的方法 主要包括以下内容 xff1a imageLayers图层容器添加多个图层 1 imageryLayers图层容器 imag
  • GeoServer入门(一):发布第一个WMS图层

    本章主要讲述如何下载和安装使用GeoServer服务器 xff0c 介绍了GeoServer的管理界面 xff0c 并演示了发布地理数据的简单流程 主要从以下几个方面展开叙述 xff1a 下载和安装GeoServerGeoServer管理界
  • FreeBSD内存交换文件的设置与自动加载

    本文主要讲述FreeBSD操作系统下内存交换文件的作用及其自动加载过程 xff0c 主要从以下几个方面展开叙述 xff1a 交换文件的设置交换文件的自动加载 交换文件是虚拟内存机制的重要组成部分 xff0c 在物理内存不够用时可以临时将不常
  • GeoServer入门(二):WMTS图层瓦片切割与调用

    本章主要讲述如何GeoServer进行图层瓦片切割与缓冲 xff0c 发布标准的WMTS服务 xff0c 并介绍了REST格式的调用参数 主要包含以下内容 xff1a 图层切片与缓冲WMTS服务调用 在GeoServer入门 xff08 一
  • Cesium入门(五):加载WMTS瓦片地图服务

    本章介绍Cesium JS库的WebMapTileServiceImageryProvider类 xff0c 并以GeoServer为例演示了在CesiumViewer控件中添加瓦片图层的方法 主要包括以下内容 xff1a WebMapTi
  • 深入学习Tomcat----自己动手写服务器(附服务器源码)

    相信大多 Web 开发者对 Tomcat 是非常熟悉的 xff0c 众所周知 Tomcat 是一款非常好用的开源 Servlet 容器 xff0c 您一定对这个最流行的 Servlet 容器充满好奇 xff0c 虽然它并不像一个黑盒子那样让
  • Cesium入门(六):加载EPSG4326网格的瓦片地图

    本章介绍Cesium JS库的TilingScheme类 xff0c 并以GeoServer服务器为例演示了加载EPSG 4326网络的瓦片地图 主要包括以下内容 xff1a TilingScheme添加EPSG 4326瓦片图层 在Ces
  • Cesium入门(七):设置影像图层的覆盖范围

    本章介绍Cesium JS库的Rectangle类 xff0c 并以GeoServer服务器为例演示了在加载EPSG 4326网格的瓦片地图时 xff0c 通过设置rectangle参数来限定图层的覆盖范围 主要包括以下内容 xff1a R
  • Wget下载网页与镜像网站

    本文主要介绍GNU Wget实用程序及其在在FreeBSD操作系统下的安装过程 xff0c 并对几个最常用的下载功能进行了说明 xff0c 主要包括以下几个方面 xff1a GNU Wget概述Wget程序安装Wget常用功能 1 GNU
  • 使用cron定时执行任务

    本文主要介绍Unix系统中用于定时执行任务的cron守护程序和crontab配置表的文件格式 xff0c 并对自动执行脚本文件时的注意事项进行了说明 xff0c 主要包括以下几个方面 xff1a cron守护程序概述crontab配置表cr
  • 用Imagex备份&还原Windows7简明教程+本人编写的批处理+解说Imagex常用命令

    用Imagex备份 amp 还原Windows7简明教程 43 本人编写的批处理 43 解说Imagex常用命令 2012 03 26 23 32 53 分类 xff1a Windows 7 探索实 标签 xff1a 举报 字号 大 中 小
  • Android 硬件版本问题(M/Q/O/RM)

    M gt MTK Q gt 高通 O gt 海外 RM gt 国内 个人理解 xff1a 软件在编写的过程中 xff0c 为了适配不同的硬件 处理器 xff0c 要搞不同的内置版本
  • 学成在线笔记三:CMS管理页面开发

    注意 xff1a 我是用的element ui的版本位 xff1a 2 10 1 xff0c 若要使用本博客中的前端代码 xff0c 建议修改为相同版本 修改方式 xff1a 修改根目录下的package json中dependencies
  • vue3 和 vite3脚手架相关20个库

    学会这 20 个库 xff0c 让你快速看懂 vue3 和 vite3 源码 x1f680 前言 写一个开源的项目也不例外 xff0c 就拿在国内很火的 vue3 框架 和 vite 工具 来讲 xff0c 其中的实现与架构设计无不是一个
  • SQL高级优化

    知识回顾 1 git版本控制工具 xff0c 主要管理项目的代码文件 它相比CVS SVN它特点 xff0c 可支持分布式 外网 离线工作 主流代码管理工具 2 xff09 基本概念 工作空间 本地索引 本地仓库 远程仓库 就体积而言 xf