3种SQL语句优化方法,测试人必知必会!

关于SQL语句的优化,本质上就是尽量降低SQL语句的执行时间,对于如何降低SQL语句的执行时间,可以从以下几个方面入手。

一、降低SQL语句执行时的资源消耗

这是我们在数据库性能调优中常用的方法,该方法以分析SQL语句的执行计划为切入点,核心思路是找到执行计划中开销较高的操作,通过改写SQL语句或改变表访问方式调整执行计划,从而达到降低SQL语句执行消耗,缩短执行时间的目的。

对于改变表访问方式,常见的手段是使用索引替代开销较高的全表扫描,但这种方式不是万能的,是有一定的使用前提的,有时候,滥用索引反而会带来较高的性能开销。

以下列举一些适合采用访问索引的方式替代原有操作的案例。

1. 使用索引替代全表扫描

如果查询结果集只占表中的一小部分数据,这时,可以采用索引访问的方式替代全表扫描,即使不能达到索引覆盖而产生回表操作,其开销也小于采用全表扫描操作。

例如,使用Oracle数据库存储,一个用户信息表

user(userid,username,sex,tel,code),code列表示用户的社保号信息,系统运行之初允许社保号信息为非必填项,这就导致少部分code列的值为null,为了提高对code列检索的效率,我们为code列创建了普通B树索引inx_code(code),要查询所有未提供社保号的那部分用户信息,之后系统为这部分用户发送信息,提示补全社保号信息,语句如下:

select * from user where code is null;

语句执行后,用时20秒左右,user表中存在50万条左右的用户记录,返回的未提供社保号的用户记录有5000条左右。

通过分析执行计划,在查询执行时采用了全表扫描方式,这是造成查询执行时间较长的主要原因。

对于B树单列索引,null值将使得索引失效,所以优化器采用了全表扫描方式。

该查询实际返回记录5000条左右,表中共有记录50万条左右,实际返回的记录只占表总记录的1%,这时,可以采取使用索引扫描替代全表扫描。

如何使得包含null值的列在检索时可以使用索引呢,这就需要将基于B树的单列索引改为复合索引,将原有索引修改为inx_code(code,0),再次执行查询,对user表的访问方式由全表扫描改为索引范围扫描,执行时间降至1秒之下。

现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:691998057【暗号:csdn999】

2. 利用索引的有序性消除排序操作

在对数据库的访问中,排序是一种开销较搞的操作,数据库为了完成排序操作,需要扫描表中的所有记录,之后采取相应的算法对记录进行排序。

如果表中的记录随系统的运行累积增加,那么排序操作的执行开销会逐渐变大,执行时间会越来越长。

索引是有序的,因为相应的索引键值已经事先按一定规则完成排序,如果SQL语句中需要按表中的某列进行排序,此时,可以为该列创建索引,从而达到通过索引扫描代替完成排序需要的全表扫描,达到降低访问开销,缩短执行时间的目的。

例如,在MySQL8.0数据库中,如果需要对多个列进行排序,且排序顺序有升有降,即:order by col1,col2 desc,此时,可以为两个排序列创建一个复合降序索引idx_col1_col2(c1,c2 desc)

3. 利用索引改变表关联方式

在执行表关联查询操作时,数据库的优化器可能选择了不合理的表关联方式,使得表关联查询开销较高,耗时较长。

例如,PostgreSQL数据库中有userureorg三个表,分别存储系统用户信息、已完成认证的用户信息和相应的组织信息。有如下的查询语句:select *  

from user join ure on user.id=ure.id join on org on ure.oid=org.oid

where org.pcode=’12012’

order by ure.update;

该查询的执行计划如下图所示:

查询执行用时32毫秒,开销为2206。

通过执行计划我们发现,userureorg三表关联均采用了Hash Join的关联方式,这种关联方式是最优的吗?

分析表连接方式,org表是第一个关联的驱动表,该表过滤后的结果集只有24条记录,结果集很小,所以,可以将org表与user表的连接方式调整为嵌套循环连接方式。

此外,对org表的访问采用了全表扫描,可将其调整为索引扫描。

为查询org表的where条件列pcode列创建索引,同时为作为嵌套循环连接的被驱动表user表的关联条件列oid列创建索引,本次调优后的执行计划如下图所示。

改变org表与user表的连接方式后,执行时间降低为4.85ms,执行开销降低到273。

进一步分析调优后的执行计划,org表与user表连接后的结果集只有47条记录,该结果集与ure表的连接方式仍可以调整为嵌套循环连接,以该结果集作为驱动表,ure表作为被驱动表。为达到该目的,为ure表的连接条件列id设置索引即可。

最终的执行计划如下图所示。

由此可见,将表连接方式全部由Hash连接调整为嵌套循环连接后,执行时间最终降至1ms,执行开销降至30。

二、并行执行SQL语句

这种方式是通过增加额外的资源消耗来换取SQL执行时间的缩短,其意义类似于代码优化中的“以空间换时间”的策略。

