SQL Server数据库性能优化(一)之 优化SQL 语句-程序员宅基地

技术标签: 运维  数据结构与算法  数据库  

最近工作上基本没什么需求(好吧 不是最近是好久了,所以随便看看基础的东西来填补自己的空白)

原文出自:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html   转载请保留

数据库优化主要可以从以下几个方面入手

(1)架构级别,表结构设计:如良好的系统和数据库设计

(2)代码语句级别:优质的SQL编写

(3)索引设计:合适的数据表索引设计

(4)硬件因素:网络性能、服务器的性能、操作系统的性能,甚至网卡、交换机等

 

这里主要讨论最容易修改优化的 SQL 语句

准则1:1. 按需索取字段,跟“SELECT *”说拜拜

 字段的提取一定要按照“用多少提多少”的原则,避免使用“SELECT *”这样的操作。

做了这样一个实验,表tblA有1000万数据:

select top 10000 c1, c2, c3, c4 from tblA order by c1 desc  --用时:4673毫秒
select top 10000 c1, c2, c3 from tblA order by c1 desc --用时:1376毫秒
select top 10000 c1, c2 from tblA order by c1 desc --用时:80毫秒

由此看来,我们每少提取一个字段,数据的提取速度就会有相应的提升。但提升的速度还要看您舍弃的字段的大小来判断。
另外,关于“SELECT *“的问题,可以参考这篇文章:
http://www.cnblogs.com:80/goodspeed/archive/2007/07/20/index_coverage.html  //此文章评论争议很大 所以此处不推荐阅读

 

准则2:2. 字段名和表名要写规范,注意大小写
这一点要多注意,如果大小写写错的话,虽然SQL仍然能正常执行,但数据库系统会花一定的开销和时间先要把您写的规范成正确的,然后再执行SQL。写对的话,这个时间就省了。
正常的:    select top 10 dteTransaction, txtSystem_id from tblTransactionSystem
不小心的:select top 10 dtetransaction, txtsystem_id from tbltransactionsystem

 

准则3:3. 适当使用过渡表
把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。例如:

 

SELECT cust.name,rcvbles.balance,……other   columns     
FROM cust,rcvbles     
WHERE cust.customer_id = rcvlbes.customer_id     
AND rcvblls.balance>0     
AND cust.postcode>98000”     
ORDER BY cust.name

  如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:    

 

SELECT cust.name,rcvbles.balance,……other   columns     
INTO temp_cust_with_balance     
FROM cust,rcvbles     
WHERE cust.customer_id = rcvlbes.customer_id     
AND rcvblls.balance>0     
ORDER BY cust.name

 

  然后以下面的方式在临时表中查询:     

 

SELECT cl,c2 FROM temp_cust_with_balance WHERE  postcode>98000

 

临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。注意:过渡临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。

准则4. 别在where条件中做函数计算
这样做的后果是将在每个行上进行运算,这将导致该列的索引失效而触发全表扫描。如下SQL:

select * from users where YEAR(dteCreated) < 2007

可以改成

select * from users where dteCreated <2007-01-01

这样会使用针对dteCreated的索引,提高查询效率。

准则5. IN(NOT IN)操作符与EXISTS(NOT EXISTS)操作符
有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种方式的子查询。如下:
第一种方式使用IN操作符:

select a.id from tblA a where a.id in (select b.id from tblB b)

 

第二种方式使用EXIST操作符:

select a.id from tblA a where exists (select 1 from tblB b where b.id = a.id)

 

用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。但是用IN的SQL性能总是比较低的,而第二种格式要远比第一种格式的效率高。从SQL执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:
SQL试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。
第二种格式中,子查询以’select 1’开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器就不必遍历整个表而仅根据索引就可完成工作(这里假定在where语句中使用的列存在索引)。相对于IN子句来说,EXISTS使用相连子查询,构造起来要比IN子查询困难一些。
通过使用EXIST,数据库系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。数据库系统在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。
同时应尽可能使用NOT EXISTS来代替NOT IN,尽管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查询效率更高。

