SQL性能规范

一、随聊

记录一下吧,2023年7月13日00:11:11,现在的状态真的很,忙,干不完的活,希望巨大的压力,能够让自己快速成长,回想我这一路,21年大专毕业,用一年时间熟悉软件,快捷键,熟悉开发思维,数据库、JS、HTML、Java都只能算是皮毛,故而当年没有选择Java开发,目前从事数据分析,帆软报表,餐饮零售业务多一点,涵盖,财务、门店、产品、会员、供应链、加盟商等多种场景。越发觉得,成年世界的残酷,多少次想过放弃,想想自己身后空无一人,唯有自渡,便继续咬紧牙关砥砺前行。有感而发~最近加班有点严重,博客断更了很久了~

以下分享自己的工作笔记~~~

二、、SQL性能规范

简介:在项目中常用优化策略。针对本章的内容,需要掌握以下能力:

(1)了解数据库运算时基础的内存、硬盘交互,

(2)了解数据表扫描,基于对扫描的理解来提升SQL执行效率,

(3)了解执行计划,掌握到这一层级可以满足90%项目的需求。

基本理念:当我们执行SQL查询语句时,数据库的操作是先根据SQL语句从硬盘中获取数据,然后加载进内存中进行后续计算。由于SQL语句有执行的先后顺序,因此当SQL一开始查询的数据量越小,加载进内存时间越短,并且整个SQL执行也越快。

1、明确字段,不取多余

解释只取我们需要的字段,不用的不取。不要随意用“*”来查询全部。例如:

假设A表总共有10个字段,只需要用到其中两个字段,那么查询语句中只取我们需要的两个字段,速度比查询所有字段的速度快。

2、大表关联,先做过滤

解释大表关联查询语句中,做到先过滤再关联。不允许使用WHERE来进行关联。提前过滤好,在硬盘和内存交互上、内存计算上可以节省很多时间。

例如

 

3、提取共性,减少重复

解释SQL语句中有多处重复的子查询,可以将其提取出来,进行参数化,减少数据库查询次数。

例如,以下语句中重复使用了一个子查询:

SELECT employee_id, first_name, last_name,

       (SELECT department_name FROM departments WHERE department_id = employees.department_id) AS department_name,

       (SELECT AVG(salary) FROM employees WHERE department_id = 80) AS avg_salary

FROM employees

WHERE salary > (SELECT AVG(salary) FROM employees)

ORDER BY department_name;

可以将子查询提取出来进行参数化,如下所示:

CREATE VIEW department_names AS

SELECT department_id, department_name

FROM departments;

CREATE VIEW avg_salaries AS

SELECT department_id, AVG(salary) as avg_salary 

FROM employees

GROUP BY department_id;

SELECT employee_id, first_name, last_name, department_names.department_name, avg_salaries.avg_salary

FROM employees

JOIN department_names ON employees.department_id = department_names.department_id

JOIN avg_salaries ON employees.department_id = avg_salaries.department_id

WHERE salary > (SELECT AVG(salary) FROM employees)

ORDER BY department_name;

通过将子查询提取到视图中,并且使用JOIN语句将相关表连接起来,可以避免多次执行相同的子查询,从而提高查询效率。

4、减少不必要的扫描计算

解释:如果UNION ALL可满足要求,就使用UNION ALL,而不用UNION,因为UNION会有一个比较然后去重的过程,而UNION ALL没有。

5、经常查询的大数据量表,需要创建索引,过滤和排序尽量放在索引列上操作

解释:索引会提高SELECT效率,但是会影响到INSERT及UPDATE的效率。索引的介绍、什么时候应该加索引、什么时候不建议加索引等内容不在此赘述。

创建方式:

-- 新建索引

CREATE INDEX index_name ON table_name(column_name);

-- 新建组合索引

CREATE INDEX index_name ON table_name(column_name1, column_name2, ...);

-- 修改索引

ALTER TABLE table_name DROP INDEX index_name;

ALTER TABLE table_name ADD INDEX index_name (column_name1, column_name2, ...);

-- 删除索引

DROP INDEX index_name ON table_name;

-- 查询单表索引

SHOW INDEX FROM table_name;

6、避免显式转换、隐式转换导致索引失效

解释避免数据库运算时对索引列进行转换,例如:

(1)显示转换举例,假设索引列为日期型数据,和字符串型日期比较。

错误写法:TO_CHAR(T.索引列,'YYYYMMDD')>='20190715',

