查询表达式优化

2024-07-28

查询表达式优化(精选八篇)

查询表达式优化 篇1

查询优化器是数据库管理系统的核心部件,查询优化技术是影响数据库性能的关键因素[1,2]。在面向数据库的三层架构的应用系统中,如果用户的查询语句条件错误或参数冗余,在表示层不进行检查就提交给数据抽取器,这种请求将导致计算服务器空耗,影响数据库系统处理性能[3],因此有必要在表示层就借鉴数据库查询优化技术,提供对输入的查询表达式进行逻辑检查和优化处理的机制。

一般数据库查询优化可以分为两个阶段:第一阶段,查询重写,将查询表达式进行等价变换,变成效率更高的形式,这一阶段的优化是静态的。第二阶段,计划优化,决定查询执行计划中关系的连接次序和连接方法,以及使用怎样的存取方法,为每个查询操作(数据抽取操作)提供一个较优的路径,如图1所示。

用户在表示层提交的查询表达式首先进入查询分析器,分析器立即对表达式进行词法分析,然后借助一个具有各种标志状态的堆栈和采用递归下降法进行语法分析,去除原表达式中冗余的括号,形成语法树结构。在进行真正优化前,需要对查询树进行一些预处理工作,包括把条件表达式转换成析取范式(Disjunctive Normal Form)、去掉NOT、尽可能地把NOT下推等[4]。

本文研究的查询表达式优化技术以轨道交通AFC运营管理数据分析系统为应用背景,侧重于查询重写,提出了一种面向对象的表达式优化框架,将接收的表达式变换为语义上等价的更高效、带异常预防功能的查询表达式,从而提高应用系统的效率和智能性。

1 查询重写的面向对象框架

定义1 命题元素:分解原子命题所得的具有独立语义的元素。

查询重写子系统按工作步骤分为两层,即最简合(析)取式层和命题元素优化层,如图2所示。首先在最简合(析)取式层将表达式形式化地抽象成合(析)取式对象,然后应用经典命题逻辑中的规则,通过命题逻辑形式的变换实现最简化。然而经典命题逻辑应用的局限性在于它不考虑原子命题中的非命题成份[5],而本文讨论的表达式优化要更进一步,最终实现在命题元素层次进行优化,为此设计了“单字段优化和逻辑验证”类和“多字段间关系自动推理”类来继承合(析)取式类,并相应地提出和实现了具体的算法模型。查询重写的面向对象框架提供了较好的灵活性和可扩展性。

2 最简合(析)取式层

经过预处理的表达式可以形式化地抽象成两种,一是析取式,二是先析取再合取的合取式。最简合(析)取式层针对合取式对象,基于经典命题逻辑的等幂律和吸收律,对其进行简化。算法思想是首先要对每个析取式进行编码,用数0,1,2(即反变量,原变量,空)来表示析取式中每个原子命题的三种取值,增加程序的可读性[6]。根据等幂律,如果有相同编码就只保留一个,然后根据析取式编码中1的个数从小到大排序,循环检测是否有析取式被合取式中的其它析取式包含,有则删除,实现吸收律。本功能超过了MySQL手册中说明的功能[7]。系统框架采用面向对象设计的优点是为优化系统提供了较好的可扩展性,可以方便地扩充对其它经典命题逻辑规则的支持。

3 命题元素优化层

命题元素的优化针对单字段对象和多字段对象有不同的处理策略。

3.1 单字段的优化和逻辑验证类

为了实现单字段对象两个条件及多个条件的优化和逻辑验证,要借助一个数据模型:关系运算符分析表ROAT(Relational Operators Analysis Table)。ROAT有6个单元分别对应=、≠、>、 ≥、<、≤ 6种关系运算符,除了≠单元可以多值外其余单元均为单个数值。ROAT的每个单元初始化时均置为Double.MinValue(计算机表示的最小可能值,实际条件的右部不会出现此数值)。如果某字段的ROAT的某单元的值大于MinValue,则说明该字段条件有该运算符,原子条件的右部就是单元内的数值。

3.1.1 ROAT的构造

根据单字段对象的条件对ROAT的单元进行赋值,每个单元的第一次赋值直接保存。第二次及以后赋值只有符合规则的新值才能替换原值,新值和原值的比较规则见图3。

3.1.2 ROAT的逻辑一致性保证

当单字段对象的ROAT构造完成后,还要保证ROAT的逻辑一致性,即循环判断各关系运算符间是否还能优化,或是否有冲突。经研究共有24种情况,本文仅对相对比较复杂的A ≠ a and A ≥ b举例说明,如表1所示,其余部分的比较如法制作。

根据条件构造ROAT,可知ROAT[2]=a,ROAT[4]=b。

ⅰ) 当a>b时,已是最简,故无需进一步处理。

ⅱ) 当a<b时,结果应为A >=b,为了去掉A ≠ a这个冗余条件,ROAT[2]=min。因为按照取值规则,最后生成A字段的优化条件时min不起作用。

ⅲ) 当a=b时,结果应为A>a,由“≠”、“≥”这两个运算符推出了“>”运算符单元中的值,所以ROAT[2]=ROAT[4]=min,而a向ROAT[3] (代表“>”)赋值时还要和ROAT[3]中的原值比较,a比原值大才替换,ROAT[3]=max(a,ROAT[3])。

根据上述步骤,条件用ROAT表示后循环查表比较,可以实现每个析取式中的单字段条件优化。合取式中如果存在单字段多条件的情况如A >=a OR A>=b同理可再优化,不再赘述。

3.2 多字段间关系自动推理类

定义 2 扩展表:不重复地记录从该顶点出发能访问到的所有图中顶点的数据模型。

字段间还可能存在偏序关系,如A>B AND B>C AND A>C,可以简化为等价的A>B AND B>C,因为A>C完全可以由前两个多字段间关系推理得到。完成具有偏序关系的多字段间关系自动推理的算法思想如下:

1) 预处理工作:为保证符号方向统一,将“<”换成“>”,“≤”换成“≥”,字段在关系算符左右对换,如A>B换成B<A。

2) 将表达式中的每个字段抽象成图中的一个顶点,字段间的关系抽象成图中的边,那么表达式就可以构造成有向图,为每个顶点建立邻接表。优化的目标就等价转换为去除图中多余的边。

3) 为每个顶点建立相应的扩展表。

4) 根据扩展表,删除每个顶点邻接表中的冗余元素,即多字段间冗余关系被删除,再把优化后的邻接表翻译成表达式。

例如有表达式A>B and A>C and A>D and C>B and C>E and D>E and F>D and F>E,构造的有向图如图4(为了描述方便,A记作V1,B记作V2,依次类推),优化后的有向图即为图5。

实现多字段间字段推理的关键算法介绍如下:

3.2.1 建立扩展表算法

(1) 每次读取一个顶点入栈

(2) 当一个顶点的所有邻接表元素都被完整访问,该顶点出栈,否则继续执行

(2.1) 读取第一个邻接表元素

(2.2) if 某元素被完整访问

(2.2.1) 该元素无邻接表元素,加入顶点的扩展表,执行(2.2.3)

(2.2.2) 该元素有邻接表元素,该元素和其扩展表中的所有元素带检查地加入顶点的扩展表,并要保证邻接表元素不重复

(2.2.3) 继续检查下一个元素,转(2.2)