准则6. IS NULL 或 IS NOT NULL操作(判断字段是否为空)
不能用null作索引,任何包含null值的列都将不会被包含在索引中,因为B树索引是不索引空值的。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。
任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。
推荐方案:用其它相同功能的操作运算代替,如a is not null 改为 a>0 或a>’等。另外还设置字段不允许为空,而用一个缺省值代替空值,如一个datetime字段,可以将默认时间设为“1900-01-01”。

准则7. > 及 < 操作符(大于或小于操作符)
       大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,30 万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为 A>2时sql会先找出为2的记录索引再进行比较,而A>=3时sql则直接找到=3的记录索引。可结合非聚集索引一起考虑。

准则8. LIKE操作符
LIKE 操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。因为索引的摆放是依据字段值升序或降序排列,like'%*'这种用法,不能利用有序的数据结构,利用二分法查找数据。一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。

准则9. 查询条件中的适当与不适当
查询参数可以包含一下操作:=、<、>、>=、<=、BETWEEN、部分like。其中,like当这样使用时会用到索引:like '*%',但like'%*'就用不到索引。
不适当的查询参数有:NOT 、!= 、<>、 !>、 !< 、NOT EXISTS、 NOT IN 、NOT LIKE等,还有一些不当的用法,例如:对数据进行计算,负向查询、等号左边使用函数、使用OR。上述语法都用不上索引,降低程序的效率。

准则10. 慎用DELETE

一般在存储过程中或多或少都会实现一些删除数据的逻辑。对小数量的表来说,问题倒是不大。但对于大数据量的表来说,采用delete删除数据会对储存过程的性能产生一定的影响。因为delete采用的是全表逐条扫描的方式进行,是一种事务性操作,会计入SQL Server的事务日志中。不但增加了运行时间,同时也频繁写入LOG文件,导致LOG文件过大,过分消耗磁盘空间。所以,可以用truncate操作代替delete,truncate并不会计入事务日志中,同时也是不带条件的删除,执行速度很快。又或者直接drop掉表重新创建,有时都会比delete来得快。

 

 

PS: 第10点引出的两种清空SQL Server日志文件的方法

一种方法:清空日志。

1.打开查询分析器,输入命令DUMP TRANSACTION 数据库名 WITH NO_LOG

2.再打开企业管理器--右键你要压缩的数据库--所有任务--收缩数据库--收缩文件--选择日志文件--在收缩方式里选择收缩至XXM,这里会给出一个允许收缩到的最小M数,直接输入这个数,确定就可以了。

另一种方法有一定的风险性,因为SQL SERVER的日志文件不是即时写入数据库主文件的,如处理不当,会造成数据的损失。

1: 删除LOG

分离数据库 企业管理器->服务器->数据库->右键->分离数据库

2:删除LOG文件

附加数据库 企业管理器->服务器->数据库->右键->附加数据库

此法生成新的LOG,大小只有500多K。

下边的内容来自 <程序员SQL金典>

准则11:尽量将多条SQL语句压缩到一句SQL中

每次执行SQL的时候都要建立网络连接,进行权限校验,进行SQL语句的查询优化/发送执行结果,这个过程是非常耗时的,因此尽量避免过多的执行SQL语句

//这一条  本人觉得有异议  因为这样会导致sql语句非原子性的存在  耦合性更高 如果业务发生变动的话 需要重新修改SQL语句这是很不必要的   所以结合的时候要注意

准则12:使用表的别名

当在SQL 语句中连接多个表时,最好使用表的别名,并把别名前缀置于每一个列名上,这样可以减少解析的时间,也可以减少由于列名的歧义产生的错误,比如 两张表中的 列名 很接近。

准则13:用表连接代替Exists

通常来说表连接的方式比Exists 更有效率,因此如果可能的话尽量使用表连接替换Exists。 

//这一条本人有异议,因为表连接会过长的占用某张表,如果一张表需要快速的操作,则在其他地方出现连接使用这张表时,则会使整体的执行效率变慢,尽管连接的表可能不受影响。 这也是为什么很多大型系统不允许多张表连接操作的