这里是用函数将索引列由日期类型转换为字符串类型,导致索引失效。

正确写法:T.索引列 >=TO_DATE('20190715',’YYYY-MM-DD’)

(2)隐式转换举例,假设索引列是一串字符串型的数字,取索引列值为1的数据。

错误写法:T.索引列=1

这里是数据库用隐式转换将索引由字符串类型转换成数值类型,导致索引失效。

正确写法:T.索引列=’1’

7、大表查询时,避免子查询中的排序计算,排序需放在执行计划最后一步

解释:尽量在子查询中避免ORDER BY、DISTINCT等语句。其中ORDER BY是对结果进行排序,而DISTINCT和GROUP BY是在计算过程中排序。子查询数据量较大时用EXISTS子句代替DISTINCT。

8、决策报表中,尽量将多个数据集合并为同一个数据集,减少并发数量

解释:一个数据集就是一个并发,数据集过多导致并发过高,数据库加载压力大,计算效率会降低。可以用以下方案减少决策报表中的数据集数量:

(1)将A、B、C三个指标的每月/每日的趋势,以年月/年月日为条件进行关联,而不是每个指标单独一个数据集。

(2)查询结果为一条记录的数据集,直接关联在一起,例如三个数据集A、B、C都返回一条记录,那么可以如下图进行数据集合并处理。

建议同比环比能一个数据集查询出来就用一个数据集查询

如下图

 

9、报表中控件的数据字典如果数据量过大,并且涉及到控件联动,此时将一个数据集拆开成多个数据集可以提高控件加载效率,与本条规则相违背,需要酌情考虑。

三、EXPLAIN 命令

EXPLAIN 命令来查看 MySQL 的查询执行计划

  1. id:每个 SELECT 子句或者操作表的唯一 ID。
  2. select_type:表示是哪种 SELECT 类型,例如 SIMPLE(简单 SELECT,不包含子查询或 UNION)、PRIMARY(最外层的 SELECT)、SUBQUERY(子查询)等。
  3. table:操作的表名。
  4. partitions:查询中涉及到的分区列表。
  5. type:表示用于执行查询的 Join 类型,例如 ALL,index,range,ref,eq_ref 等。
  6. possible_keys:可能用于查询的索引列表。
  7. key:实际使用的索引。
  8. key_len:表示索引字段长度。
  9. ref:表示索引和哪个字段或常量进行比较。
  10. rows:表示需要扫描的表行数。
  11. filtered:表示筛选出来的行占总行数的百分比。
  12. Extra:其他信息,如使用的索引类型、是否使用临时表、是否使用文件排序等。

四、按照优化程度从最好到最差的顺序排列:

  1. system:表示只有一行记录(例如SELECT ... FROM DUAL),这是最快的访问类型。
  2. const:表示通过索引一次就能找到的常量表达式。例如,根据主键或唯一索引进行等值查询。
  3. eq_ref:表示使用了等值连接,对于每个索引键值,表中只有一条匹配记录。这通常出现在使用主键或唯一索引进行连接的情况下。
  4. ref:表示使用非唯一索引进行等值查询或使用唯一索引进行不完全的索引查询。这可能返回多个匹配记录。
  5. range:表示通过索引范围扫描来获取记录,例如使用BETWEENIN或某些算术操作符进行查询。
  6. index:表示全索引扫描,通常出现在查询中没有使用索引或无法使用索引的情况下。
  7. all:表示全表扫描,需要遍历整个表以找到匹配的记录,这是最慢的访问类型。

五、SHOW INDEX指令

  • Table:表示所查询的表名。
  • Non_unique:表示索引是否允许重复值,如果为0则表示唯一索引,否则为非唯一索引。
  • Key_name:表示索引名称。
  • Seq_in_index:表示这个索引列在索引中出现的顺序,从1开始计数。
  • Column_name:表示索引列的名称。
  • Collation:表示索引列的字符集。
  • Cardinality:表示索引列的基数,即不同值的数量,数值越大则说明该索引是更加有用的。
  • Sub_part:表示索引列的子串长度,对于非字符串类型的索引列其值为null。
  • Packed:表示所有索引列使用的数据类型所占的字节数,数值越小则说明该索引更加紧凑。
  • Null:表示索引列是否允许为空。
  • Index_type:表示使用的索引方法,如 Btree、Hash 等。
  • Comment:表示索引的注释信息。

六、常用优化手段

1、删除单个索引,增加组合索引

2、修改处理时间条件的函数function_xx_month【针对SQL查询中使用函数处理】

