【SQL】关于SQL Server的性能优化——基础内容
【一些网课后的笔记与后续学习的思考】
平时我们觉得查数据很慢,这个慢是什么意思?
就是在现有资源达到最大吞吐量的前提下,系统不能满足合理的数据请求的一些表现。
一、调优时,可以从以下五点考虑
① 最小化SQL相应时间
② 合理地增加吞吐量
③ 减少网络延迟
④ 优化IO
⑤ 减少最小化
二、调优要达到的目标
使系统能有协调、平衡地运作,合理地响应外部及内部请求,实现资源利用的最大化。
三、性能调优的误区
1、增加硬件就能缓解性能问题
增加硬件或许会让系统性能更好,但没有解决真正的问题所在
2、只要数据库性能好就没问题
不要把很多本该在应用层实现的逻辑放到数据库实现,以此希望优化数据库就能解决性能问题
3、任何的数据库性能问题都可以通过索引解决
性能问题的解决思路:
检查日志,发现问题所在——优化SQL语句或修改表结构——最后才是考虑建立索引
4、编码过于激进或极端
任何功能都有自己的场景,要根据自己的企业形式、开发模式和技术栈去综合考虑,切忌一刀切(比如:要么全部使用存储过程实现功能,要么完全不允许使用存储过程)
四、影响性能的常见因素:
1、数据库结构的设计
①了解业务、满足业务,性能只是业务之外的附属属性
②优先考虑第三范式设计(字段冗余可以避免过多的表关联,但是字段冗余会让维护成本提升。这时就需要对维护成本和过
③多关联查询影响性能进行权衡)
④表关联要尽可能地少
⑤坚持最小原则:使用尽可能小的字段长度
⑥在适当的地方使用约束:但是,安全方面还是最重要的,千万不要为了性能而放弃对安全的追求!因为我们并不需要极致的性能,而是性能在一定范围内可以承受就可以了。
2、事务和隔离的级别
3、T-SQL的编写
数据库性能的优化,基本都是针对SQL语句的优化。编写健壮的T-SQL语句,让我们的代码更稳定,更高效地执行
①编写语句前,要完全了解业务的需求,知道表的用途和用法,明确查询目的
②只查询需要的字段,避免返回所有字段(select * from )
③限定好查询地结果集(select top 100 …)
④使用有效的索引,确保业务需要用到的过滤字段能使用索引,是否有必要在字段上添加索引
(当需要对数据进行过滤时,应当优先考虑使用索引字段。要是有多个索引字段可供选择,优先选择筛选率较高、重复率较低的索引字段作为过滤条件)
⑤不要对有索引的字段使用计算、函数等运算符,因为会导致查询优化器无法使用索引进行数据的检索,从而导致表触发扫描操作
⑥order by字句的性能,取决于参与排序操作的数据量大小。
(排序操作会在数据筛选完以后,对筛选出的结果集进行排序。因此对需要进行排序的操作,应将排序的操作控制在结果集和数据量都尽量小的查询中,避免不必要的CPU消耗。不然,当排序操作超过可以分配的内存大小时,就会把排序的中间数据放在TempDb,增加I/O操作,导致性能大大下降)
⑦尽量使用简单的SQL语句来实现业务功能
简单的SQL语句:只关联2-4个表、单表查询、只有2-3个过滤条件,并且有一个过滤条件明确可以使用索引查找操作
4、硬件资源
五、执行计划的分析
在SQL优化中,都是以SQL语句的执行计划中的开销去判断最优的语句。
SQL语句的处理流程如图示:
1、T-SQL语句
没啥好说的,就是你的SQL语句
2、语法分析
编译语法,检验语句和语法是否合规、正确,然后把T-SQL语句转化为逻辑查询树(树里包含各种逻辑代数运算:inner join…)
3、绑定
把逻辑树的节点与数据库的实际对象(比如你要查询的表)进行绑定。检验所有查询引用的对象是否都在数据库中。检验完成通过,就把逻辑树转换为绑定树,并加载各种元数据(表里相关的约束、索引…)
4、优化
使用绑定树,通过优化产生一个预估的执行计划。SQL优化器尽可能寻找最优方案(随着SQL语句的表关联和过滤条件的复杂度,方案的选择会越多,所以有可能会找到不适合的方案)
查询优化器只能基于成本选择出成本最低的一个执行计划。成本的评估和优化过程,需要大量的资源,在选择合适的计划上,SQL设置了一些阙值,以某个阙值为基准来评估优化的成本和执行计划的代价。
4.1简化
对查询进行简化,移除一些无用的条件。
4.2普通计划搜索
4.3更新统计信息
4.4基于开销的优化
真正的优化阶段,CBD阶段,分三个阶段
阶段0:分析出一些执行计划,成本小于SQLServer内定的阙值的话,选择当前这个阶段的执行计划,成本大于SQLServer内定的阙值的话进入阶段1
阶段1:快速计划,没有合适的执行计划。判断是否可以使用并行操作,当并行的执行计划成本小于串行的执行计划成本,进入阶段2
阶段2:完全优化。最综合、最全面的分析,对所有可用的优化进行全盘分析,最终选择成本最低的,退出优化。
当你的表关联少于三张,是不会进入【基于开销的优化】这个节点的,因为方案只有一个,不会进到优化阶段,优化阶段不会有开销。而当你的SQL语句越复杂,查询优化器就越消耗成本和查询时间。
5、执行
语句的执行计划中,每个运算符都有自己的开销,执行计划运算符的详细信息和各种指标如下:
- Estimated Number of Rows 预估扫描影响的行数。
- Estimated row size 操作符生成的行的估计大小(字节)。
- Estimated Data Size 预估影响的数据的大小。
6、返回结果
SQL语句执行后的输出结果
7、执行计划展现方式
执行计划可以以:图像方式、文本方式和XML方式进行展现来分析。
7.1、图像方式
如果T-SQL语句过于复杂,会产生较大的流程图像
7.2、文本方式
- SET SHOWPLAN_TEXT ON(只开启执行计划,不包括详细的评估值)
要分步执行每一个语句
文本方式展示执行计划,执行SQL语句,关闭文本展示方式
- SET SHOWPLAN_ALL ON (开启所有的执行计划明细,包括各个属性的评估值 )
7.3、XML方式
XML方式提供的信息是最为全面的
六、执行计划中不同的运算符
执行计划里组成的单元之一,用来完成某个特定的任务。每个运算符都实现一个单独的基本操作,比如:表扫描、索引扫描、索引查找、键查找、RID查找…
1、阻塞运算符和非阻塞运算符
阻断和非阻断的区别就是:运算符是否在输入数据的时候能够直接输出结果数据
阻断
一个运算符所产生的输出结果需要等待所有的数据输入
比如select count(*) from user_info,要等待所有的数据行输入才能 count(计算)出行数非阻断
一个运算符在消耗输入行的同时生成输出行
要尽量的使用非阻断式操作来代替阻断式操作,这样才能更好的提高响应时间
2、逻辑运算符和物理运算符
2.1、逻辑运算符
逻辑运算符和比较运算符一样,都是返回 true 或 false 值的布尔数据类型
AND、OR、NOT、IN、EXISTS、LIKE、BETWEEN…
2.2、物理运算符
每个物理运算符都是一个执行某项操作的对象或例程。
SQL Server默认支持三种物理连接运算符:嵌套循环连接、合并连接以及哈希连接。
3、数据访问运算符(扫描、查找)
根据表类型(堆表、聚集索引表)不同,数据访问运算符也不同
3.1、扫描运算符:表扫描、聚集索引扫描、非聚集索引扫描
- 表扫描(Table Scan)
无任何条件地对整张表进行全表扫描
--举例:user_info_no_key表中,无主键(既无聚集索引)
select *
from user_info_no_key
- 聚集索引扫描(Clustered Index Scan)
表中的所有数据行都存在于聚集索引的业节点中。相当于将整个表中地数据都取出来。
--举例:user_info表中,自增的id字段作为主键(既有聚集索引)
select *
from user_info
- 非聚集索引扫描(Index Scan NoClustered )
发生在查询的数据都包含在已经定义好的索引中,就不需要扫描全表,只需将索引中的数据取出即可。(亦称为覆盖索引)
--举例:user_info表中,自增的id字段作为主键,对user_id,user_phone都建立了非聚集索引,查询的所有字段都定义有索引
select user_ids,user_phone
from user_info
- 关于扫描
数据库中,一旦出现扫描操作(Scan),就会有性能问题。因为扫描操作不仅需要等待大量的IO,还需要消耗许多内存来存储相关的数据。当数据库的缓存池中剩余空间不足的时候,它就需要把数据写到内存中。这个时候,数据库就会利用利用淘汰算法将缓存中的数据进行清理,然后再继续填充数据。
当我们频繁地出现大量数据的淘汰,那么缓存中的数据也会频繁地交替,这时候就会造成数据库操作的性能瓶颈。
所以在开发业务系统的时候,应尽量避免大数据量的搜索。
3.2、查找运算符:聚集索引查找、非聚集索引查找、键查找(标签查找的一种)、RID(行ID查找)
- 聚集索引查找(Clustered Index Seek)
发生在对聚集索引字段进行where条件过滤的情况下
--举例:user_info表中,自增的id字段作为主键,既聚集索引。对聚集索引字段进行where条件过滤
select *
from user_info
where id=1
- 非聚集索引查找(Index Seek NoClustered )
发生在对非聚集索引字段进行where条件过滤的情况下
--举例:user_info表中,自增的id字段作为主键,对user_id,user_phone都建立了非聚集索引,对非聚集索引字段进行where条件过滤
select user_ids,user_phone
from user_info
where user_phone='11111111111'
4、关联运算符(嵌套循环、合并连接、哈希连接)
4.1、嵌套循环
外部输入的每一行,都会扫描内部大数量输入,然后输出匹配的行。
即两张表通过关键字关联,然后再进行双层循环,两张表依次关联,最后通过关键字进行筛选。(其实就相当于两层for循环,输出符合条件的值)
4.2、合并连接
从两个数据集中各取一个值进行比较,如果相符,就把两行连接起来返回,如果不相符,就把小的去,一直到两个表中某一个表的行扫描结束。
(合并连接相对于嵌套循环,对大表的操作比较高效)
4.3、散列链接(哈希连接)
顶部输入的每一行生成哈希表(Hash keys build),每一行进行哈希计算,生成哈希桶。(非常消耗资源的算法)
4.4、嵌套循环、合并连接和哈希连接的应用对比
嵌套循环 | 合并连接 | 哈希连接 | |
---|---|---|---|
最佳场景 | 数据集相对较小,内部表的关联没有索引 | 数据集中等或较大,关联字段有索引且已排序或结果集已排序 | 数据集较大,适合数据仓库下的复杂查询 |
并发性 | 大量并发 | 有索引的多对多时并发性较好 | 不建议大并发 |
关联字段是否相等 | 否 | 是 | 是 |
是否使用额外内存 | 否 | 已排序下不需要 | 是 |
是否使用TempDb | 否 | 多对多情况下需要 | 是 |
数据集是否需要排序 | 否 | 是 | 否 |
期望输入数据集要排序 | 外部表已排序 | 是 | 否 |
5、聚合运算符(流聚合、哈希聚合)
5.1、流聚合Stream Aggregate(标量聚合)
- max()、min()、avg()、count()、sum()
Compute Scalar:计算标量的运算符
在流聚合产生的结果项数据类型为Bigint类型,而默认输出为int类型,所以增加了一个类型转换的运算符。
- 有group by分组的语句
当group by的字段无索引时,会出现sort(排序)节点,占用开销,一旦出现sort运算符,开销一般都是比较大的。
所以,对于流聚合的一种优化方式:
要避免sort排序的产生,就需要group by的字段在索引覆盖范围内。
5.2、哈希聚合(散列聚合)
group by的字段无索引,并且表为大数据、大规模的表
(当对无索引的字段创建索引,哈希聚合会变成流聚合)
5.3、流聚合和哈希聚合的应用对比
流聚合 | 哈希聚合 | |
---|---|---|
最佳场景 | 小规模且输入已排序 | 中大型未排序输入 |
是否要求输入排序 | 是 | 否 |
是否阻塞操纵 | 否,排序时可能阻塞 | 是 |
是否使用内存 | 否 | 是 |
是否使用TempDb | 否 | 否,内存不足时可能会使用 |
- TempDb
SQL Server中的一个系统数据库,用于存储查询过程中产生的中间数据。
(TempDb存储在磁盘上,所以只要用到TempDb的操作,就会影响I/O,比如sort排序和哈希连接)
6、联合运算符(union all、union)
6.1、union all:将两个数据集结果合并
6.2、union :将两个数据集合并后进行去重
一旦出现sort,就意味着资源的消耗,所以,这里可优化的地方就出来了,就是把sort排序去掉或更换。
七、结束语
就…先到这里吧,主要简单记录了一下关于SQL Server调优时要关注的一些因素,还有一些基础的运算符。
进阶的话,就是在这些基础上,如何展开实际的SQL开销分析、语句运行时的指标监测,然后进行SQL的优化和改写。
【SQL】关于SQL Server的性能优化——基础内容,记录,打板!
【SQL】关于SQL Server的性能优化——基础内容相关推荐
- Sql Server查询性能优化之索引篇【推荐】
Sql Server查询性能优化之索引篇[推荐] 这篇是索引系列中比较完整的,经过整理而来的 一 索引基础知识 索引概述 1.概念 可以把索引理解为一种特殊的目录.就好比<新华字典>为了加 ...
- 【SQL Server】性能优化-索引
性能优化-索引 1 索引 1.1 什么是索引 1.2 索引的存储机制 1.3 创建索引原则 1.4 如何创建索引 1.4.1 创建索引 1.4.1 删除索引 1.4.1 显示索引 1.5 索引使用次数 ...
- SQL Server 查询性能优化——覆盖索引(二)
在SQL Server 查询性能优化--覆盖索引(一) 中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索 ...
- Sql Server查询性能优化之走出索引的误区
据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会.也什么没有必要去关心.了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是, ...
- 前端性能优化基础知识--幕课网
作为一个前端小码农,在页面样式都能实现以后,就开始考虑:同一个效果,我该用什么样的方式和代码去实现它比较规范?前两天逛幕课网发现了两门课程–<前端性能优化-基础知识认知>和<前端性能 ...
- 由美团技术文章整理---spark性能优化基础篇--开发调优与资源参数调优
文章地址1:Spark性能优化指南--基础篇 - 美团技术团队 文章地址2:Spark性能优化指南--高级篇 - 美团技术团队 目录 一.关于性能优化基础篇--开发调优 1.避免创建重复RDD (1) ...
- SQL Server 2005 性能优化实战系列(文章索引)
http://www.cnblogs.com/gaizai/archive/2012/01/20/2327814.html 前言 性能优化是数据库方向一个很重要的技能,这也是快速提供企业级应用性能最快 ...
- SQL Server 追踪Profiler,SQL Server的性能优化工具
点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 SQL Server Profiler是什么 SQL Server Profiler是 ...
- SQL Server 数据库性能优化
对一个数据库来说,只能做到更优,不可能最优,并且根据实际需要,优化方案也是有所差异的,大概需要我们关心的有它的读取速度.存储空间.可维护性以及可扩展性等,而这些方面往往又是相互矛盾的,那么本文就着重讲 ...
最新文章
- python神秘的魔法函数_python进阶之魔法函数
- 【网络流】解题报告: luogu P2045 方格取数加强版(k取方格数)(最大费用最大流)
- 指纹传感器沾水便失效的原因解析
- Mysql 出现Got error 28 from storage engine
- 性能优化(7):教你正确使用css选择器
- 信息学奥赛一本通 1136:密码翻译 | OpenJudge NOI 1.7 09
- Jenkins报错Error fetching remote repo 'origin'真正解决办法
- hdu3094 A tree game
- dispatcherServlet源码分析之doDispatch
- qq企业邮箱创建过程
- ppt制作心得【转发】
- 【NLP】文本情感分析
- jar error in opening zip file
- 树莓派4B EC20 查看4G信号强度
- 卡特加特数字家庭又爆重磅合作!厦门火炬创投莅临卡特加特考察
- 希沃白板如何解决手机端播放课件内视频出现黑屏闪退
- Java SE 高级教程
- 基于php的学生公寓管理系统,php毕业设计学生公寓管理系统
- 系统安全及应用--账号安全控制
- 动漫网站源码设计与实现
热门文章
- ab 发送post请求 测试API性能
- cad怎样编辑标注文字?分享一个方法
- 各种智能跟随定位技术解剖
- 显卡---显卡驱动---CUDA---Cudnn
- 为什么苹果录屏没有声音_苹果手机自带录屏功能,打开声音录制方法
- 免费电脑纯净绿色好用的软件
- NVIDIA CUDA初级教程(P2-P3)CPU体系架构概述、并行程序设计概述
- mysql异地双活架构,银行跨数据中心数据库双活架构设计:五大难点攻克
- 集成学习(ensemble learning)干货系列(3)——Boosting方法详解
- WM_CTLCOLOR消息重载