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

优化sql查询语句论文

发布时间: 2023-01-29 11:18:14

Ⅰ 如何优化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数据库论文

ORACLE中SQL查询优化研究

摘 要 数据库性能问题一直是决策者及技术人员共同关注的焦点,影响数据库性能的一个重要因素就是SQL查询语句的低效率。论文首先分析了导致SQL查询语句性能低下的四个常见原因以及SQL调优的一般步骤,然后分别针对如何降低I/O操作、在查询语句中如何避免对查询结果的高成本操作以及在多表连接时如何提高查询效率进行了分析。
关键词 ORACLE;SQL;优化;连接

1 引言
随着网络应用不断发展,系统性能已越来越引起决策者的重视。影响系统性能的因素很多,低效的SQL语句就是其中一个不可忽视的重要原因。论文首先分析导致SQL性能低下的常见原因,然后分析SQL调优应遵循的一般步骤,最后从如何降低I/O、避免对查询结果的高成本操作和多表连接中如何提高SQL性能进行了研究。鉴于目前ORACLE在数据库市场上的主导地位,论文将只针对ORACLE进行讨论。
2 影响SQL性能的原因
影响SQL性能的因素很多,如初始化参数设置不合理、导入了不准确的系统及模式统计数据从而影响优化程序(CBO)的正确判断等,这些往往和DBA密切相关。纯粹从SQL语句出发,笔者认为影响SQL性能不外乎以下四个重要原因:
(1)在大记录集上进行高成本操作,如使用了引起排序的谓词等。
(2)过多的I/O操作(含物理I/O与逻辑I/O),最典型的就是未建立恰当的索引,导致对查询表进行全表扫描。
(3)处理了太多的无用记录,如在多表连接时过滤条件位置不当导致中间结果集包含了太多的无用记录。
(4)未充分利用数据库提供的功能,如查询的并行化处理等。
第(4)个原因处理起来相对简单。论文将针对前三个原因论述如何提高SQL查询语句的性能。
3 SQL优化的一般步骤
SQL优化一般需经过发现问题、分析问题、提出解决措施、应用措施、测试性能几个步骤,如图1所示。“发现问题就是解决问题的一半”,因此在SQL调优过程中,定位问题SQL是非常重要的一步,一般可借助于ORACLE自带的性能优化工具如STATSPACK、TKPROF、AUTOTRACE等辅助用户进行,同时还应该重视动态性能视图如V$SQL、V$MYSTAT、V$SYSSTAT等的研究。