(2.3) else

该元素作为顶点入栈,进行递归,转(2)

其中入栈检查的目的是检查将入栈的顶点是否与已入栈的顶点相同,如有相同还要循环检查顶点之间的符号。如果都是“>=”,就更改这些顶点的关系为“=”,如A>=B,B>=C,C>=A,实际就是A=B=C。否则如A>=B,B>=C,C>A,就报错。

3.2.2 删除顶点邻接表的冗余元素算法每次取图中一个顶点S=该顶点所有扩展表元素

for (g=S的第一个元素;g<=S的最后一个元素;g++)

T=S-g

for (g’=T的第一个元素;g’=T的最后一个元素;g’++)

M=g’的所有扩展表元素

检查g是否包含于M

包含立即删除

前例根据算法3.2.1和3.2.2建立的扩展表如图7所示,得到优化后的邻接表如图8所示。

4 测试结果分析

在上海市轨道交通AFC运营管理数据分析系统的表示层输入查询语句(选择中央车站设备节点标识表中的英文名称索引En_name_index等字段):

(( En_name_index >= 15 & En_name_index > 10 ) and Ch_name_index < 5 or ( En_name_index > Line_id and Ch_name_index >= Site_id and ( Ch_name_index > En_name_index ) and Line_id <= Ch_name_index )) or (( Ch_name_index < 5 and En_name_index >= 15 ) and ( En_name_index > 10 and Site_id = 7 ))。

立即化简为:

En_name_index >= 15 and Ch_name_index < 5 or En_name_index > Line_id and Ch_name_index > En_name_index and Ch_name_index >= Site_id。

另外作者设计了20多例查询语句对系统性能进行对比测试,测试内容是查询表达式分别在优化和未优化的情况下执行数据抽取的结果和耗费时间(不含打印数据时间)。实验结果显示每组测试用例抽取的数据完全一致。为了简明起见,选取其中3组执行了不同部分的查询优化算法的典型用例,其执行时间如表2所示。实验证明本文提出的算法是正确而高效的。

5 结 论

本文介绍了查询优化的过程,并提出了一种面向对象的框架应用于查询重写阶段,将WHERE子句化简为最简合(析)取式,创造性地提出和实现了“单字段优化和逻辑验证”,“多字段间关系自动推理”等算法,为数据库查询优化的重写机制的实现提供参考。把查询重写后的表达式传到下一个计划优化模块,结合起来应用于数据库应用系统中,在数据抽取前保证用户查询语句正确、合适,提高系统效率。

摘要:查询是数据库应用系统中使用最频繁的操作,其执行效率很大程度上影响了整个系统的性能。介绍了查询表达式优化的一般过程,在查询重写阶段提出了一种面向对象的框架,设计和实现了“多字段间关系自动推理”等若干种优化算法。测试结果表明,查询取得了良好的优化效果。

关键词:查询表达式优化,where子句,查询重写

参考文献

[1]Surajit Chaudhur.An Overview of Query Optimization in Relational Systems[C].Proceedings of the17th ACMSIGACT—SIGMOD—SI—GARTSymposium on Principles of Database Systems,1998:34-43.

[2]许向阳,徐持恒.查询优化器的面向对象框架[J].计算机应用研究,2005,10:71-73.

[3]陆忠良,苏厚勤.基于Oracle/Linux环境数据抽取技术的研究与实践[J].四川大学学报:工程科学版,2007,39(增刊).

[4]许平格,卜佳俊.OSCAR查询优化器的设计与实现[J].计算机应用研究,2005,12:181-183.

[5]陆钟万.面向计算机科学的数理逻辑[M].北京:科学出版社,2002.

[6]朱幼莲.计算机化简逻辑函数的算法研究[J].南京理工大学学报:自然科学版,2003(4).

[7]MySQL参考手册[EB/OL].http://dev.mysql.com/doc/.

数据库查询语句优化方法 篇2

1、没有创建索引,或者没有正确地使用索引。这是最有可能影响数据库查询的原因之一。创建索引是优化数据库查询效率的重要手段。

2、存在死锁的情况,从而导致Select语句挂起,无法返回结果集。

3、返回不必要的列,很多程序员喜欢使用Select * from TableName 来查询表可视图中的数据,* 代表表或视图中所有字段,建议用户在使用Select语句时,只返回必要的列。浪费更多的系统资源,从而影响查询效率。

4、在Select语句中使用Where字句,设置查询条件,只返回必要的记录。

5、在Select语句中使用Top 关键字,限制返回的记录数量。

6、如果在Where字句中使用Like谓词进行模糊查询,则要注意通配符的使用方法。

7、慎用Union关键字,因为它会影响查询的效率。

8、慎用Distinct关键字,因为在结果集中返回重复的记录并不会影响查询的效率。相反,过滤掉重复的记录会浪费查询的时间和系统资源。因此,除非必须如此,不要使用Distinct关键字。

9、如果需要经常对表中的数据进行统计,可以在表中增加一个统计字段,每次表中数据发生变化时,动态更新统计字段。这样,在查询统计结果时,就不需要临时对表中的数据统计计算了。

10、如果需要多次对一个数据量非常大的表中的一部分数据进行查询操作,可以将这部分数据保存到临时表中,然后对临时表进行查询操作。如果需要,可以在临时表上创建索引。

11、在Where字句中,有时使用Between关键字比使用In关键字要快,因为In关键字对其后面的集合中的每个元素进行比较操作。如果必须使用In关键字,则可将频繁使用的值放在集合的前面,从而减少比较的次数。

12、尽量少使用视图,特别是嵌套视图,可以直接从表中获取数据。在开发应用程序时,有时程序员为了方便,设计一个包含很多字段的大视图,无论需要什么数据,都可以通过查询此视图获取到。实际上,最好从表直接获取数据,以避免查询大视图而造成的系统开销。建议使用存储过程代替视图,从而提高执行的效率。

13、如果不需对结果集进行排序,则不要使用Order By字句,因为排序操作会占用系统资源。

14、不要在Where字句中“=”的左侧使用函数和表达式,因为系统将无法应用函数或表达式中的索引。

15、当判断表中包含记录时,使用Exists关键字,而不要使用Count统计表中所有的记录数量。

你的数据库应用系统违反几条建议?欢迎提出更多优化建议!

查询重写关系数据库查询优化技术 篇3

关键词:查询重写,数据库,查询优化

引言

查询优化是数据库管理系统设计与实现所采用的一项重要技术,它是影响数据库性能的关键因素,当前所有的商用数据库都成功地采用了这项技术。但由于目前Internet上存在着大量的半结构化数据,信息集成过程中也产生了大量的半结构化视图,因此如何利用半结构化视图来重写用户查询,减少响应时间成为当前此领域研究的热点问题。

1 优化视图重写

SQL语言是一个描述性的非过程化语言,用户在写SQL语句的时候,不用知道要操作的数据具体是如何存放的以及必须按照什么步骤才能进行处理,查询处理器会自动完成这些工作。但是,查询语句操作的数据库对象除了可能是基本表以外,还可能是视图,如果查询处理器直接对视图进行操作的话,查询优化器所能生成的执行计划的唯一选择就是先执行视图定义,再将视图的查询结果作为一个临时表参与查询的其余处理,这种处理方式在绝大多数情况下效率极低,此时,可以认为用户提供的查询蕴含了过程性。查询重写的目标之一就是将过程性查询转换为描述性的,因此,优化器需要对视图进行重写,也就是将对视图的引用转换为对视图所涉及的基本表的引用,而得到一个语义上完全等价的查询,且重写后的查询效率可以比原来提高很多倍。根据关系数据库查询处理过程,要想提高数据库系统的查询效率,必须编写出性能较优的查询语句。

