当前位置:首页 » 编程语言 » 数据库性能优化sql语句
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

数据库性能优化sql语句

发布时间: 2022-07-15 08:25:40

数据库怎么优化sql怎么优化

1 避免无计划的全表扫描
如下情况进行全表扫描:
- 该表无索引
- 对返回的行无任何限制条件(无Where子句)
- 对于索引主列(索引的第一列)无限制条件
- 对索引主列的条件含在表达式中
- 对索引主列的限制条件是is (not) null或!=
- 对索引主列的限制条件是like操作且值是一个bind variable或%打头的值

2 只使用选择性索引
索引的选择性是指索引列中不同值得数目和标志中记录数的比,选择性最好的是非空列的唯一索引为1.0。
复合索引中列的次序的问题:
1 在限定条件里最频繁使用的列应该是主列
2 最具有选择性的列(即最清晰的列)应该是主列
如果1和2 不一致,可以考虑建立多个索引。
在复合索引和多个单个索引中作选择:
考虑选择性 考虑读取索引的次数 考虑AND-EQUAL操作

3 管理多表连接(Nested Loops, Merge Joins和Hash Joins) 优化联接操作
Merge Joins是集合操作 Nested Loops和Hash Joins是记录操作返回第一批记录迅速
Merge Joins的操作适用于批处理操作,巨大表 和远程查询
1全表扫描 --〉 2排序 --〉3比较和合并 性能开销主要在前两步
适用全表扫描的情形,都适用Merge Joins操作(比Nested Loops有效)。
改善1的效率: 优化I/O, 提高使用ORACLE多块读的能力, 使用并行查询的选项
改善1的效率:提高Sort_Area_Size的值, 使用Sort Direct Writes,为临时段提供专用表空间

4 管理包含视图的SQL语句
优化器执行包含视图的SQL语句有两种方法:
- 先执行视图,完成全部的结果集,然后用其余的查询条件作过滤器执行查询
- 将视图文本集成到查询里去
含有group by子句的视图不能被集成到一个大的查询中去。
在视图中使用union,不阻止视图的SQL集成到查询的语法中去。

5 优化子查询

6 使用复合Keys/Star查询

7 恰当地索引Connect By操作

8 限制对远程表的访问

9 管理非常巨大的表的访问
- 管理数据接近(proximity) 记录在表中的存放按对表的范围扫描中最长使用的列排序 按次序存储数据有助于范围扫描,尤其是对大表。
- 避免没有帮助的索引扫描 当返回的数据集合较大时,使用索引对SGA的数据块缓存占用较大,影响其他用户;全表扫描还能从ORACLE的多块读取机制和“一致性获取/每块”特性中受益。
- 创建充分索引的表 使访问索引能够读取较全面的数据 建立仅主列不同的多个索引
- 创建hash簇
- 创建分割表和视图
- 使用并行选项

10 使用Union All 而不是Union
UNION ALL操作不包括Sort Unique操作,第一行检索的响应速度快,多数情况下不用临时段完成操作,
UNION ALL建立的视图用在查询里可以集成到查询的语法中去,提高效率

11 避免在SQL里使用PL/SQL功能调用

12 绑定变量(Bind Variable)的使用管理
使用Bind Variable和Execute using方式
将like :name ||’%’ 改写成 between :name and :name || char(225), 已避免进行全表扫描,而是使用索引。

13 回访优化进程
数据变化后,重新考察优化情况

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

1、深入理解数据库的工作原理和数据存储的方式,不同的数据库的工作原理是不同的,mysql oracle db2等等都是不同的,更不要说一些nosql数据库和newsql数据库了。
2、理解sql语句检索数据的方式。
3、理解索引,知道怎样的字段建立怎样的索引,索引能做什么,不能做什么,合理的建立字段。
4、合理的拆分和合并表,数据放在一张表里面查询肯定比放在多张表里面级联查询要快。
5、会查看执行任务,任何数据库都有查看执行任务的方法,包括nosql数据库和newsql数据库已经一些大数据数据库;同时还要会分析执行任务,分析主要是所以的使用效率和字段数据的检索方式。
6、sql语句只是性能优化的简单方面,性能优化是从整体应用架构开始体现的,优化sql并不能够解决根本问题,当数据量达到一定级别以后,数据就不能使用关系型数据库,而要使用大数据数据库,这样sql就无用了。
7、不要刻意专注sql本身,sql只是一种查询语言,它本身与性能无关,性能优化的本质在于对存储方式和查询检索过程的深入理解。
8、任何系统功能业务的准确性至上,首先保证功能的正确性再考虑性能优化,如果功能就是数据量大,业务复杂,必须要用到低性能sql的检索方式,那么你只能妥协,否则就要弃用sql和关系型数据库另寻它路。

