SQL Server数据库性能优化之SQL语句篇【转】
SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html
近期项目需要, 做了一段时间的SQL Server性能优化,遇到了一些问题,也积累了一些经验,现总结一下,与君共享。SQL Server性能优化涉及到许多方面,如良好的系统和数据库设计,优质的SQL编写,合适的数据表索引设计,甚至各种硬件因素:网络性能、服务器的性能、 操作系统的性能,甚至网卡、交换机等。这篇文章主要讲到如何改善SQL语句,还将有另一篇讨论如何改善索引。
如何改善SQL语句的一些原则:
1. 按需索取字段,跟“SELECT *”说拜拜
字段的提取一定要按照“用多少提多少”的原则,避免使用“SELECT *”这样的操作。做了这样一个实验,表tblA有1000万数据:
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. 字段名和表名要写规范,注意大小写
这一点要多注意,如果大小写写错的话,虽然SQL仍然能正常执行,但数据库系统会花一定的开销和时间先要把您写的规范成正确的,然后再执行SQL。写对的话,这个时间就省了。
正常的: select top 10 dteTransaction, txtSystem_id from tblTransactionSystem
不小心的:select top 10 dtetransaction, txtsystem_id from tbltransactionsystem
3. 适当使用过渡表
把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。例如:
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
AND cust.postcode>“98000”
ORDER BY cust.name
如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:
INTO temp_cust_with_balance
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
ORDER BY cust.name
然后以下面的方式在临时表中查询:
临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。注意:过渡临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。
4. 别在where条件中做函数计算
这样做的后果是将在每个行上进行运算,这将导致该列的索引失效而触发全表扫描。如下SQL:
可以改成
这样会使用针对dteCreated的索引,提高查询效率。
5. IN(NOT IN)操作符与EXISTS(NOT EXISTS)操作符
有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种方式的子查询。如下:
第一种方式使用IN操作符:
第二种方式使用EXIST操作符:
用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 Server数据库性能优化之SQL语句篇【转】的更多相关文章
- 转载——SQL Server数据库性能优化之SQL语句篇
转载自:http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一 ...
- SQL SERVER数据库性能优化之SQL语句篇
(引用自重明鸟的博客,方便学习和查看) 1. 按需索取字段,跟“SELECT *”说拜拜 字段的提取一定要按照“用多少提多少”的原则,避免使用“SELECT *”这样的操作.做了这样一个实验,表tbl ...
- Sql Server数据库性能优化之索引
最近在做SQL Server数据库性能优化,因此复习下一索引.视图.存储过程等知识点.本篇为索引篇,知识整理来源于互联网. 索引加快检索表中数据的方法,它对数据表中一个或者多个列的值进行结构排序,是数 ...
- SQL Server数据库性能优化之索引篇【转】
http://www.blogjava.net/allen-zhe/archive/2010/07/23/326966.html 性能优化之索引篇 近期项目需要, 做了一段时间的SQL Server性 ...
- SQL Server数据库性能优化(一)之 优化SQL 语句
最近工作上基本没什么需求(好吧 不是最近是好久了,所以随便看看基础的东西来填补自己的空白) 原文出自:http://www.blogjava.net/allen-zhe/archive/2010/07 ...
- SQL Server数据库性能优化技巧
查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引: 2.I/O吞吐量小,形成了瓶颈效应: 3.内存不足: 4.网络速度慢: 5.查询出的数据量过大: 6.锁或者死锁: 7.返回了不必 ...
- SQL Server数据库性能优化(二)之 索引优化
参考文献 http://isky000.com/database/mysql-performance-tuning-index 原文作者是做mysql 优化的 但是我觉得 在索引方面 ...
- SQL Server 数据库性能优化
分析比较执行时间计划读取情况 1. 查看执行时间和cpu set statistics time on select * from Bus_DevHistoryData set statistics ...
- [转] SQL Server 数据库性能优化
分析比较执行时间计划读取情况 1. 查看执行时间和cpu set statistics time on select * from Bus_DevHistoryData set statistics ...
随机推荐
- Java生成带小图标的二维码-google zxing 工具类
近期一直忙于开发微信商城项目,应客户要求,要开发个有图标的二维码.经过两次改版,终于实现了该功能(第一次没有小图标,这次才整合好的),如下是完整代码 . 该代码使用Java7开发,另外使用 core- ...
- 微信小程序-视图列表渲染
wx:for 在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件. 默认数组的当前项的下标变量名默认为index,数组当前项的变量名默认为item <view ...
- Strus2学习Exception处理集锦(一)
2015-01-05 同学用dom4j写的一个更改节点文本的方法爆出这样一个错误: 代码: for(Iterator itr=root.elementIterator();itr.hasNext(); ...
- Http referer origin
为了防止CSRF的攻击,我们建议修改浏览器在发送POST请求的时候加上一个Origin字段,这个Origin字段主要是用来标识出最初请求是从哪里发起的.如果浏览器不能确定源在哪里,那么在发送的请求里面 ...
- IT关键词,发现与更新,点成线,线成面,面成体
时序图 1.什么是时序图 2.如何看懂时序图 3.时序图的作用 4.如何绘制时序图 分布式 一个业务分拆多个子业务,部署在不同的服务器上. 分布式是指将不同的业务分布在不同的地方. 而集群指的是将几台 ...
- react1
1.方法用() 里面的每个参数之间用,分隔2.对象(函数.数组)用{} 3.{/*注释...*/} 4 组件的生命周期可分成三个状态:Mounting:已插入真实 DOMUpdating:正在被重新 ...
- eclipse导入android项目红叉和红色感叹号怎么解决
解决办法如下:第一步:你要确保这个项目没有问题,有的项目本身就有问题,例如:xml文件,java程序等本身就有错.第二步:在Eclipse菜单中选择“Project”----〉Clean 解决不了,下 ...
- 【java基础】面向对象的三大基本特征之-------继承
面向对象的三大特征:封装,继承,多态 java通过extends关键字来实现继承,而且是单继承,一个子类只可以有一个直接父类,但是父类还可以有父类... java.long.Object是所有类的父类 ...
- [分享] IT天空的二十二条军规
Una 发表于 2014-9-19 20:25:06 https://www.itsk.com/thread-335975-1-1.html IT天空的二十二条军规 第一条.你不是什么都会,也不是什么 ...
- VWmare workstation12.5中出现的问题
安装VWmare Workstation12.5之后,出现只能从主机复制文件到虚拟机,但是虚拟机的文件不能直接拖到主机中进行复制.所以我们需要重新安装VWmare Tools. 在虚拟机的VM-> ...