下面举例来说明视图重写的基本方法。假设一个数据库中包含以下几个关系:

emp (name,age,sal,dno)

dept (dno,dname,floor,budget,mgr,ano)

acnt (ano,type,balance,bno)

blank (bno,bname,address)

例:

select emp_view.name

From emp_view,dept_view

Where emp_view.dno=dept_view.dno and dept_view.dname='市埸部'

查询市場部所有员工的姓名,其中emp_view和dept_view均为视图,定义如下:

create view emp_view (name,dno)

As select name,dno

From emp

Create view dept_view (dno,dname)

As select dno,dname

From dept

以上查询经过视图重写后变换为以下查询,这样就转化为两个基本表的连接操作了。

Select emp.name

From emp,dname

Where emp.dno=dept.dno and dept.name='市場部’

2 基于嵌套子查询的重写

当查询涉及两个表时,如果先连接成一个表后再查询,其中间结果会很大,形成一个临时表放在硬盘中,对该表的操作(表的生成、查询)都可能会有多次访盘,导致效率较低,有时还会产生巨大的运算量,增加对内存的需求。严重时可使软件在执行中出现异常。使用嵌套子查询时每次先执行子查询,产生的中间表规模小,效率远比连接后查询的效率高。

2.1 子查询合并规则

(1)如果外层查询的结果没有重复,即SELECT子句中包含主码,则可以合并其子查询,并且合并后的SELECT子句前应加上DISTINCT标志。

(2)如果外层查询的SELECT子句中有DISTINCT标志,那么可以直接进行子查询合并。

(3)如果内部子查询结果没有重复元组,则可以合并。

2.2 子查询合并

步骤:

(1)将子查询外层查询的FROM子句连接成为一个FROM子句,并具修改相应的运行参数。

(2)将子查询的谓词符号作相应修改(如“IN”修改为“=”)

(3)将子查询的WHERE条件作为一个整体与外层查询的WHERE条件合并,并用AND连接词连接,从而保证新生成的谓词的上下文意思相同,并且成为一个整体。

如:

可重写为:

这里需要指出的是,以上讨论的子查询合并规则只适应于单层嵌套子查询,对于多层嵌套子查询处理能力受到一定限制。

3 等价谓词重写

由于执行引擎对各种谓词的处理方法不同,因此把逻辑表达式重写成等价的且效率较高的表达式是提高效率的有效方法,同时也是切实可行的。笔者通过查阅大量的文献资料以及大量的实验,分析了RDBMS执行引擎对各种谓词执行效率的不同,总结出以下谓词转换规则。

(1)将多个OR连接的谓词转化为ANY表达式

(lexp preop rexp1) or (lexp preop rexp2) or (lexp preop rexp3) or…

lexp preop any (rexp1,rexp2,rexp3,…)

考虑条件表达式中同层次由连接词OR连接的谓词,如果谓词的左表达式lexp相同且谓词符号preop也相同(不包括IN谓词),那么可以将谓词合并为一个右表达式用ANY来描述的谓词。如:

(sal>1000 and dno=3) or (sal>1000 and dno=4) or (sal>1000 and dno=5)

可重写为:

sal>1000 and any (dno=3,dno=4,dno=5)

(2)将ANY或ALL转化为单个值

lexp preop any (rexp1,rexp2,rexp3,…) lexp preoprexp1

lexp preop all (rexp1,rexp2,rexp3,…) lexp preop rex-pn

用于右表达式为ANY或ALL的形式,若ANY (ALL)包含的各表达式有固定值,并且可以比较大小,则可根据谓词符号(仅限于比较大小的操作符)将ANY (ALL)重写为单个值。如:

len>ANY (3,sqrt (8),5*5)可重写为:len>sqrt (8);

len>ALL (3,sqrt (8),5*5)可重写为:len>25;

(3)将BETWEEN转化为AND连接的谓词

lexp between rexp1 and rexp2lexp>=rexp1 and lexp<=rexp2

用于由between rexp1 and rexp2的形式重写为用AND连接的两个谓词,效率往往有一定的提高。如:

Age between 20 and 30重写为:age>=20 and age<=30

(4)将IN谓词表达式扩展为OR连接的谓词表达式

lexp in (rexp1,rexp2,rexp3,…)

lexp=rexp1 or lexp=rexp2 or lexp=rexp3 or…

把IN谓词转换为一串OR连接的表达式。如:

Age in (20,30,40)

重写为:

age=20 or age=30 or age=40

以上所提到的四类谓词重写规则均有其特定的条件,在条件满足的情况下才可以使用。对于简单谓词的重写,每条规则提高的效率可能不太明显,但如果查询语句的WHERE条件同时使用多条规则进行重写时那么效率的提高将非常可观。

4 临时表的重写

在数据库中创建一张表,这个表不用于其他的什么功能,主要用于自己的软件系统的一些特殊功能才用的,而当你用完之后表中的数据就没用了。通常,数据库的临时表创建之后基本不占用表空间,如果你没有指定临时表存放的表空间的时候,插入到临时表的数据是存放在系统的临时表空间中。使用临时表可以避免多重排序操作,而且在其他方面也可以简化优化器的工作。例如有下面的语句:

SELECT*FROM student,thesis WHERE student.ID=the-sis.student-ID and student.id>‘0500000’and thesis.type=‘2’ORDER BY student.ID;

如果这个查询要被执行多次而不止一次,可以把所有论文类型为2号的学生的信息找出来放在一个临时文件中,并按学号排序:

SELECT*FROM student,thesis WHERE student.ID=the-sis.student ID and thesis.type=‘2’ORDER BY student.ID IN-TO TEMP sthe;

然后以下面的方式在临时表中查询:SELECT*FROM sthe WHERE sthe.ID>‘0500000*

临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。

5 结语

优化要抓住关键问题,对于数据库应用程序来说,重点在于如何提高SQL的执行效率。在数据库的开发和维护过程中,查询的优化设计可以提高系统性能,对于海量数据库系统尤为重要。要正确地使用它们,另外在提高查询效率的同时还要兼顾程序的正确性和数据的安全性,只有这样才能真正起到查询优化的作用。

参考文献

[1]杨晓春,王丹,王国仁等.虚拟企业环境中支持完整性约??束的主动规则[J].东北大学学报(自然科学版),2001, 22.

[2]C.Yu,L.Popa.Constraint-Based XML Query Rewriting for Data Integration.In:Proc.of the Intl Conf.on Management of Data (SIGMOD),2004.

XML代数查询优化研究 篇4

XQuery是XML查询语言的推荐标准。XQuery处理策略有两种方法,一种是基于核心语法一次一结点的方法,另一种是基于查询代数的一次一集合的方法。单独使用这两种方法都不能很好地处理XQuery查询。一方面,基于核心语法树的方法效率低,而且很难优化,而现有基于代数的方法又不能很好地满足XQuery的过程化查询语言的特性。基于这样的目的文献[1]提出了一种名为Oreint XA的有效查询代数,该代数结合了一次一结点及一次一结合的两种处理方法,是一种有效的代数系统。该代数的优点是根据XQuery语言的特点,明确提出了包括强绑定/弱绑定、结点绑定/序列绑定等概念;引入Sequence操作符,有效结合了两种XQuery处理策略的特点,能有效地表达XQuery查询,这是Orient XA区别于现有XML代数系统的最大不同之处。