准则14:避免在索引列上使用计算

在WHERE 字句中,如果索引列是计算或者函数的部分,DBMS的优化器将不会使用索引而进行全表扫描。

准则15:避免隐式类型的转换造成的全表扫描

在大部分数据库的隐式转换类型中数值类型的优先级高于字符串类型,因此DBMS会对比较时的不同类型做隐式转换,有时会将字符串类型变为数值类型导致索引失效而进行全表扫描 

准则16:防止检索范围过宽

如果DBMS优化器认为检索范围过宽,那么他将放弃索引查找而使用全表扫描,下面是造成检索范围过宽的情况:

1使用 IS not Null 或者不等于判断,可能造成优化器假设匹配的记录数量太大。

2使用LIKE的时候 a%会使用索引而 a%b %c则会使用全表扫描,因此a%b %c不能有效的评估匹配的数量

准则17:必要时采用Union ALL 替换Union

两者区别是 Union ALL 会查找所有结果  而Union 会合并两张表的重复记录

倘若两张表的数据全部唯一时,Union 仍然会试图在结果集中进行合并

 

转载于:https://www.cnblogs.com/jilodream/p/4219846.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30256505/article/details/98723858

智能推荐

飞行管理数学建模论文_飞机的安全飞行管理调度问题1995年csdn-程序员宅基地

文章浏览阅读6.7k次,点赞13次,收藏95次。飞行管理问题建模目录(1)摘要(2)问题重述(3)问题分析(4)模型假设(5)符号说明(6)模型的建立与求解(7) 模型的缺点与改进方向摘要对飞行区域内的飞机,通过调整飞机飞行的角度且飞机调整的幅度要尽量小来避免飞机相撞的的问题,本文先将区域内任意两架飞机在区域内飞行时不相撞的条件转化成关于飞机在飞行区域内关于飞行时间的非线性约束条件,即任意两架飞机在未飞出区域的时间里,..._飞机的安全飞行管理调度问题1995年csdn

大作业毕设系列基于matlab的直方图优化的图像去雾系统_基于matlab的图像去雾系统毕业设计-程序员宅基地

文章浏览阅读377次。雾霾天气往往会给人类的生产和生活带来极大不便,也大大增加了交通事故的发生概率。一般而言,在恶劣天气(如雾天、雨天等)条件下,户外景物图像的对比度和颜色会被改变或退化,图像中蕴含的许多特征也会被覆盖或模糊,这会导致某些视觉系统(如电子卡口、门禁监控等)无法正常工作。因此,从在雾霾天气下采集的退化图像中复原和增强景物的细节信息具有重要的现实意义。数字图像处理技术已被广泛应用于科学和工程领域,如地形分类系统、户外监控系统、自动导航系统等。为了保证视觉系统全天候正常工作,就必须使视觉系统适应各种天气状况。_基于matlab的图像去雾系统毕业设计

IDEA Help–>Edit Custom VM Options 修改后导致打不开进行复原-程序员宅基地

文章浏览阅读1.2k次。IDEA Help–>Edit Custom VM Options 修改后的坑_edit custom vm options

LVGL之GUI GUIder使用教程_lvgl界面编辑器-程序员宅基地

文章浏览阅读3.6k次,点赞7次,收藏28次。lvgl是一个免费的开放源代码图形库,提供创建具有易于使用的图形元素,再配合NXP提供的GUI-Guider软件,极大简化了嵌入式系统UI的设计。GUI Guider是恩智浦提供的用户友好型图形用户界面开发工具,可通过开源LVGL图形库快速开发高品质的显示。GUI Guider的拖放编辑器可以轻松利用LVGL的众多特性,如小部件、动画和样式来创建GUI,而只需少量代码或根本无需任何代码。单击按钮,您可以在模拟环境中运行应用或将其导出到目标项目。_lvgl界面编辑器

Unity Editor 不同枚举显示不同属性_unity 面板中不同枚举选择不同属性-程序员宅基地

文章浏览阅读623次。1_unity 面板中不同枚举选择不同属性