3、改进重复数据集【针对帆软数据集重复、冗余问题】

4、将in子查询改为内连接

5、优化group by字段

6、开启缓存【如果SQL因业务场景是在无法继续优化,可以开启帆软数据集中的数据缓存,牺牲服务器的空间换取SQL执行的时间】

7、条件属性的删除【帆软报表中的条件属性、过滤、形态、公式计算比较多的时候需要考虑优化】

8、删除索引【过量的索引也会导致查询速度变慢】

9、将between and关键字换为>= <=【这个仁者见仁,自己测试部分场景下的SQL有显著提速,但是大多数情况下提速不明显】

七、总结

SQL的优化是一个不断试错的过程,同时观摩不同人的SQL风格,会有不一样的理解,如果你看的懂别人写的,静下心多看,这样自己写的时候,水到渠成,如果看不懂别人的SQL/代码,静下心慢慢看,只有看懂才会写!共勉!

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

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

相关文章

STM32 Proteus仿真医用仓库环境控制系统紫外线消毒RS232上传CO2 -0066

STM32 Proteus仿真医用仓库环境控制系统紫外线消毒RS232上传CO2 -0066 Proteus仿真小实验&#xff1a; STM32 Proteus仿真医用仓库环境控制系统紫外线消毒RS232上传CO2 -0066 功能&#xff1a; 硬件组成&#xff1a;STM32F103R6单片机 LCD1602显示器DHT11温度湿度电位器模拟…

golang中的【数组】相关知识点

目录 数组含义数组定义形式数组的声明初始化方式数组变量的类型 arr的特征数组的遍历遍历的用法二数组的值传递数组的引用&取地址 传送二维数组的相关操作定义二维数组初始化遍历 Golang是一种高效的编程语言&#xff0c;具有很多特性和优点&#xff0c;其中之一就是其对数…

RNN、LSTM、Seq2Seq

目录 时间序列表示梯度弥散和梯度爆炸RNN&#xff08;循环神经网络&#xff09;LSTMSeq2SeqELMo 时间序列表示 核心是加入历史信息去预测下一步骤 在NLP中&#xff0c;序列维度一般是这个样子:[b,seq_len,feature_len] b个句子&#xff0c;每个句子seq_len个单词&#xff0c;…

【复习10-12天内容】【我们一起60天准备考研算法面试(大全)-第十四天 14/60】

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

OK3588运行python程序对摄像头数据进行图像处理

OK3588运行python程序读取usb摄像头 硬件连接用工具测试验证摄像头工作正常python 读取usb摄像头并进行图像处理 硬件连接 把usb摄像头插入HOST的usb接口。 在串口终端运行 sudo v4l2-ctl --list-devices 如下图 当前的usb设备是 /dev/video74 用工具测试验证摄像头工作正常…

贪心算法、贪心搜索/采样(greedy search/sampling)、集束搜索(beam search)、随机采样(random sample)

首先需要了解贪心算法&#xff1a; 贪心算法&#xff0c;又名贪婪法&#xff0c;是寻找最优解问题的常用方法&#xff0c;这种方法模式一般将求解过程分成若干个步骤&#xff0c;但每个步骤都应用贪心原则&#xff0c;选取当前状态下最好/最优的选择&#xff08;局部最有利的选…

Android之Intent

意图介绍 一个意图(Intent)对象包含了目标组件、动作、数据、类别、附加数据、标志六个部分。 目标组件 目标组件可以帮助应用发送显式意图调用请求。在创建Intent时&#xff0c;可以通过setComponent方法来设置一个组件&#xff0c;如&#xff1a; //设置组件 intent.setC…

LRU 缓存

题目链接 LRU 缓存 题目描述 注意点 如果插入操作导致关键字数量超过 capacity &#xff0c;则应该 逐出 最久未使用的关键字函数 get 和 put 必须以 O(1) 的平均时间复杂度运行 解答思路 如果想以O(1)的速度进行get&#xff0c;则需要将对应的key、value存到map中如果想…

​ 基于单片机智能温室大棚控制系统

功能介绍 以51单片机作为主控系统&#xff1b; DS18B20温度采集模块检测温度&#xff1b; 光敏电阻和ADC0832组成的光照检测模块&#xff1b; 土壤湿度检测模块检测土壤湿度&#xff1b; CO2检测模块检测CO2浓度&#xff1b; LCD1602显示模块显示测量值、 若温度小于温度最…