2 问题的提出

XML的查询优化,工作内容有两部分:

(1)逻辑代数的定义及逻辑优化技术,这里的逻辑代数可以转化为不同的物理代数,例如原生代数或是扩展关系代数。

(2)物理存储结构的设计和物理优化技术。

从优化策略上看,XML数据管理的数据库支持有两类,扩展关系型数据库和原生型数据库。对于扩展关系型数据库,是将XML文档转换成关系数据,将XQuery转换成SQL表达式,查询优化的空间为从XQuery到SQL的转换空间和SQL自身的优化空间。对于原生型数据库,是将XML文档直接存储于物理存储设备,以标记有序树作为数据模型,XQuery查询将转换为一系列的作用于XML树上的操作,查询优化的空间在于操作本身。

从优化层次上看可分为:

(1)语言级:查询语言的优化。

(2)代数级:查询代数的优化。

(3)物理操作级:物理优化技术。

在文献[1]提出的代数系统基础上,本文考虑代数级的优化。优化的目标是,在得到相同结果集情况下,使查询执行更有效,更少的执行时间。

3 问题研究

XML树形结构数据模型比关系模型在本质上有更强的复杂性,从而给XML的查询优化带来了困难。由于效率原因,传统的基于代价估计的查询优化并不适宜大量XML数据的查询。因此本文采用了基于启发式的代数查询重写方法,即将XML查询表达式写成代数表达式,完全采用等价的方式来处理代数表达式,从而获得更好的查询效率。

谓词下移是关系数据库中进行启发式查询优化中的重要手段。很多文献都有介绍。在XML数据库中,也考虑选择谓词下移策略。

上边的查询,选择谓词$b/author/first="Smith"就可以先于连接操作执行,以使参与连接的集合变小。一般来说,如果一个内层谓词提到外层之后,该谓词所约束的子句是一样的,那么该谓词就可以提到外层,以提高查询效率。但是,对于XML查询以模式树结构作为操作对象,在选择谓词下移时,还需要考虑选择操作的范围问题。

选择谓词$b/title=$v/title的操作范围是(用XPath表示)doc("http://bookstore1.com/bib.xml")//book[publisher="Adsion"]&

doc("http://bookstore2.com/bib.xml")//review。但是针对谓词$b/author/first="Smith"的操作范围是受{$v/content}影响的,而不是doc("http://bookstore.com/bib.xml")//book[publisher="Adsion"]。因此不能将谓词下移到$b/title=$v/title执行。

除了选择操作下移可以提高查询效率外,抽取操作的尽早执行,也可以尽早给出模式树,一方面,减小模式树的规模,另一方面,也减少扫描文档的次数。考虑通过改变抽取与其他操作的次序,将抽取操作合并。

在XQuery代数中,由于抽取操作可能作用于大的文档产生任意多的实例树,是一个潜在的昂贵操作。在查询计划中,考虑将多个抽取操作合并。这样,全部抽取操作的代价可以降低,避免多次扫描文档。另一方面,可能将一个抽取工作拆开,由多个抽取操作完成,以实现子表达式的重用。

由于XQuery没有显式的GROUPBY语句,查询结果的分组通常由嵌套的FLWR表达式实现,将其转换成一个连接操作。这样的连接操作是作用于同一文档的,成为自连接。考虑取消这种连接,因为连接操作是比较费时的操作,而抽取则相对省时。有下面的规则X1!"c X2=EP1∪P2,假设X1,X2的模式树分别为P1,P2,如果P1,P2为同一文档,那么用抽取操作代替连接操作,这时操作范围被改变为这个文档,抽取模式树P1∪P2。

看下面的一个例子,通过静态的路径投影来实现连接的结果。

let$p=doc("http://bookstore.com/price.xml")/book[title=$t]/price可以改写成为

let$b=doc("http://bookstore.com/price.xml")/book[title=$t],let$p=$b/price。

除了上面给出的启发性原则,还有一些原则,如先分组后连接,提取公共表达式等。

4 总结及展望

以上在Oreint XA的基础上,给出了查询优化的等价变换公式,提出五种启发性优化原则,特别是如何利用语义信息进行优化,提高了查询的效率,达到了优化的目的。但是本文给出的启发性原则中,如何快速的判断谓词的作用域并且确定什么时候谓词下移,是我们将来需要研究的方向之一。提取表达式中,如何解决嵌套问题,也是将来研究的方向。

摘要:随着XML数据大量出现在Web上,XML数据库研究成为数据库研究热点。逻辑代数的定义及逻辑优化技术是查询优化的一个方向。在OreintXA代数的基础上,考虑代数级的优化,优化目标是,在相同结果集情况下,使查询执行更有效,执行时间更短。

关键词:XML,查询优化,代数

参考文献

[1]罗道锋,蒋瑜,孟小峰.OrientXA:一种有效的XQuery查询代数[J].软件学报,2004,15(11):1648-1660.

[2]何震瀛,李建中,王朝坤.一种XML数据库的数据模型[J].软件学报,2006,17(4):759-769.

[3]World Wide Web Consortium(W3C).XML Schema.http://www.w3c.org/TR/xmlschema-2,2001.

[4]Abiteboul S,Buneman,P,and Suciu D.Data on the Web:From Relations to Semistructured Data and XML.Morgan Kauf-mann Publishers,2000.

查询表达式优化 篇5

关键词:SQL Server,查询优化,索引,SQL优化

引言

为了缩短大数据量的查询处理时间, 提高数据库应用系统的效率。提出了针对SQL语句进行优化的策略。查询优化就是把原有的SQL语句转换成为在功能上相同而执行效率更高的SQL语句, 以下是SQL SERVER数据库管理系统查询优化的一些主要方法。

1. 合理使用索引

索引是数据库管理系统中最主要的也是最常用的查询优化方法, 其作用相当于书的日录, 可快速定位所需查找的数据行, 避免全表扫描的发生。在SQL Server中, 索引用B-树这种数据结构来构造, 索引记录中包含索引键值及指向索引键值所对应的表行实际存储位置 (即, 指向实际存储数据行的数据页面的地址) 的指针两部分内容。其通过寻找一条从根节点到叶子节点的路径来快速查找数据。它只需少数的几个I/O操作就可以在短时间内定位到表中相应的行, 比从头至尾逐行比较的顺序访问数据表在平均时间上要少, 从而达到优化查询的目的。

然而, 由于索引是一种独立于数据表的数据库对象, 需要占用磁盘空间以保存索引信息, 另外当表数据进行更改时, 相应的索引信息也要作出相应的更改, 因此增加了一些额外的开销。并且在实际的查询操作中, 已创建的索引是否被使用, 还取决于SQL Server的查询优化器、查询语句的书写方式等因素。因此, 如果索引创建过多或者创建的不恰当, 不仅不能起到查询优化的作用, 反而会适得其反, 降低系统的查询效率。