图1 SQL优化的一般步骤
4 SQL语句的优化
4.1 优化排序操作
排序的成本十分高昂,当在查询语句中使用了引起结果集排序的谓词时,SQL性能必然受到影响。
4.1.1 排序过程分析
当待排序数据集不是太大时,服务器在内存(排序区)完成排序操作,如果排序需要更多的内存空间,服务器将进行如下处理:
(1) 将数据分成多个小的集合,对每一集合进行排序。
(2) 服务器向磁盘申请临时空间,将排好序的中间结果写入临时段,再对另外的集合进行排序。
(3) 在所有的集合均排好序后,服务器再将它们进行合并得到最终的结果,如果排序区尺寸太小,合并无法一次完成时,将分多次进行。
从上述分析可知,排序是一种十分昂贵的操作,它消耗大量的CPU时间和内存,触发磁盘分页和交换操作,因此只要有可能,我们就应该在SQL语句中尽量避免排序操作。
4.1.2 SQL中引起排序的操作
SQL查询语句中引起排序的操作大致有:ORDER BY 和GROUP BY 从句;DISTINCT修饰符;UNION、INTERSECT、MINUS集合操作符;多表连接时的排序合并连接(SORT MERGE JOIN)等。
4.1.3 如何避免排序
1)建立恰当的索引
对经常进行排序和连接操作的字段建立索引。在建立索引后,当服务器向这些字段发出排序请求时,将直接引用索引而不进行排序操作;当进行等值连接查询操作时,若建立连接的字段未建立索引,服务器进行的是排序合并连接(SORT MERGE JOIN),连接操作的过程如下:
对进行连接的两个或多个表分别进行全扫描;
对每一个表中的行集分别进行全排序;
合并排序结果。
如果建立连接的字段已建立索引,服务器进行嵌套循环连接(NESTED LOOP JOINS),该连接方式不需要任何排序,其过程如下:
对驱动表进行全表扫描;
对返回的每一行利用连接字段值实施索引惟一扫描;
利用从索引扫描中返回的ROWID值在从表中定位记录;
合并主、从表中的匹配记录。
因此,建立索引可避免多数排序操作。
2)用UNIION ALL替换UNION
UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。大部分应用中是不会产生重复记录的,最常见的是过程表与历史表UNION 。因此,采用UNION ALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。
4.2 优化I/O
过多的I/O操作会占用CPU时间、消耗大量内存和占用过多的栓锁,因此有必要对SQL的I/O进行优化。优化I/O的最有效方式就是用索引扫描代替全表扫描。
4.2.1 应用基于函数的索引
基于函数的索引(FUNCTION BASED INDEX,简记为FBI)提供了索引计算列并在查询中使用这些索引的能力。FBI的实质是对查询所需中间结果进行预处理。如果一个FBI与查询语句中的内嵌函数完全匹配,CBO在生成查询计划时,将自动启用索引范围扫描(INDEX RANGE SCAN)替换全表扫描(FULL TABLE SCAN)。考察下面的代码段并用AUTOTRACE观察创建FBI前后执行计划的变化。
select * from emp where upper(ename)=’SCOTT’
创建FBI前,很明显是全表扫描。
Execution Plan
……
1 0 TABLE ACCESS (FULL) OF 'EMPLOYEES' (Cost=2 Card=1 Bytes=22)
idle>CREATE INDEX EMP_UPPER_FIRST_NAME ON EMPLOYEES(UPPER(FIRST_NAME));
索引已创建。
再次运行相同查询,
Execution Plan
……
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMPLOYEES' (Cost=1 Card=1 Bytes=22)
2 1 INDEX (RANGE SCAN) OF 'EMP_UPPER_FIRST_NAME' (NON-UNIQUE) (Cost=1 Card=1)
这一简单的例子充分说明了FBI在SQL查询优化中的作用。FBI所用的函数可以是用户自己创建的函数,该函数越复杂,基于该函数创建FBI对SQL查询性能的优化作用越明显。
4.2.2 应用物化视图和查询重写
物化视图是一个预计算结果集,其中通常包含聚集与多表连接等复杂操作。数据库自动维护物化视图,且随用户的要求进行刷新。查询重写机制就是用数据库中的替代对象(如物化视图)将用户提交的查询重写为完全不同但功能等价的查询。查询重写对用户透明,用户完全按常规编写访问数据库的查询语句,优化程序(CBO)自动决定是否对用户提交的查询进行重写。查询重写是提高查询性能的一种非常有效的方法,尤其是在数据仓库环境中针对汇总、多表连接以及其它高成本的操作方面。
下面以一个非常简单的例子来演示物化视图和查询重写在优化SQL查询性能方面的作用。
select dept.deptno,dept.dname,count(*)
from emp,dept
where emp.deptno=dept.deptno
group by dept.deptno,dept.dname
查询计划及主要统计数据如下:
执行计划:
-----------------------------------------
……
2 1 HASH JOIN (Cost=5 Card=14 Bytes=224)
3 2 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=4 Bytes=52)
4 2 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=14 Bytes=42)
主要统计数据:
-----------------------------------------
305 recursive calls
46 consistent gets
创建物化视图EMP_DEPT:
create materialized view emp_dept build immediate
refresh on demand
enable query rewrite
as
select dept.deptno,dept.dname,count(*)
from emp,dept
where emp.deptno=dept.deptno
group by dept.deptno,dept.dname
/
再次执行查询,执行计划及主要统计数据如下:
执行计划:
-------------------------------------
……
1 0 TABLE ACCESS (FULL) OF 'EMP_DEPT' (Cost=2 Card=327 Bytes=11445)
主要统计数据:
------------------------------------
79 recursive calls
28 consistent gets
可见,在建立物化视图之前,首先执行两个表的全表扫描,然后进行HASH连接,再进行分组排序和选择操作;而建立物化视图后,CBO自动将上述复杂操作转换为对物化视图EMP_DEPT的全扫描,相关的统计数据也有了很大的改善,递归调用(RECURSIVE CALLS)由305降到79,逻辑I/O(CONSISTENT GETS)由46降为28。
4.2.3 将频繁访问的小表读入CACHE
逻辑I/O总是快于物理I/O。如果数据库中存在被应用程序频繁访问的小表,可将这些表强行读入KEEP池,从而避免物理I/O的发生。
4.3 多表连接优化
最能体现查询复杂性的就是多表连接,多表连接操作往往要耗费大量的CPU时间和内存,因此多表连接查询性能优化往往是SQL优化的重点与难点。
4.3.1 消除外部连接
通过消除外部连接,不仅使得到的查询更易于读取,而且性能也经常可以得到改善。一般的思路是,有以下形式的查询:
SELECT …,OUTER_JOINED_TABLE.COLUMN
FROM SOME_TABLE,OUTER_JOINED_TO_TABLE
WHERE …=OUTER_JOINED_TO_TABLE(+)
可转换为如下形式的查询:
SELECT …,(SELECT COLUMN FROM OUTER_ JOINED_TO_TABLE WHERE …)FROM SOME_TABLE;
4.3.2 谓词前推,优化中间结果
多表连接的性能低下多数是因为连接操作与过滤操作的次序不合理,大多数用户在编写多表连接查询时,总是先进行连接操作再应用过滤条件,这导致服务器做了太多的无用功。针对这类问题,其优化思路就是尽可能将过滤谓词前推,使不符合条件的记录提前被筛选掉,只对符合条件的少数记录进行连接处理,这样可成倍的提高SQL查询效能。