增加的额外资源主要是指数据库服务器的处理器(CPU)、内存、I/O等硬件资源。

例如:在Oracle数据库中,对于一个查询操作,如果其所作的工作可以分割成多个互不相关的部分,则该查询可以由多个进程并发执行。可以并行执行的查询操作主要有全表扫描、快速索引全扫描、分区索引范围扫描、以及需要执行全表扫描完成的表连接。

三、避免不必要的资源争用导致SQL执行效率下降

有些SQL语句,其执行时间不定,时快时慢,这些语句的执行计划自身未存在问题。导致语句执行效率差的原因是语句执行时,数据库服务器在执行其他消耗资源的操作,出现资源争用的情况。

例如:某系统每日凌晨定时执行统计信息收集工作,如果这时对系统执行性能测试,涉及对该数据的查询操作将受到影响,导致性能测试结果不准确。因此,性能测试需要避开数据库执行统计信息收集的时间。

以上对SQL语句的优化方法做了简要的介绍,下面对SQL语句的优化步骤和方法做一个说明和总结。

  • 1. 找到执行时间较长、消耗资源较多的SQL语句。例如:MySQL数据库可从慢查询日志中获取,Oracle数据库可查看AWR报告。

  • 2. 分析以上获取的性能较差的SQL语句的执行计划,找到执行计划中开销较高的部分,评估执行计划是否合理,是否需要调整。

  • 3. 对于执行计划中开销较高的部分,采取相应的措施降低执行开销,缩短执行时间,例如如下方式:

  • (1)如果是统计信息不准确导致生成了错误的执行计划,需要首先重新收集统计信息;

  • (2)如果是SQL语句编写存在问题,可以在不改变业务逻辑的前提下对SQL语句进行适当的改写;

  • (3)对于不必要的全表扫描或排序,可以通过创建合适索引消除全表扫描和排序;

  • (4)如果因为某些原因导致SQL语句的执行计划不稳定,在条件允许的情况下,使用提示器(Hint)固定SQL语句的执行计划;

  • (5)如果因为表或索引本身设置不合理,导致执行开销较高,用时较长,则应该对表或索引重新设计,例如:表中记录过大,超过亿级,此时应考虑分表分库;

  • (6)对于具备并行执行的部分,考虑采用并行执行的方式;

  • (7)如果是业务设计不合理导致SQL语句执行效率低下,应考虑修改业务逻辑。

END

下面是配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

最后: 可以在公众号:程序员小濠 ! 免费领取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!

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

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

相关文章

Qt程序设计-报警灯自定义控件实例

本文讲解Qt报警灯自定义控件实例。 实现功能 设置边框和内部颜色。 设置是否闪烁点亮。 添加的报警灯类 #ifndef LIGHT_H #define LIGHT_H#include <QWidget> #include <QDebug> #include <QPainter> #include <QTimer>class Light : public QWid…

Python实用技巧:处理JSON文件写入换行问题

Python实用技巧&#xff1a;处理JSON文件写入换行问题 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 &#x1f448; 希望得到您的订阅…

linux中将普通用户添加sudo权限

1.登录root权限账号&#xff0c;编辑/etc/sudoers文件 2.找到"root ALL(ALL) ALL"&#xff0c;并在下面添加普通用户 格式&#xff1a;username ALL(ALL) ALL vim /etc/sudoers ## Next comes the main part: which users can run what software …

理解大数据处理过程中的小文件问题

相信很多开发都知道这个问题&#xff0c;看文章&#xff0c;看博客都有了解过。但是如果让你自己讲&#xff0c;能不能从头到尾讲明白原理和对应的解决方案呢&#xff1f; 这个小文件是怎么产生的&#xff1f;就一句话&#xff0c;spark处理完数据输出时&#xff0c;一个分区一…

CMake和VsCode调试的使用

目录 CMake使用 CMake下载 创建系统文件目录 MakeList编写规范 VsCode启动调试 添加配置文件 添加断点&#xff0c;启动调试 CMake使用 CMake下载 输入指令 sudo apt install cmake 安装cmake&#xff0c;使用 cmake -version可查看cmake的版本信息 创建系统文件目…

土耳其商务团一行莅临优积科技考察交流

7月31日土耳其商务代表Emre Arif Parlak等一行三人莅临优积科技考察交流&#xff0c;公司CEO刘其东携团队成员热情接待并深入交流。 商务团首先参观了我司产品生产基地&#xff0c;详细了解了钢结构模块的生产加工工艺流程和质量控制体系。随后参观了我司模块化学校样板房、模块…

Python-语句

一、if语句 格式 if 条件&#xff1a; 条件成立执行的代码 if True:print(条件成立执行的代码) print(这个代码执行吗?)上述代码两个print均执行 if False:print(条件成立执行的代码) print(这个代码执行吗&#xff1f;)只执行第二个print 2.总结 对于未缩进的代码&#x…

Git+py+ipynb Usage