Ⅲ 如何优化SQL语句

一、问题的提出
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。
在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引,这有助于写出高性能的SQL语句。
二、SQL语句编写注意问题
下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低。
1.
IS
NULL

IS
NOT
NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。
任何在where子句中使用is
null或is
not
null的语句优化器是不允许使用索引的。
2.
联接列
对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。我们一起来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),现在要查询一个叫比尔.克林顿(Bill
Cliton)的职工。
下面是一个采用联接查询的SQL语句,
select
*
from
employss
where
first_name||''||last_name
='Beill
Cliton';
上面这条语句完全可以查询出是否有Bill
Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。
当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。
***
where
first_name
='Beill'
and
last_name
='Cliton';
.
带通配符(%)的like语句
同样以上面的例子来看这种情况。目前的需求是这样的,要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句:
select
*
from
employee
where
last_name
like
'%cliton%';
这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:
select
*
from
employee
where
last_name
like
'c%';
4.
Order
by语句
ORDER
BY语句决定了Oracle如何将返回的查询结果排序。Order
by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Order
by语句的非索引项或者有计算表达式都将降低查询速度。
仔细检查order
by语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写order
by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order
by子句中使用表达式。
5.
NOT
我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子:
...
where
not
(status
='VALID')
如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例:
...
where
status
<>'INVALID';
对这个查询,可以改写为不使用NOT:
select
*
from
employee
where
salary<3000
or
salary>3000;
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。

Ⅳ 如何进行SQL性能优化

这里分享下mysql优化的几种方法。

1、首先在打开的软件中,需要分别为每一个表创建 InnoDB FILE的文件。

Ⅳ 怎样进行sql数据库的优化

1、数据库空间是个概述,在sqlserver里,使用语句 exec sp_spaceused 'TableName' 这个语句来查。

Ⅵ 请简述项目中优化sql语句执行效率的方法,从哪些方面,sql语句性能如何分析

1. SQL优化的原则是:将一次操作需要读取的BLOCK数减到最低,即在最短的时间达到最大的数据吞吐量。
调整不良SQL通常可以从以下几点切入:
? 检查不良的SQL,考虑其写法是否还有可优化内容
? 检查子查询 考虑SQL子查询是否可以用简单连接的方式进行重新书写
? 检查优化索引的使用
? 考虑数据库的优化器

2. 避免出现SELECT * FROM table 语句,要明确查出的字段。

3. 在一个SQL语句中,如果一个where条件过滤的数据库记录越多,定位越准确,则该where条件越应该前移。

4. 查询时尽可能使用索引覆盖。即对SELECT的字段建立复合索引,这样查询时只进行索引扫描,不读取数据块。

5. 在判断有无符合条件的记录时建议不要用SELECT COUNT (*)和select top 1 语句。

6. 使用内层限定原则,在拼写SQL语句时,将查询条件分解、分类,并尽量在SQL语句的最里层进行限定,以减少数据的处理量。

7. 应绝对避免在order by子句中使用表达式。

8. 如果需要从关联表读数据,关联的表一般不要超过7个。

9. 小心使用 IN 和 OR,需要注意In集合中的数据量。建议集合中的数据不超过200个。

10. <> 用 < 、 > 代替,>用>=代替,<用<=代替,这样可以有效的利用索引。

11. 在查询时尽量减少对多余数据的读取包括多余的列与多余的行。