基于ffmpeg的MP4文件解封装_linux ffmpegmp4解封装-程序员宅基地

文章浏览阅读944次,点赞26次,收藏14次。基于ffmpeg的MP4文件解封装_linux ffmpegmp4解封装

随便推点

工欲善其事,必先利其器!(如何在Window上读写Linux项目)_windows 读写linux工具-程序员宅基地

文章浏览阅读493次。接触过C/C++的都知道,写一些C/C++项目的时候,避免不了跟Linux打交道,网上很多的项目,都是一些基于Linux的服务。当我们想学习这些项目的时候,如果没有一套方便读写代码的工具,那将会让你举步维艰。这篇文章主要和大家分享一下我自己用的一套工具,以及环境的搭建方法~_windows 读写linux工具

在Centos7中搭建http服务器_centos搭建http代理-程序员宅基地

文章浏览阅读2.8k次,点赞4次,收藏15次。Centos7默认的http服务器为Apache,Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。Apache源于NCSAhttpd服务器,经过多次修改,成为世界上最流行的Web服务器软件之一。Apache取自“a patchy server”的读音,意思是充满补丁的服务器,因为它是自由软件,所以不断有人来为它开发新的功能、新的特性、修改原来的缺陷。_centos搭建http代理

黑马程序员机器学习Day2学习笔记_深度学习与cv入门 黑马程序员-程序员宅基地

文章浏览阅读590次,点赞2次,收藏11次。一.转换器和预估器二. KNN算法网格搜索和交叉验证KNN案例:Facebook预测签到位置朴素贝叶斯联合概率、条件概率与相互独立决策树信息熵回顾传统机器学习算法流程:1.获取数据2.数据处理3.特征工程4.机器学习算法训练5.模型评估总结本章内容: 1.KNN算法用于小型数据集的分类2.朴素贝叶斯用于特征于特征之间关系不强的算法,比如文本的分类3.决策树算法用于大型的数据集中一.转换器和预估器Day1的时候我们学习了获取数据,特征工程。(Day1中我们并没有没有使用到数据处理,因为._深度学习与cv入门 黑马程序员

极客公园对话 Zilliz 星爵:大模型时代,需要新的「存储基建」-程序员宅基地

文章浏览阅读563次。大模型在以「日更」进展的同时,不知不觉也带来一股焦虑情绪:估值 130 亿美元的 AI 写作工具 Grammarly 在 ChatGPT 发布后网站用户直线下降;AI 聊天机器人独角兽公司 Character.AI 的自建大模型在 ChatGPT 进步之下,被质疑能否形成足够的竞争壁垒 …ChatGPT Plugins 插件发布之后,更多创业者开始担忧大模型的技术进步会把自己卷入「打击射程」,瞬时抹掉自己所在领域的技术积累和优势。

桌面被关闭,如何在任务管理器中打开桌面?_任务管理器打开桌面-程序员宅基地

文章浏览阅读3.8w次,点赞15次,收藏9次。explorer.exe就是windows系统的资源管理器主程序,也是桌面显示程序。如果要在任务管理器中打开桌面方法如下:1、打开任务管理器。2、点击菜单栏文件。3、新建任务,然后输入explorer按确定即可。..._任务管理器打开桌面

虚拟化 (Hypervisor) 技术详解-程序员宅基地

文章浏览阅读1.5k次,点赞34次,收藏24次。随着 ICT 技术的发展,单 SOC 算力可以承担更多业务,网络带宽拓展及低时延、区分服务等特性使得业务部署、功能分配更加灵活,比如 : 感知、融合、规划、控制、执行可分离解耦,汽车业务功能可分可合、可软件定义。电子电气架构从分布式架构到域集中式架构,再到中央集中式架构转变,分散的 ECU功能集成到域控制器甚至车载中央计算机,这就是多域融合。汽车电子底层硬件不再是由单一芯片提供简单的逻辑计算,而是需要复杂的多核 SoC 芯片提供更为复杂控制逻辑以及强大的算力支持。但是多域业务具有不同的技术需求,在域融合的同_hypervisor