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

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

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

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

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

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

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

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

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

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

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

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

”     
ORDER BY cust.name

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

ORDER BY cust.name

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

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

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

可以改成

这样会使用针对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操作符:

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 仍然会试图在结果集中进行合并

SQL Server数据库性能优化(一)之 优化SQL 语句的更多相关文章

  1. SQL Server数据库性能优化之SQL语句篇【转】

    SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...

  2. Sql Server数据库性能优化之索引

    最近在做SQL Server数据库性能优化,因此复习下一索引.视图.存储过程等知识点.本篇为索引篇,知识整理来源于互联网. 索引加快检索表中数据的方法,它对数据表中一个或者多个列的值进行结构排序,是数 ...

  3. 5. SQL Server数据库性能监控 - 当前请求

    原文:5. SQL Server数据库性能监控 - 当前请求 对于在线运行的系统,当前数据库性能监控,通常监视以下几点: (1) 是否有阻塞 (Blocking); (2) 是否有等待 (Waitin ...

  4. SQL Server数据库性能优化之索引篇【转】

    http://www.blogjava.net/allen-zhe/archive/2010/07/23/326966.html 性能优化之索引篇 近期项目需要, 做了一段时间的SQL Server性 ...

  5. SQL SERVER 数据库备份的三种策略及语句

    1.全量数据备份    备份整个数据库,恢复时恢复所有.优点是简单,缺点是数据量太大,非常耗时 全数据库备份因为容易实施,被许多系统优先采用.在一天或一周中预定的时间进行全数据库备份使你不用动什么脑筋 ...

  6. SQL SERVER数据库状态(脱机,联机,可疑)及SQL设置语句详解

      首先我们应该知道数据库总是处于一个特定的状态中,下面先来了解一下数据库的常见的三种状态:1,脱机:我们可以在Microsoft SQL Server Management中看到该数据库,但该数据库 ...

  7. [转]如何将高版本的SQL Server数据库备份到低版本的SQL Server

    本文转自:https://blog.csdn.net/wang465745776/article/details/54969676 前提条件备份SQL Server服务器版本为:12.0.2000.8 ...

  8. 无法将数据库从SINGLE_USER模式切换回MULTI_USER模式(Error 5064),及查找SQL Server数据库中用户spid(非SQL Server系统spid)的方法

    今天公司SQL Server数据库无意间变为SINGLE_USER模式了,而且使用如下语句切换回MULTI_USER失败: ALTER DATABASE [MyDB] SET MULTI_USER W ...

  9. SQL Server数据库性能优化技巧

    查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引: 2.I/O吞吐量小,形成了瓶颈效应: 3.内存不足: 4.网络速度慢: 5.查询出的数据量过大: 6.锁或者死锁: 7.返回了不必 ...

  10. SQL Server数据库性能优化(二)之 索引优化

    参考文献 http://isky000.com/database/mysql-performance-tuning-index 原文作者是做mysql 优化的     但是我觉得  在索引方面    ...

随机推荐

  1. There is no tracking information for the current branch

    There is no tracking information for the current branch. Please specify which branch you want to mer ...

  2. Struts Upload上传文件

    1.Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.te ...

  3. ActiveMQ发布订阅模式

    ActiveMQ的另一种模式就SUB/HUB即发布订阅模式,是SUB/hub就是一拖N的USB分线器的意思.意思就是一个来源分到N个出口.还是上节的例子,当一个订单产生后,后台N个系统需要联动,但有一 ...

  4. 算法训练 Hanoi问题

      算法训练 Hanoi问题   时间限制:1.0s   内存限制:512.0MB      问题描述 如果将课本上的Hanoi塔问题稍做修改:仍然是给定N只盘子,3根柱子,但是允许每次最多移动相邻的 ...

  5. LeetCode -- Triangle 路径求最小和( 动态规划问题)

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  6. 利用zxing制作彩色,高容错,支持中文等UTF编码的QR二维码图片

    利用zxing制作彩色,高容错,支持中文等UTF编码的QR二维码图片.代码如下 import java.awt.Color;import java.io.File;import java.util.H ...

  7. windows 访问 ubuntu虚拟机 django服务器 失败

    配置ubuntu配置成桥接,在ubuntu虚拟机中运行django.py开发服务器.windows访问django失败. 虚拟机运行: python manage.py runserver 0.0.0 ...

  8. LeetCode Majority Element I && II

    原题链接在这里:Majority Element I,Majority Element II 对于Majority Element I 来说,有多重解法. Method 1:最容易想到的就是用Hash ...

  9. php自定义错误处理和try{}catch(){}学习

    <?php //语法错误 //运行时的错误 //逻辑错误 //php的错误报告级别 // display_errors; // ini_set("display_errors" ...

  10. face mask in opencv

    http://stackoverflow.com/questions/22427550/face-mask-in-opencv