12. 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在where或order by子句中这些字段出现的顺序要与建立索引时的字段顺序一致,且必须包含第一列。只能是F1或F1,F2或F1,F2,F3。否则不会用到该索引。

13. 多表关联查询时,写法必须遵循以下原则,这样做有利于建立索引,提高查询效率。格式如下select sum(table1.je) from table1 table1, table2 table2, table3 table3 where (table1的等值条件(=)) and (table1的非等值条件) and (table2与table1的关联条件) and (table2的等值条件) and (table2的非等值条件) and (table3与table2的关联条件) and (table3的等值条件) and (table3的非等值条件)。
注:关于多表查询时from 后面表的出现顺序对效率的影响还有待研究。

14. 子查询问题。对于能用连接方式或者视图方式实现的功能,不要用子查询。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。应该用如下语句代替:select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100。

15. 在WHERE 子句中,避免对列的四则运算,特别是where 条件的左边,严禁使用运算与函数对列进行处理。比如有些地方 substring 可以用like代替。

16. 如果在语句中有not in(in)操作,应考虑用not exists(exists)来重写,最好的办法是使用外连接实现。

17. 对一个业务过程的处理,应该使事物的开始与结束之间的时间间隔越短越好,原则上做到数据库的读操作在前面完成,数据库写操作在后面完成,避免交叉。

18. 请小心不要对过多的列使用列函数和order by,group by等,谨慎使用disti软件开发t。

19. 用union all 代替 union,数据库执行union操作,首先先分别执行union两端的查询,将其放在临时表中,然后在对其进行排序,过滤重复的记录。
当已知的业务逻辑决定query A和query B中不会有重复记录时,应该用union all代替union,以提高查询效率。

Ⅶ 如何写出高性能SQL语句

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

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

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

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

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

select * from al
select * From al

其实就是大小写不同,查询分析器就认为是两句不同的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,赶紧升级吧。

Ⅷ 谁能告诉我怎样优化sql语句