建立合理的索引看似容易实际操作起来很有难度。其难点在于判断哪些是必要的索引, 哪些又不是必要的。要合理的使用索引提升查询的性能, 需要对SQL Server数据库的SQL语句相当熟悉, 知道常用的可能对性能有影响的SQL语句, 同时需要分析、归纳出在Where条件子句中出现频率较高的列以及作为主键、外键那些列以及值唯一的那些键等等;在这些判断的基础上可以初步确定哪些表的哪些列应该建立索引。其次, 必须熟悉应用程序。必须了解数据操作频繁的表;经常与其他表进行连接的表;数据量可能很大的表;对于数据量大的表, 其中各个字段的数据分布的详细情况等等。对于满足以上条件的这些表, 需要加以重点关注, 因为在这些表上的索引, 将对SQL语句的效率及性能产生举足轻重的影响。因此, 这里简单总结了创建索引的各个原则。

考虑创建索引的列:

(1) 由于很多查询都是通过主键来设置查询条件的, 所以应在表的主键列上建立聚簇索引, 尤其是当用主键列进行多表联接的时候, 更应当在主键上创建聚集索引。

(2) 多表联接中频繁使用的列, 应当创建索引, 以减少这些列值的查找时间。

(3) 对于经常有范围查询、排序和分组发生的列, 或者频繁查询的列, 可考虑建立聚簇索引;

(4) 如果知道所有索引键值都是唯一的, 那么应当把索引定义成唯一索引;

不考虑创建索引的列:

(1) 查询中很少涉及的列不创建索引, 因为系统很少或从来不根据这个列的值去查找数据行。

(2) 只有少数几个值的列 (如性别列, 只有两个值“男”或“女”) , 在这样的列上创建索引并不能性能上的提升。

(3) 对于频繁更改的表, 尽量少创建索引, 同时小表一般也没有必要创建索引。

如果表上的索引过多会影响对表的更新、插入、删除等操作的性能, 因为更改操作导致索引信息必须相应的更改。所以, 索引应根据需要而定, 不要盲目多建。

(4) 避免在任何可以为空的列上创建索引。

(5) 避免使用复合索引中的非首列作为Where子句的第一个条件。

如果表中存在复合索引, 该复合索引关键字的排列顺序决定了索引的排序方式, 也就影响着SQL Server使用索引进行查找的方式。因此, 在书写where子句时, 尽可能将索引首列用于第一个查询条件。

有时尽管在列上建立了索引, 但SQL语句执行时, 所期望的索引是否被使用, 还要具体分析。因为wher子句中的有些条件谓词可能会强迫查询优化器使用全表扫描方式来顺序访问。例如下面的查询将迫使查询优化器对orders表执行顺序扫描:

SELECT*FROM orders

WHERE (cusid=104 AND orderid>1001) OR orderid=1008

虽然在cusid和orderid上建有索引, 但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。可以把SQL语句书写成下面的形式, 就利用到我们所期望的索引:

SELECT*FROM orders WHERE cusid=104 AND orderid>1001

UNION ALL

SELECT*FROM orders WHERE orderid=1008

在SQL语句中, 具体哪些情况会影响到索引的使用, 将在下面的SQL语句优化中更多的看到。

2. SQL语句的优化

实现相同查询功能的SQL语句的书写方式有很多, 然而不同方式书写的SQL语句执行效率各不相同, 有时甚至相差甚远。为了提高查询性能, 除了合理的使用索引外, 编写高效的查询语句是另一个非常重要的因素。一般而言, 构造高效的查询语句应注意以下一些技巧:

(1) 只选择实际所需要的列

在SELECT子句的列列表中只列出实际需要的列, 少用通配符*。这可以减少客户/服务器之间传输的数据量, 尤其是当客户/服务器连接距离比较远时效果更明显。其次是, 当系统遇到SELECT*时, 会先分析数据表的结构, 然后把表的所有字段名再罗列出来, 增加了系统分析的时间;

(2) WHERE后的条件语句尽量少用IN/NOT IN和IS NULL/IS NOT NULL语句, IN/NOT IN用EXISTS/NOT EXISTS代替。WHERE子句中使用这些谓词会导致系统不使用索引扫描而是进行全表扫描, 需要根据具体情况改变查询语句。

(3) 避免对查询条件中出现的列进行操作

对查询条件中出现的列进行任何操作都可能会导致全表扫描, 即使在相应在列上建有索引。这里的操作包括数据库函数、计算表达式、使用复杂谓词、使用否定谓词等等。为避免使用表扫描, 在where子句中尽可能的避免使用不可求值的表达式、尽量避免将列引用在表达式或函数中, 避免使用否定谓词 (比如, NOT、NOT IN、!=、◇和NOT LIKE, 以及通配符引导的字符串) 以及复杂的谓词 (如IN、LIKE等) 。这是由于where子句中对列的任何操作结果都是在SQL运行时逐行计算得到的, 因此它不得不进行表扫描, 而没有使用该列上面的索引;如果查询条件中列的值在查询编译时就能得到, 那么就可以被SQL优化器优化, 使用索引, 避免表扫描。对查询条件中的列进行操作的示例有很多。

