优化SQL查询:如何写出高性能SQL语句

别再折腾源码编译了!5分钟搞定ANTs医学影像工具(Mac/Ubuntu/CentOS) 本文介绍了ANTs医学影像处理工具的极速安装方法,通过预编译版本实现5分钟内完成部署,大幅提升安装成功率和效率。详细步骤包括获取预编译包、环境变量配置及实战案例,帮助研究人员快速上手ANTs进行医学影像分析。 阅读详情

1、 首先要搞明白什么叫执行计划?

执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。

可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要:

(1) SQL语句是否清晰地告诉查询优化器它想干什么?

(2) 查询优化器得到的数据库统计信息是否是最新的、正确的?

2、 统一SQL语句的写法

对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。

select*from dual 

select*From dual

其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行!

3、不要把SQL语句写得太复杂

我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。

一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。

另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。

4、 使用“临时表”暂存中间结果

简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。

5、 OLTP系统SQL语句必须采用绑定变量

select*from orderheader where changetime >'2010-10-20 00:00:01'
select*from orderheader where changetime >'2010-09-22 00:00:01'

以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量

select*from orderheader where changetime >@chgtime

@chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。

6、 绑定变量窥测

事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是“倾斜字段”的时候。

“倾斜字段”指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中“民族”这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那“民族”这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。

试想如果@nation传入的第一个值是“汉族”,那整个执行计划必然会选择表扫描。然后,第二个值传入的是“布依族”,按理说“布依族”占的比例可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的“汉族”的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的“绑定变量窥测”,建议对于“倾斜字段”不要采用绑定变量。

7、 只在必要的情况下才使用begin tran

SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。

有些情况下,我们需要显式声明begin tran,比如做“插、删、改”操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。

可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。

Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。

8、一些SQL查询语句应加上nolock

在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存“数据前影”,该数据如果在修改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle 广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用 nolock有3条原则。

(1) 查询的结果用于“插、删、改”的不能加nolock !

(2) 查询的表属于频繁发生页分裂的,慎用nolock !

(3) 使用临时表一样可以保存“数据前影”,起到类似oracle的undo表空间的功能,

能采用临时表提高并发性能的,不要用nolock 。

9、 聚集索引没有建在表的顺序字段上,该表容易发生页分裂

比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。

比如“张三”的“contactid”是001,那么“张三”的订单信息必须都放在这张表的第一个数据页上,如果今天“张三”新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。

SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。

曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的 15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较低,因为查询时必须扫描那些没有数据的空位。

重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。

对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题!

10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读

加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。

上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。

11、使用like进行模糊查询时应注意

有的时候会需要进行一些模糊查询比如

select*from contact where username like ‘%yue%’

关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,

12、数据类型的隐式转换对查询效率的影响

sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。

13、SQL Server 表连接的三种方式

(1) Merge Join

(2) Nested Loop Join

(3) Hash Join

SQL Server 2000只有一种join方式——Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。

SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。

如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。

总结一下,在表连接时要注意以下几点:

(1) 连接字段尽量选择聚集索引所在的字段

(2) 仔细考虑where条件,尽量减小A、B表的结果集

(3) 如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧

文章转载自公众号:java一日一条:https://mp.weixin.qq.com/s/mHOP3maLeOdN8bELbYePEw

一、Sql Server SQL查询优化方法 Sql Server SQL查询优化方法 阅读详情

相关推荐

【技术纵览】行为识别前沿模型演进:从CNN到多模态大模型

本文全面解析了行为识别技术从CNN到多模态大模型的演进历程,重点介绍了SlowFast、TimeSformer、VideoMAE和InternVideo等SOTA模型的核心创新与应用实践。通过对比分析各代模型在Kinetics-400等数据集上的表现,揭示了自监督学习和多模态融合如何推动行为识别准确率突破85%,并探讨了工业部署中的技术选型策略与优化方向。

weixin_29169505的博客 155

聊聊sql优化的15个小技巧

前言 sql优化是一个大家都比较关注的热门话题,无论你在面试,还是工作中,都很有可能会遇到。 如果某天你负责的某个线上接口,出现了性能问题,需要做优化。那么你首先想到的很有可能是优化sql语句,因为它的改造成本相对于代码来说也要小得多。 那么,如何优化sql语句呢? ​ 我的个人技术博客:https://susan.net.cn​​​​​​​ ​ 这篇文章从15个方面,分享了sql优化的一些小技巧,希望对你有所帮助。 最近无意间获得一份BAT大厂大佬写的刷题笔记,一下子打通了我的任督二脉,越来越觉得算法没

9687

Verilog实战:手把手教你实现四路组相联Cache(附完整代码解析)

本文提供了一份详细的Verilog实战指南,手把手教你实现一个四路组相联Cache。内容涵盖从设计规格、核心存储阵列、LRU替换策略到状态机设计的完整流程,并附有代码解析与优化技巧,旨在帮助硬件设计者掌握Cache控制器的RTL实现与调试方法。

pp12345的博客 519

SQL语句优化的30种方法,总结的太棒了

1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2、应尽量避免在 where 子句中使用!=或操作符,否则将引擎放弃使用索引而进行全表扫描。3、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: 4、应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: ..

biyusr的专栏 2万+

W25N01GV SPI NAND Flash驱动开发避坑指南:详解2KB缓冲区机制与状态寄存器正确用法