标准连接查询如下:
Select a.prod_name,sum(b.sale_quant),
sum(c.sale_quant),sum(d.sale_quant)
From proct a,tele_sale b,online_sale c,store_sale d
Where a.prod_id=b.prod_id and a.prod_id=c.prod_id
and a.prod_id=d.prod_id And a.order_date>sysdate-90
Group by a.prod_id;
启用内嵌视图,且将条件a.order_date>sysdate-90前移,优化后代码如下:
Select a.prod_name,b.tele_sale_sum,c.online_sale_sum,d.store_sale_sum From proct a,
(select sum(sal_quant) tele_sale_sum from proct,tele_sale
Where proct.order_date>sysdate-90 and proct.prod_id =tele_sale.prod_id) b,
(select sum(sal_quant) online_sale_sum
from proct,tele_sale
Where proct.order_date>sysdate-90 and proct.prod_id =online_sale.prod_id) c,
(select sum(sal_quant) store_sale_sum
from proct,store_sale
Where proct.order_date>sysdate-90 and proct.prod_id =store_sale.prod_id) d,
Where a.prod_id=b.prod_id and
a.prod_id=c.prod_id and a.prod_id=d.prod_id;
5 结束语
SQL语言在数据库应用中占有非常重要的地位,其性能的优劣直接影响着整个信息系统的可用性。论文从影响SQL性能的最主要的三个方面入手,分析了如何优化SQL查询的I/O、避免高成本的排序操作和优化多表连接。需要强调的一点是,理解SQL语句所解决的问题比SQL调优本身更重要,因此SQL调优需要系统分析人员、开发人员和数据库管理员密切协作。
参考文献
[1]Thomas Kyte.Effective Oracle by Design:Design and Build High-performance Oracle Application[M],The McGral- Hill Companies,Inc,2003
[2]Kevin Loney,George Koch,Oracle 9i:The Complete Reference[M],The McGral-Hill Companies,Inc,2002
[3] Oracle9i SQL Reference release 2(9.2)[OL/M],2002.10. http://www.oracle.com/technology/
[4] Oracle9i Data Warehousing Guide release 2(9.2) [OL/M],2002.03. http://www.oracle.com/technology/
[5]Alexey Danchenkov,Donald Burleson,Oracle Tuning:The Definitive Reference[OL/M],Rampant Techpress,2006.
[6] Oracle9i Database Concepts release 2(9.2) [OL/M],2002.08. http://www.oracle.com/technology/
[7] Oracle9i supplied plsql packages and types reference release 2(9.2) [OL/M],2002.12. http://www.oracle.com/ technology/

Ⅲ 请简述项目中优化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语句的几种优化方法

1、尽可能建立索引,包括条件列,连接列,外键列等。

2、尽可能让where中的列顺序与复合索引的列顺序一致。

3、尽可能不要select *,而只列出自己需要的字段列表。

4、尽可能减少子查询的层数。

5、尽可能在子查询中进行数据筛选 。

Ⅳ 查询的SQL语句怎么写才能提高查询效率

这是SQL语句优化的问题了。网上好多类似的文章,非常全面。
个人觉得比较常用的是:
SQL语句查询中经常用到的字段建索引,这样可以非常明显的提升查询速度。
FROM表的顺序,大表在前,小表在后,因为检索的顺序从后往前。
WHERE, WHERE A.COLUMN = B.COLUMN,把小表的字段放在后边(B表),大表在前。
固定值查询的放在后边 COLUMN = '1'这种。因为这个也是从后往前的顺序。
如果有(NOT) IN (SELECT ...) 尽量避免,因为IN里面也是一个大的查询,使用 (NOT) EXISTS的语法代替。
还有UNION和UNION ALL,多表联合,UNION的作用是可以去掉重复,如果多表没有重复数据,使用UNION ALL效率也会大大提高。