例如, 在EMP_Name列上创建有单列索引, 对于类似EMP_Name LIKE‘%林’ (通配符引导的字符串) 、len (EMP_Name) =1 (对列使用函数) 、EMP_Name IN (‘Tom’、‘Bob’、‘BenjeMin’ (使用了复杂的IN谓词) 等情况, 都不能使用该索引进行查找。如果可以尽可能的使用“=”, 以减少使用“LIKE“谓词的使用。而对于LIKE谓词而言, 因为其使用的非常频繁, 因此如果能够对LIKE子句使用索引, 将使查询的效率进一步提高。这要求LIKE子句尽量进行前端匹配。

例:select*from book where Bname LIKE‘%S%’

以上查询的执行计划用了全表扫描 (TABLE ACCESS FULL) , 如果能够修改为:

select*from book where Bname LIKE‘S%'

那么查询的执行计划将会变成 (INDEX RANGE SCAN) , 成功的利用了name字段的索引。在做LIKE查询时, 应尽可能使查询的匹配端是具体数值, 也就是使用LIKE‘S%’。

(4) 尽可能的避免使用OR连接多个条件

尽可能的避免使用OR连接多个条件, 原因在于单个的索引扫描不能用来限制所有的条件。以“emp_name=’李明’and Emp_wyer>15”为例, 此时第二个条件的查询会基于第一条件使用索引查找后的集合中进行查询 (假设存在基于列emp_name的索引) 。对于“emp_name=’李明’OR Emp_wyer>15”查询条件, 在第二个条件将会重新扫描全表或重新使用索引查找, 因此会降低查询速度。对于这样的情况, 可以使用union重写查询。

(5) 基于函数的索引

对列的任何操作都可能导致全表扫描, 例如:

select*from emp where substr (ename, 1, 2) =‘SM';

但是这种查询在数据库的查询系统中经常用到, 可以创建一个带有substr函数的基于函数的索引, 例如:create index emp_ename_subst on eemp (substr (ename, 1, 2) ) ;

这样在执行上述查询语句的时侯, 基于函数的索引将会被用到。

(6) 多表联接查询优化

在多表联接查询时, FROM子句中表的排列顺序应按照表中记录数从低到高的顺序依次从左向右排列, WHERE子句中的查询条件也应该按照表的记录数从低到高的顺序排列。

在对多个表进行联接时, 在不影响查询结果的情况下, 表连接的个数越少越好;尽量先筛选后连接, 以减少表中的行数, 从而减少扫描时间。同时尽量使用表的别名, 以减少解析的时间和由字段歧义引起的语法错误。

此外, 在多表查询的时候可以通过OPTION子句指定联接方式。以使所使用的联接方式更适合自己特定的情况, 减少表的联接时间。常用的联接方式包括以下几种:FORCE OPDER (使用查询语法标明的联接方式) 、LOOP JOIN (嵌套循环联接) 、HASH JOIN (哈希联接) 、MERGE JOIN (合并联接) 。

尽可能避免笛卡尔积查询。

(7) 每一个联接查询在理论上都有一个与之等效的子查询, 在设计查询时尽可能使用联接, 而不使用子查询。

(8) 尽量避免相关子查询

SQL中的嵌套查询分为相关子查询和不相关子查询两种。不相关子查询不依赖于外部查询, 其查询独立于外部查询;而相关子查询依赖于外部查询, 一或多列同时出现在主查询和子查询中, 当外部查询中的列值发生改变时, 子查询需要重新查询, 查询嵌套层次越多, 效率越低, 因此应当尽量避免这种相关子查询, 如不能避免时, 那么要在子查询中过滤掉尽可能多的行。

3. 善于使用存储过程

用存储过程 (Procedure) 可以减少网络传输量以及提升应用程序性能和系统安全性。存储过程是SQL Server服务器上一组预先定义并编译好的T ransact-SQL语句, 它可以接受参数、返回状态值和参数值, 并且还可以嵌套调用。当一个存储过程被第一次运行时, SQL S erver将该存储过程放入内存并完全编译 (不必进行词法分析与规范化, 因为在存储过程被创建时, 这些工作就已经完成了) , 在该存储过程被再次调用时 (无论是由同一用户还是不同用户调用) , 可以被马上处理, 而没有任何额外开销。另外, 存储过程是一种模式化的程序设计, 在Client/Server的应用程序中, 使用存储过程可以方便地进行程序设计, 减少程序员的工作量。

4. 结束语

查询优化的实质就是在结果正确的前提下, 使查询语句执行时能充分利用索引, 使用索引扫描来快速定位数据, 减少表扫描的次数。好的查询优化方案可以极大的改善数据库 (尤其是大型数据库) 的性能。深入研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。

参考文献

[1]黄晶晶.基于SQL server数据库优化查询的分析[J].企业信息化.2006 (8) :181

[2]朱东.基于SQL Server的查询优化[J].信息与电脑.2011 (11) :172

SQL语句查询优化探讨 篇6

以下所用案例的数据表来自平时教学中的Sale数据库里的客户表 (members) 、产品表 (product) 、订购表 (orders) 。

(1) 算法的书写结构尽量简单:在查询时, 通配符能尽量避免就不要使用, 如下例:

select*from members

根据实际需要, 需要查询几列就选几列, 如select m_no, m_name, m_pwd from members;另外, 某些情况下用户是不需要那么多的数据, 尽量限制结果集行数, 如:select top 13 m_no, m_name, m_pwd from members。

(2) 尽量使用兼容的数据类型。如float和int、char和numeric是不兼容的。不兼容的数据类型可能使优化器无法执行一些本来可以进行的优化操作[3]。例如:

Select p_price from product where p_price>500

在这个查询语句中, p_price列是money型的, 优化器很难将其优化, 因为这里的500是int型, RDBMS将2000转化成为money型要耗费时间进行比较。我们应在写SQL时将整形2000转化成为money型, 而不由系统自动来转化。如下:

Select p_price from product where p_price>$500

(3) 避免在WHERE子句中对字段进行函数或表达式计算操作, 这将导致系统放弃用索引而对全表扫描。如下例所示:

A组:Select*from product where p_price/3=600;

B组:Select*from product where p_price=600*3

B组的SQL代码, 经过了优化后, 查询速度提高了十倍。因为, 数据库优化器在面对B组的p_price=600*3时, 会自动转换成p_price=1800进行查询, 却不能将A组中的p_price/3=600进行转换。

(4) 尽量不要使用!=或<>、IS NULL或IN、NOTIN、OR等这样的操作符, 这些操作符会使系统无法使用索引, 却只能直接搜索表中的数据。如以下两个查询语句之间的差别:

A组:Select*from members where m_age>25

B组:Select*from members where m_age>=25

A组中, 系统要读所有值为25的索引页面, 直到找到值为25的开始处, 而B组中, 系统直接从>25的页面开始读数据。

使用I N、O R子句的查询语句中, 在W H E R E子句中的“I N”使用结果相当于“OR”, 工作表中索引失效。在不会有大量重复值的情况下, 可以将子句拆分开, 但拆分的子句中应该包含索引。

(5) 尽可能使用数字型字段, 有些开发人员和数据库管理人员喜欢把包含数值信息的属性列设计为字符型, 这样会降低查询性能, 并会增加系统存储开销。因为系统在处理查询会逐个比较字符串中每一个字符, 而对于数字型只需要比较一次就行了。

(6) 在某些情况下, 合理使用EXISTS、NOT EXISTS子句, 将不会产生大量锁定的表扫描或是索引扫描。

(7) 如果想查询表中是否存在某条记录, 不要用count (*) , 语句效率很低, 浪费服务器资源。可以用EXISTS实现。如可以将

IF (SELECT COUNT (*) FROM product WHERE p_kind='电器') >0写成:

IF EXISTS (SELECT*FROM product WHERE p_kind='电器')

(8) 尽量不要使用matches和like关键字。

matches和like关键字是进行通配符匹配。但使用了这种表达式做查询操作非常费时, 例如, 在客户表中通过客户号查询2004年客户的相关信息:

SELECT*FROM members where m_no LIKE‘2004%’

即使m_no列上已经建立了索引, 还是采用整表扫描的方式。若把语句改为:

SELECT*FROM members where m_no>‘20040101001’

SQL就会利用索引来进行, 大大提高查询速度。

(9) 尽量不要相关嵌套查询。

SQL中的相关嵌套查询基本上是被处理成获取参数并返回一个单独的值或值的集合的函数。它的执行方式如下:首先, 计算位于上层查询的FROM子句中各个关系的笛卡尔积, 然后, 对该笛卡尔积的每个记录用位于WHERE子句中的谓词进行测试。这种执行方式效率慢, 因为嵌套查询要对应位于上层查询的每一个记录进行计算, 从而导致大量的随机磁盘I/O操作。在实际应用中, 如果可以用连接查询代替嵌套查询, 则用连接查询实现。如果嵌套查询不可避免, 那么要将嵌套查询中多的行过滤掉。例如下面嵌套查询比较费时[2]:

SELECT m_name FROM members WHERE exists (select*from members, orders where o_quantity>100 and members.m_no=orders.m_no)

而使用连接查询替代嵌套查询能大大提高查询速度, 达到优化目的。

SELECT m_name FROM members, orders WHERE o_quantity>100 and members.m_no=orders.m_no

(10) 使用视图可以提高查询速度。如创建一个查询用来查找某件产品是否被某个客户订购, 这个查询要被执行多次, 可以把所有未被订购的产品找出来放在一个视图中, 并按产品名排序如:

CREATE VIEW V_pro

A S

SELECTp_name, p_priceFROM product, orders

Where product.p_no=orders.p_no and o_pay_state=0

SELECT*FROM V_pro WHERE p_name=’电视机’

视图中的行比主表中的行少, 不仅减少了磁盘I/O, 而且物理顺序即是所要求的顺序, 因而查询工作量大幅减少。

(1 1) 尽可能用B E T W E E N的就不要用IN, 如:

SELECT*FROM product WHERE p_price IN (200, 2500, 30000, 4000)

改成:SELECT*FROM product WHERE p_price BETWEEN 200 AND30000

IN在系统中的索引没法使用, 只能全表搜索数据。

本文通过设计查询Sale数据库的三张表数据的SQL语句, 进行分析比较, 得出较优的SQL语句编写方法, 通过提高数据库系统查询数据速度以达到系统优化性能。

摘要:越来越多的数据库应用系统正在投入使用, 多数人遇到数据库系统性能问题都要检查系统级组件:内存大小、处理器数量和速度等等。调整这些组件会消除许多性能问题, 但是也可能会隐藏一些潜在的问题, 这些问题可以通过调整应用或用户发出的实际SQL查询得到解决。

关键词:数据库,性能,SQL

参考文献

[1]刘志成.数据库系统原理与应用SQL Server2000[M].机械工业出版社, 2007 (3) .

[2]许平格.数据库管理系统中查询优化的设计和实现[D].浙江大学图书馆, 2005.

关系数据库查询优化研究 篇7

在数据库应用系统中,查询操作所占据的比重最大,其优劣直接影响该应用系统的性能,本文从关系数据库查询现状入手,指出关系数据库查询优化的基本原则,总结出关系数据库查询优化的多种实现途径及方法。

二、数据库查询现状

随着计算机应用的不断深入和数据库技术的不断发展,几乎所有的应用程序都要和数据库打交道,目前,绝大多数的数据库应用软件都是基于关系数据库系统。通过查询数据库可以很容易地获得想要的数据。但是,现实中数据库系统只重视用户界面的华丽,而对于查询语句的效率并不重视,导致应用系统中某些查询耗时长,响应速度慢,甚至查询结果不够准确,系统性能极为低下,资源浪费严重。因此对查询操作进行优化处理十分必要。

三、关系数据库查询优化的基本原则

对关系数据库查询优化应遵行以下基本原则:

1选择运算应尽可能先做,以得到较小的中间结果;

2在执行连接前对关系适当地预处理;

3把投影运算和选择运算同时进行,减少分开操作造成多次扫描文件;

4把投影同其相邻的双目运算结合起来;

5把某些选择同在它前面要执行的笛卡尔积结合起来成为一个连接运算,减少时间和空间的开销;

6按照小关系运算优化处理的原则,减少中间结果;

7将表中与查询无关的属性去除,减少中间结果;

8找出公共子表达式,预先计算并保存起来.以免重复计算从而节省操作时间。

四、查询优化的实现途径及方法

1合理使用索引

索引是数据库中重要的数据结构,一个设计良好的索引可以减少I/O操作,从而显著提高查询效率。但也应注意其负面影响,因为每一索引的使用都以磁盘容量作为代价,并降低写操作的性能。因此要合理使用索引。一般而言,其使用应考虑以下原则:

(1)在经常进行连接但没有指定为外键的列上建立索引,而不经常连接的列则由优化器自动生成索引;

(2)在频繁进行排序或分组的列上建立索引;

(3)在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引.如“性别”列上只有“男”、“女”两种取值,若建立索引不但不会提高查询效率,反而会大大降低更新速度;[3]

(4)选择长度较短的列建立索引.因为在较短列上建立索引,缓存中能放置更多的索引页,可以减少I/O操作,提高查询速度;

(5)若一个关系的更新频率很高,则该关系上建立的索引数不宜太多。因为更新关系时,必须对关系上的索引做相应的修改;

(6)如果待排序的列有多个,可以在这些列上建立复合索引。

2避免对大型表行数据的顺序存取

在嵌套查询中,大型表的顺序存取对查询效率可能产生致命的影响。如一个嵌套3层的查询,如果每层查询都产生1000行数据。则整个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列建立索引,按索引路径完成连接运算,从而大大降低连接运算的执行代价。如:books表和book category表要进行连接,就要在“图书类编号”这个列上建立索引。还可以使用并集来避免顺序存取。

尽管在所有的检索列上都有索引,但某些形式的WHERE子句强迫优化器使用顺序存取。[4]如下列语句:

SELECT*FROM books WHERE (图书编号>1101 AND图书编号<1150)OR价格=30

虽然在“图书编号”和“价格”列上都建有索引,但优化器对该语句的处理还是使用顺序存取路径扫描整个表,因为这个语句要检索的数据行是分离的行的集合,因此应改成以下多条SELECT查询语句的并集形式,强迫优化器对books表使用索引路径处理查询。

SELECT*FROM books WHERE (图书编号>1101 AND图书编号<1150)

UNION

SELECT*FROM books WHERE价格=30

3尽量减少嵌套查询的层数[5]

查询嵌套的层数每增加一层,查询效率成几何级降低。因此要提高查询效率,就应尽量减少嵌套查询的层数。下面通过具体实例来说明。

例如:查询学生成绩信息表Cj (Student_ID,Ks_ID,Student name,Score)中同时满足两个分数段[Scorel 1,Scorel2]、[Score21,Score22]的学生记录,利用嵌套查询语句表示为:

SELECT Student_Id FROM Cj WHERE Cj.Scroe>=Score11 AND Cj.Score<=Scorel2 AND Student_Id IN(SELECT Student_Id FROM Cj WHERE Cj.Score>=Score21AND Cj.Score<=Score22);

在上面的查询中,若每层查询1000行语句,查询量就达到了100万行。如果需要对更多的分数段或对这些分数段的逻辑表达式进行这样的查询,查询效率就更低了。为了减少嵌套查询语句的层数,我们先看下面的命题。

命题有区间序列:,,…,且两两不相交,即=Φ(ij)

若映射为,则将区间与运算转化为代数和运算,即AND AND…AND转化为++…+

根据上面的命题,将分数段{[Score11,Score12],[Score21,Score22]}映射为数值{1,2},将区间与运算转化为代数和运算。

将上面的例子进行转换:将学生成绩表中增加一个辅助整型字段key,将key字段的值设置为:

UPDATE Cj SET key=1 WHERE Cj.Score>=Score11AND Cj.Score<=Score12

UPDATE Cj SET key=2 WHERE Cj.Score>=Score21AND Cj.Score<=Score22

则将原来的嵌套语句改为:

SELECT Student_Id SUM (DISTINCT key)FROM Cj WHERE key>0 GROUP BY Student_Id HAVING SUM(DISTINCT key)=3

可以看出,该语句变得简洁且执行效率要高。

通过该实例可知,利用区间运算转换为代数运算,将减少嵌套查询语句嵌套的层数,从而达到提高关系数据库查询效率的目的。

4避免困难的正规表达式

在SELECT查询语句中,MATCHES和LIKE关键字支持通配符匹配,技术上称为正规表达式。但这种匹配特别耗时。如:SELECT*FROM Student WHERE Sno LIKE‘2002%’,即使在Sno列上建立了索引,优化器还是会采用顺序扫描方式处理该SELECT语句。但若把SELECT语句改为:

SELECT*FROM Student WHERE Sno>‘2002000000’AND Sno<‘2003000000’

则优化器会利用索引来执行查询,显然会大大提高查询速度。

另外,还要避免非开始子串的查询。

5用排序来取代非顺序磁盘存取

非顺序磁盘存取是最慢的操作,表现在磁盘存取臂的来回移动。SQL隐藏了这一事实,使得在编写应用程序时很容易写出要求存取大量非顺序页的查询语句。这种情况下,使用数据库的排序操作来取代非顺序磁盘存取能改进查询效率。

参考文献

[1]萨师煊、王珊:《数据库系统概论》[M].北京:高等教育出版社,2000.

[2]魏威、马国峰:《基于索引的关系数据库查询优化》[J].洛阳大学学报,2007,22(2).

[3]汤庸、叶小平、汤娜:《数据库理论及应用基础》[M].北京:清华大学出版社,2004

[4]周峰:《SQL Server2005中文版关系数据库基础与实践教程》[M].北京:电子工业出版社,2006.

[5]谷震离:《关系数据库查询优化方法研究》[J].微计算机信息,2006,22(5-3).

[6]肖捷、肖正新、袁华强:《关系数据库查询优化策略的分析与应用:[J]计算机与现代化,2006,(11)

关系数据库的查询优化 篇8

随着现代数据库规模的不断扩大, 有些甚至要用太字节来计量, 对能够处理如此巨大数据的信息系统的要求也随之而来, 因而, 找到一种高效的信息提取方法是十分必要的。数据库应用系统的性能受多方面的制约, 如操作系统、数据库管理系统以及前期阶段开发工具等。从大多数数据库应用系统的实例来看, 在数据库应用系统中, 查询操作所占的比重是相当大的, 查询效率是数据库系统的重要指标。高效的查询能极大的提高系统的性能, 查询速度的快慢将直接影响到整个应用系统, 它是系统优劣的关键所在。在关系型数据库中, 数据的高度独立性, 为用户提供了方便、简单、非过程化的查询方法, 但同时也增加了系统的负担, 使查询效率降低, 因此, 关系数据库中查询优化就显得尤为重要。

2 查询优化

所谓的查询优化就是对于给定的查询选择代价最小的序列, 使查询过程既省时间, 又省空间。关系数据库中, 对于用户给出的查询语句, 系统的查询处理程序能自动实现查询优化。但对于一个较复杂的查询要求, 通常可以有几种不同的查询语句表达式, 虽然他们的结果是相同的, 但执行的过程可能有很大的差别。写出最优的查询语句, 从而在系统开销最小的情况下进行查询, 对于开发数据库管理系统具有重要意义。

查询优化既有逻辑方法的优化 (如关系代数表达式的优化) , 也有物理方法的优化 (如存储路径的优化) 。由于磁盘读写比CPU的处理速度上要慢得的多, 因此, 查询优化的关键就是减少对磁盘的访问。

3 查询优化的基本原则及策略:

3.1 合理地建立和使用索引

3.1.1 索引是数据库中重要的数据结构。

索引是建立在表上的一种数据结构, 它的根本目的就是为了提高查询效率。但未经调优的索引可能导致如下结果:

a.建立后却从来未使用, 但索引是要付出维护代价的。

b.为了返回一条单记录而扫描多个文件。

c.由于错误的索引, 导致多表的连接操作持续几个小时。

索引由存储器管理器来提供, 用来组织内存中的数据访问, 对于聚簇索引而言, 还需要组织数据在磁盘上的分布。索引和并发控制机制是紧密结合的。在查询优化过程中, 会被查询处理器频繁使用。下图是索引在的数据库系统体系结构中的位置。

3.1.2 索引的使用规则如下

a.在经常进行连接, 但是没有指定为外键的列上建立索引, 而不经常连接的字段则由优化器自动生成索引。

b.在频繁进行分组和排序的列上建立索引。若待排序的列有多个, 可以建立复合索引, 并且在where子句中尽可能的让字段顺序与索引顺序相一致, 应让使用最频繁的列作为索引的最左前缀, 只有其最左前缀作为条件时才能保证系统充分利用了该索引, 否则索引不被引用。

c.在条件表达式中经常用到的、不同值较多的列上建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同的值, 它基本上都要扫描至少一半的记录, 因此就没有必要建立索引了。如果建立索引不但不会提高查询效率, 反而会严重降低更新速度。

d.使用系统工具。如Informix数据库有一个tbcheck工具, 可以在可疑的索引上进行检查。如果使用一个索引的查询不明不白的慢下来, 可以试着用tbcheck工具检查索引的完整性, 必要时进行修复。另外, 当数据库更新大量数据后, 删除并重建索引可以提高查询速度。

3.1.3 索引的维护

a.如果索引对查询效率起反作用, 则必须删除。

b.有规律的运行目录统计更新包, 保证优化器能够得到选择合适索引所需要的信息。运行时, 要仔细考虑其中的选项。

c.系统通常会有工具来说明系统处理的查询信息, 也就是系统的查询计划, 要注意利用这些工具。

3.2 使用临时表加速查询

虽然临时表占用磁盘空间, 但需要反复访问同一张或几张表时, 可以把表经常用到的字段作为一个子集, 排序后放到临时表中, 由于其数量远少于原表, 反而较少了I/O操作从而提高了查询效率。例如:

如果这个查询要被执行数次, 可以把所有及格的学生找出来放在一个临时表文件中, 并按学生的名字进行排序:

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

临时表中的行比主表少, 而且物理顺序就是所要求的顺序, 减少了磁盘I/O操作, 所以查询效率会大大提高。

3.3 避免相关子查询

若一个列名同时在主查询和子查询where子句中的查询中出现, 那么很可能当主查询中的列值改变之后, 子查询就必须重新查询一次。查询嵌套层次越多, 效率就会越低, 因此应当尽量避免子查询。如果子查询不可避免, 那么要在子查询中过滤掉尽可能多的行。

以一个SELECT语句为例:

在这个语句中, 对于每一个外层查询的每一个num的值, 都要在内层查询中对score表进行全表扫描, 实际上是对表score进行了顺序查找, 降低了查询效率。此时, 可以用连接替代嵌套, 语句改为:

3.4 避免困难的正规表达式

MATCHES和LIKE关键字支持通配符匹配, 称为正规表达式。这种匹配特别耗费时间。例如:

即使在Sno字段上建立了索引, 在这种情况下也还是采用顺序扫描的方式。如果把语句改为

在执行查询时就会利用索引来查询, 速度会得到很大提高。

结束语

在数据库的开发和维护过程中, 查询的优化设计可以提高系统的性能, 对于数据量大的数据库系统尤为重要。提到的查询优化方法策略代一定程度上提高了查询效率。当然要根据实际情况合理正确的使用这些方法, 在提高查询效率的同时还要注意程序的正确性和数据的安全性, 只有这样才能真正的起到查询优化的作用。

参考文献

[1]萨师煊;王珊.数据库系统概论 (第四版) .高等教育出版社, 2007.

[2]Dennis Shasha Philipe Bonnet.数据库性能调优--原理与技术.电子工业出版社, 2004.

上一篇:流星余迹通信信道下一篇:工科物理