本文深入解析W25N01GV SPI NAND Flash芯片的2KB缓冲区机制与状态寄存器正确用法,提供STM32 HAL和ESP-IDF项目的实战解决方案。涵盖双阶段操作原理、状态寄存器深度解析、时序控制优化及跨平台驱动设计要点,帮助开发者避免常见错误并提升存储性能。

aizhouqian5537的博客 640

nRF52811墨水屏时钟DIY:从全刷到局刷的实战改造指南(附完整代码)

本文详细介绍了如何将基于nRF52811的墨水屏时钟从耗电的全屏刷新模式改造为高效的局部刷新模式。通过剖析全刷与局刷的原理差异,提供了从工程架构、驱动层适配到应用层逻辑重构的完整实战指南,并附上关键代码示例。改造后,设备功耗显著降低,续航大幅提升,同时解决了视觉闪烁问题,是DIY低功耗墨水屏应用的实用参考。

weixin_29194693的博客 356

关于SQL优化的二十个小方法

关于SQL优化的二十个小方法

weixin_72984629的博客 2574

《AgentScope-Java 深入浅出教程》第1章 AgentScope-Java 简介

AgentScope-Java 是一个面向智能体的编程框架,专门用于构建基于大语言模型(LLM)的 AI 应用程序。│ 你的业务应用 ││ AgentScope-Java 框架 ││ │ 智能体 │ │ 工具 │ │ 记忆 │ │ 模型 │ ││ LLM 服务 (DashScope/OpenAI/...) │能力说明类比ReAct 推理让智能体能够"思考"并"行动"就像人类思考后再做事工具调用让智能体能够执行外部操作就像人使用计算器、搜索引擎记忆管理让智能体能够记住对话历史。

步子哥的博客 595

SQL写法优化:如何写出高性能的查询语句

写出高性能的SQL,是一种意识和习惯。JOIN优先: 谨慎使用子查询,尤其是相关子查询,优先考虑用JOIN改写。指名道姓: 严禁使用SELECT *,务必明确指定所需字段。深分页优化: 遇到分页查询,立即思考如何避免巨大的OFFSET,采用“书签”方案。保持字段纯洁: 避免在索引列上使用函数或计算。优化的本质是让数据库做它最擅长的事情——快速定位和读取数据,而不是做复杂的计算和过滤。下一篇预告《实战:从一次真实的CPU 100%故障说起》

✨ 欢迎来唠嗑、切磋、一起成长!👋 958

高斯过程的数学理解

G澳大利亚的过程是有益的,特别是当我们有少量数据时。当我在制造业担任数据科学家时,我们的团队使用这种算法来揭示我们接下来应该进行哪些实验条件。但是,此算法不如其他算法流行。在这篇博客中,我将通过可视化和 Python 实现来解释高斯过程 [1] 的数学背景。

gongdiwudu的专栏 3611

3 ATK2(AUTOSAR OS)代码移植-目标硬件及编译环境简介

该部分介绍ATK2代码移植的目标硬件以及编译环境

xiaoduanduansad的博客 721

如何写出高性能SQL语句—优化SQL查询

1、 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。 可见,执行计划并不是固定的,它是“个性化的”。产生一个

Java我人生的技术博客 5664

在 SAP S/4HANA 的 BP 事务里做保存前校验:BDT 事件、BUPA_FURTHER_CHECKS 与 CVI 扩展 BAdI 一次讲透

SAP BP事务保存前校验机制解析 摘要:本文系统梳理了SAP BP事务保存前的校验机制,揭示了三种关键校验点的差异与适用场景: BDT框架DCHCK事件:最靠近UI层,适合屏幕字段级校验,但API调用时可能失效 Classic BAdI BUPA_FURTHER_CHECKS:全局拦截点,可阻断整个BP保存,适合核心业务规则 CVI扩展校验:仅管控供应商/客户段落,需注意可能产生"BP已保存但段落未保存"的情况 文章通过真实案例(如黑名单校验、付款冻结等)展示了各校验点的最佳实践,并特

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 312

mysql高性能sql语句_优化SQL查询:如何写出高性能SQL语句

1、 首先要搞明白什么叫执行计划?执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“...

weixin_29129247的博客 173

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

优化SQL查询:怎样写出高性能SQL语句

1、 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。 可见,执行计划并不是固定的,它是“个性化的”。产生一个正确...

qq_30347133的博客 1981

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

优化SQL查询:如何写出高性能的SQL语句

优化SQL查询:如何写出高性能SQL语句 1、 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。 可见,

u014492098的专栏 579

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

[SQL优化技巧]如何写出高性能的SQL查询语句

应在经常用于查询条件的列(如WHERE子句中的列)、连接操作的列(如JOIN子句中的列)以及排序和分组的列(如ORDER BY和GROUP BY子句中的列)上创建索引。但需要注意的是,索引并非越多越好,因为索引会占用额外的存储空间,并在数据插入、更新和删除时带来额外的开销。此外,连接表时应注意表的顺序,将数据量较小的表放在前面,可以减少中间结果集的大小。此外,合理的数据库设计,如规范化与反规范化的平衡,也是保证查询性能的基础。通过以上技巧,开发者可以显著提升SQL查询的性能,构建更高效、稳定的数据库应用。

430
上一篇: SpringMvc整合ehcaech
下一篇: 反转字符串的四种方法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值