(1)选择最有效率的表名顺序(只在基于规则的优化器中有效):Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。(2)WHERE子句中的连接顺序:Oracle采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。(3)SELECT子句中避免使用‘*’:Oracle在解析的过程中, 会将‘*’依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。(4)减少访问数据库的次数:Oracle在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等。(5)在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200。(6)使用DECODE函数来减少处理时间:使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。(7)整合简单,无关联的数据库访问:如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)。(8)删除重复记录:最高效的删除重复记录方法 ( 因为使用了ROWID)例子:DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
(9)用TRUNCATE替代DELETE:当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息。当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短。(TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)。(10)尽量多使用COMMIT:只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少,COMMIT所释放的资源:a. 回滚段上用于恢复数据的信息。b. 被程序语句获得的锁。c. redo log buffer 中的空间。d. Oracle为管理上述3种资源中的内部花费。(11)用Where子句替换HAVING子句:避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。(非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里。(12)减少对表的查询:在含有子查询的SQL语句中,要特别注意减少对表的查询。例子:SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
(13)通过内部函数提高SQL效率:复杂的SQL往往牺牲了执行效率。能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的。(14)使用表的别名(Alias):当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。(15)用EXISTS替代IN、用NOT EXISTS替代NOT IN:在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率。在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS。例子:(高效)SELECT * FROM EMP (基础表)
WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0
AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(16)识别‘低效执行’的SQL语句:虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法:SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$SQLAREA
WHERE EXECUTIONS>0
AND BUFFER_GETS > 0
AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
ORDER BY 4 DESC;
(17)用索引提高效率:索引是表的一个概念部分,用来提高检索数据的效率,Oracle使用了一个复杂的自平衡B-tree结构。通常,通过索引查询数据比全表扫描要快。当Oracle找出执行查询和Update语句的最佳路径时, Oracle优化器将使用索引。同样在联结多个表时使用索引也可以提高效率。另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列。通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率。虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价。索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改。这意味着每条记录的INSERT, DELETE , UPDATE将为此多付出4, 5次的磁盘I/O 。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。定期的重构索引是有必要的:ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
(18)用EXISTS替换DISTINCT:当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT。一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。例子:(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X'
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(19)SQL语句用大写的;因为Oracle总是先解析SQL语句,把小写的字母转换成大写的再执行。(20)在Java代码中尽量少用连接符“+”连接字符串。(21)避免在索引列上使用NOT通常,我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响。当Oracle“遇到”NOT,他就会停止使用索引转而执行全表扫描。(22)避免在索引列上使用计算。WHERE子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描。举例:低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(23)用>=替代>:高效:
SELECT * FROM EMP WHERE DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录。(24)用UNION替换OR (适用于索引列):通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果。对索引列使用OR将造成全表扫描。注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低。在下面的例子中, LOC_ID 和REGION上都建有索引。高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”
(25)用IN来替换OR:这是一条简单易记的规则,但是实际的执行效果还须检验,在Oracle8i下,两者的执行路径似乎是相同的:低效:SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30高效:SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);(26)避免在索引列上使用IS NULL和IS NOT NULL:避免在索引中使用任何可以为空的列,Oracle将无法使用该索引。对于单列索引,如果列包含空值,索引中将不存在此记录。对于复合索引,如果每个列都为空,索引中同样不存在此记录.如果至少有一个列不为空,则记录存在于索引中。举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , Oracle将不接受下一条具有相同A,B值(123,null)的记录(插入)。 然而如果所有的索引列都为空,Oracle将认为整个键值为空而空不等于空。因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引。低效: (索引失效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;高效: (索引有效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;(27)总是使用索引的第一个列:如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。(28)用UNION-ALL 替换UNION ( 如果有可能的话):当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序。如果用UNION ALL替代UNION, 这样排序就不是必要了。效率就会因此得到提高。需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录。因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存。对于这块内存的优化也是相当重要的。下面的SQL可以用来查询排序的消耗量:
低效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
(29)用WHERE替代ORDER BY:ORDER BY 子句只在两种严格的条件下使用索引。ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序。ORDER BY中所有的列必须定义为非空。WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列。例如: 表DEPT包含以下列:DEPT_CODE PK NOT NULLDEPT_DESC NOT NULLDEPT_TYPE NULL低效: (索引不被使用)SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE高效: (使用索引)SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0(30)避免改变索引列的类型:当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换。 假设 EMPNO是一个数值类型的索引列:SELECT … FROM EMP WHERE EMPNO = ‘123'。 实际上,经过Oracle类型转换, 语句转化为: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 。幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变。现在,假设EMP_TYPE是一个字符类型的索引列:SELECT … FROM EMP WHERE EMP_TYPE = 123 。这个语句被Oracle转换为: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123。因为内部发生的类型转换, 这个索引将不会被用到! 为了避免Oracle对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来。注意当字符和数值比较时, Oracle会优先转换数值类型到字符类型。(31)需要当心的WHERE子句:某些SELECT 语句中的WHERE子句不使用索引。这里有一些例子:(1)‘!=' 将不使用索引。记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中。(2)‘||'是字符连接函数。就象其他函数那样, 停用了索引。(3)‘+'是数学函数。就象其他数学函数那样, 停用了索引。(4)相同的索引列不能互相比较,这将会启用全表扫描。(32)a. 如果检索数据量超过30%的表中记录数.使用索引将没有显着的效率提高。b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别。而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!(33)避免使用耗费资源的操作:带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能。DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强。(34)优化GROUP BY:提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉。下面两个查询返回相同结果但第二个明显就快了许多。
低效:
SELECT JOB, AVG(SAL)
FROM EMP
GROUP JOB
HAVING JOB = 'PRESIDENT'
OR JOB = 'MANAGER'高效:
SELECT JOB, AVG(SAL)
FROM EMP
WHERE JOB = 'PRESIDENT'
OR JOB = 'MANAGER'
GROUP JOB

Ⅸ SQL Server数据库的高性能优化经验总结

本文主要向大家介绍的是正确优化SQL
Server数据库的经验总结,其中包括在对其进行优化的实际操作中值得大家注意的地方描述,以及对SQL语句进行优化的最基本原则,以下就是文章的主要内容描述。
优化数据库的注意事项:
1、关键字段建立索引。
2、使用存储过程,它使SQL变得更加灵活和高效。
3、备份数据库和清除垃圾数据。
4、SQL语句语法的优化。(可以用Sybase的SQL
Expert,可惜我没找到unexpired的序列号)
5、清理删除日志。
SQL语句优化的基本原则:
1、使用索引来更快地遍历表。
缺省情况下建立的索引是非群集索引,但有时它并不是最佳的。在非群集索引下,数据在物理上随机存放在数据页上。合理的索引设计要建立在对各种查询的分析和预测上。
一般来说:
①.有大量重复值、且经常有范围查询(between,
>,<
,>=,<
=)和order
by、group
by发生的列,可考虑建立群集索引
②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引;
③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。
2、IS
NULL

IS
NOT
NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。任何在where子句中使用is
null或is
not
null的语句优化器是不允许使用索引的。
3、IN和EXISTS
EXISTS要远比IN的效率高。里面关系到full
table
scan和range
scan。几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。
4、在海量查询时尽量少用格式转换。
5、当在SQL
SERVER
2000中
如果存储过程只有一个参数,并且是OUTPUT类型的,必须在调用这个存储过程的时候给这个参数一个初始的值,否则会出现调用错误。
6、ORDER
BY和GROPU
BY
使用ORDER
BY和GROUP
BY短语,任何一种索引都有助于SELECT的性能提高。注意如果索引列里面有NULL值,Optimizer将无法优化。
7、任何对列的操作都将导致表扫描,它包括SQL
Server数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。
8、IN、OR子句常会使用工作表,使索引失效。如果不产生大量重复值,可以考虑把子句拆开。拆开的子句中应该包含索引。
9、SET
SHOWPLAN_ALL>10、谨慎使用游标
在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,这样可使性能得到明显提高。
注释:所谓的优化就是WHERE子句利用了索引,不可优化即发生了表扫描或额外开销。经验显示,SQL
Server数据库性能的最大改进得益于逻辑的数据库设计、索引设计和查询设计方面。反过来说,最大的性能问题常常是由其中这些相同方面中的不足引起的。
其实SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语句,充份利用索引,减少表扫描的I/O次数,尽量避免表搜索的发生。其实SQL的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入研究还会涉及SQL
Server数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。

Ⅹ 2020-10-11:一条sql语句执行时间过长,应该如何优化从哪些方面进行优化

改进数据库sql语句进行优化的理由 应用程序之优化通常可分为两个方面:源代码之优化和sql语句之优化。源代码之优化在时间成本和风险上代价很高;另一方面,源代码之优化对数据库系统性能之提升收效有限。 优化之理由 1)sql语句是对数据库(数据)进行操作之惟一途径; 2)sql语句消耗了70%~90%之数据库资源; 3)sql语句独立于程序设计逻辑,相对于对程序源代码之优化,对sql语句之优化在时间成本和风险上之代价都很低; 4)sql语句可以有不同之写法; 5)sql语句易学,难精通。 优化技术之发展 第一代之sql优化工具是执行计划分析工具。这类之工具对输入之sql语句从数据库提取执行计划,并解释执行计划中关键字之含义;第二代之sql优化工具只能提供增加索引之建议,它通过对输入之sql语句之执行计划之分析来产生是否要增加索引之建议。该类工具存在着致命之缺点——只分析了一条sql语句就得出增加某个索引之结论,根本不理会(实际上也无法评估到)增加之索引对整体数据库系统性能之影响。其破坏性在于: 1、不理会增加之索引对其他增、删、改sql语句之负面影响; 2、没有考虑增加之索引可能导致数据库判断失误; 3、对由于增加索引引起之数据库系统负担忽略不计。 同时,这些工具由于技术水平之限制存在着以下缺点: 1、无法保证建议或改写之正确性; 2、无法进行重写,仅仅提供了建议或有限程度之改写,重写工作还是需要人工完成,优化工作所需之时间和工作量同人工进行优化差不多; 3、改写之规则和hints有限,难以处理复杂之sql语句; 4、必须人手逐条进行测试。 这类工具曾经盛极一时,直到人工智能自动sql优化之出现。