【2023江西省研究生数学建模竞赛】第三题 植物的多样性 48页论文及Python代码

【2023江西省研究生数学建模竞赛】第三题 植物的多样性 48页论文及Python代码 相关链接 【江西省研究生数学建模竞赛】第一题 蒸汽发生器倒U型管内液体流动 70页论文及MATLAB代码 【江西省研究生数学建模竞赛】第一题 蒸汽发生器倒U型管内液体流动 70页论文及MATLAB代码 【2…

车道线检测|利用边缘检测的原理对车道线图片进行识别

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 这两个都是博主在学习Linux操作系统过程中的记录&#xff0c;希望对大家的学习有帮助&#xff01; 操作系统Operating Syshttps://blog.csdn.net/yu_cblog/category_12165502.html?spm1001.2014.3001.5482Linux S…

【深度学习】受限玻尔兹曼机 (RBM) 初学者指南

一、说明 受限玻尔兹曼机&#xff08;Restricted Boltzmann Machine&#xff0c;RBM&#xff09;是一种基于能量模型的人工神经网络。它只有一个隐层&#xff0c;将输入层和隐层中的每个神经元互相连接&#xff0c;但不同层的神经元之间没有连接。RBM是一种无向的概率图模型&am…

一套完全开源,支持多租户,界面配置单点的后端框架JVS

JVS的多租户体系统 在IT系统中&#xff0c;“租户”&#xff08;tenant&#xff09;通常用于指代一种多租户架构&#xff08;multi-tenancy&#xff09;&#xff0c;它是一种软件架构模式&#xff0c;允许多个用户或组织共享相同的应用程序或系统实例&#xff0c;但彼此之间的…

7.5 SpringBoot 拦截器Interceptor实战 统一角色权限校验

文章目录 前言一、定义注解annotation二、拦截角色注解1. 在拦截器哪里拦截&#xff1f;2. 如何拦截角色注解&#xff1f;3. 角色如何读取?4. 最后做角色校验 三、应用&#xff1a;给管理员操作接口加注解四、PostMan测试最后 前言 在【7.1】管理员图书录入和修改API&#xf…

JMeter 中 3 种参数值的传递

目录 前言&#xff1a; (一) 从 CSV 文件读取要批量输入的变量 (二) 利用 Cookie 进行值的传递 (三) 利用正则匹配提取上一个接口的返回数据作为下个请求的输入 前言&#xff1a; 在JMeter中&#xff0c;参数值的传递是非常重要的&#xff0c;因为它允许你在测试过程中动态…

右键pdf文件没有打印

问题描述 右键点pdf文件&#xff0c;弹出的菜单找不到打印选项。网上找了很多办法&#xff0c;然并卵啊。还是得靠自己慢慢摸索。 原因分析 新安装的win11系统&#xff0c;pdf文件默认可以用windows自带的edge浏览器打开。但是edge浏览器没有能力提供右键打印功能。 解决办法…

详解LeafLet中如何展示GeoServer发布的图层组

目录 前言 一、关于图层组 1、使用图层图组的好处 2、创建图层组 二、在Leaflet中展示图层组 1、新建Html模板框架 2、绑定地图map和底图设置 3、绑定图层组 总结 前言 在之前的博文中&#xff0c;曾经重点介绍如何使用LeafLet叠加Geoserver wms图层到已有底图的方法 ,…

Python应用:什么是爬虫?

文章目录 什么是爬虫虫之初&#xff0c;性本善&#xff1f;出行社交电商搜索引擎政府部门总结 面向监狱编程爬虫的君子协议什么是君子协议君子协议是怎么产生的&#xff1f;君子协议是什么内容&#xff1f;如何查看一个网站的robots协议违反君子协议的案例 参考文献 2022年初的…

x86架构ubuntu22下运行SFC模拟器zsnet

0. 环境 ubuntu22 1. apt安装 sudo apt install zsnes 2. 运行 zsnet 参考&#xff1a;在Ubuntu上用zsnes玩SFC游戏&#xff0c;https://blog.csdn.net/gqwang2005/article/details/3877121

Linux学习之系统默认打开的文件描述符、重定向

系统默认打开的文件描述符 一个进程默认会打开标准输入、标准输出、错误输出三个文件描述符。可以在/proc/PID/fd里边可以看到打开文件的描述符&#xff0c;PID需要改成具体的pid&#xff0c;比如可以使用A终端输入vim proctest之后按下回车键。 打开一个vim编辑窗口。 再打…