0.default config ssh-keygen -t rsa #之后一路回车,当前目录.ssh/下产生公私钥 cat ~/.ssh/id_rsa.pub #复制公钥到账号 git config --global user.email account_email git config --global user.name account_namebug of ipynb TqdmWarning: IProgress not found. Please …

Springboot日常总结-@RestController和@Controller的区别

RestController和 Controlle是两种不同的控制器实现&#xff0c;它们的主要区别在于如何处理返回的数据和是否支持跳转到视图页面。 Controller 是一个基本的控制器注解&#xff0c;它允许你将一个类标记为一个Spring MVC控制器处理器。使用 Controller 的类中的方法可以直接返…

c++学习记录 string容器—字符串比较

比较方式&#xff1a; 字符串比较是按照字符的ASCII码进行对比 返回 0> 返回 1< 返回 -1 函数原型&#xff1a; int compare(const string& s) const; //与字符串s比较int compare(const char* s) const; //与字符串s比较 #include<iostream> using name…

一文1400字使用Jmeter进行http接口测试【建议收藏】

前言&#xff1a; 本文主要针对http接口进行测试&#xff0c;使用Jmeter工具实现。Jmter工具设计之初是用于做性能测试的&#xff0c;它在实现对各种接口的调用方面已经做的比较成熟&#xff0c;因此&#xff0c;本次直接使用Jmeter工具来完成对Http接口的测试。 一、开发接口…

【JavaSE】集合框架

目录 程序场景分析 Java集合框架包含的内容List接口ArrayListLinkedListList接口的常用方法ArrayList案例背景分析代码示例扩展以下功能代码示例 LinkedList案例背景分析代码示例LinkedList的特殊方法 ArrayList与LinkedList对比 Set接口HashSet 集合的特点常用方法案例背景分析…

[c 语言] 大端,小端;网络序,主机序

在网络编程中&#xff0c;特别是底层网卡驱动开发时&#xff0c;常常遇到字节序问题。字节序指的是多字节数据类型在内存中存放的顺序&#xff0c;高位保存在低地址还是高地址&#xff0c;以此来划分大端还是小端。 1 大端和小端 大端和小端指的是 cpu 的属性&#xff0c;常见…

Vulhub 靶场训练 DC-9解析

一、搭建环境 kali的IP地址是&#xff1a;192.168.200.14 DC-9的IP地址暂时未知 二、信息收集 1、探索同网段下存活的主机 arp-scan -l #2、探索开放的端口 开启端口有&#xff1a;80和22端口 3、目录扫描 访问80 端口显示的主页面 分别点击其他几个页面 可以看到是用户…

SpringBoot源码解读与原理分析(三十四)SpringBoot整合JDBC(三)声明式事务的传播行为控制

文章目录 前言10.5 声明式事务的传播行为控制10.5.1 修改测试代码&#xff08;1&#xff09;新建一个Service类&#xff0c;并引用UserService&#xff08;2&#xff09;修改主启动类 10.5.2 PROPAGATION_REQUIRED10.5.2.1 tm.getTransaction&#xff08;1&#xff09;获取事务…

一拖二ADG数据库拆除其中一个复制关系

一、备库一操作 1、检查 select name,open_mode,switchover_status,database_role from v$database; select group#,thread#,status from v$standby_log; select thread#,sequence#,first_time,next_time,applied from v$archived_log where thread#1 order by 4; select …

用于自监督视觉预训练的屏蔽特征预测

Masked Feature Prediction for Self-Supervised Visual Pre-Training 一、摘要 提出了用于视频模型自监督预训练的掩模特征预测&#xff08;MaskFeat&#xff09;。首先随机屏蔽输入序列的一部分&#xff0c;然后预测屏蔽区域的特征。研究了五种不同类型的特征&#xff0c;发…

netfilter内核实现

Netfilter是Linux内核中的一个框架&#xff0c;用于实现数据包的过滤、NAT(Network Address Translation)、连接追踪以及其他网络功能。Netfilter框架的主要实现包括如下几个部分&#xff1a; 钩子函数&#xff08;Hooks&#xff09;&#xff1a;Netfilter框架在Linux内核中通…

遥感、航拍、影像等用于深度学习的数据集集合

遥感图像的纹理特征异常繁杂&#xff0c;地貌类型多变&#xff0c;人工提取往往存在特征提取困难和特征提取不准确的问题&#xff0c;同时&#xff0c;在这个过程中还会耗费海量的人力物力。随着计算力的突破、数据洪流的暴发和算法的不断创新&#xff0c;在具有鲜明“大数据”…

我们的C++(基础)(中文翻译版)

什么是C&#xff1f; C是一种高级语言。它由 Bjarne Stroustrup 于 1979 年在贝尔实验室设计和开发。C 是一种面向对象的编程语言&#xff0c;它扩展和改进了 C 语言。C 可在各种平台上运行&#xff0c;例如 Windows、MAC 操作系统和 UNIX 版本。 C 是一种静态类型、编译、通…