4
摘摘对对对对对对 Oracle 对 对 对 对 ,,,。 对对对对 Oracle 对 对 对 ;;。 1 对对对 ,,。 对对对对对对对对 对对对对 对对对对对对 。,。,, SQL 对对对对对对对对对对对对对对对 对 ,,,。 对对 Oracle 对 对 Oracle 对对对对对对对对对对 2 Oracle 摘摘摘摘摘摘摘摘 Oracle对 对 对 对 对 对 对 一:(、、)、Oracle 对对对对Oracle 对对对对 Oracle SQL 对 Oracle 对对对对对 对 50 M 50对 对对对对对 。:, SQL 对 对 SQL 对 对 对 对对对 ,,。 SQL 对 SELECTFROMSELECTFROMSELECTFROM BIGWHERE ROWNUMTOPOS ORDER BYROWNUM DESCWHERE ROWNUMTOPOSFROMPOS1对对对 SQL 对对对对对对对对对 56 s 对对对 ,,。 Oracle 对 对 、、SQL 对 对 SQL 对 21 摘摘摘摘 对对对对 Oracle 对对对对Oracle 对对对对对 SGA 对 对 Oracle 对对对对对对对 Oracle 对对对对对对对 对 SGA 对对对对 Oracle 对 对 对 。, SGA 对对对对对对211 SGA 摘摘摘摘摘 SGA 对 对对对对对对对对对对对对对对对对对对对对对 ,。 Oracle 对SGA 对 对 1对 SGA 对对对 对对对对对对对对 SGA 对 对 对 对 对 对对对对对对对对对对对对对对对对对对对对对对对对 对对对对对对对对对对对对对对对 传一 ,,。

Oracle数据库中大型表查询优化研究

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Oracle数据库中大型表查询优化研究

摘 要:对海量数据进行访问查询时,常常遇到系统响应时间过长,占用系统资源过多的问题。本文结合实例着重对 Oracle 数据库中的查询优化进行了研究,测试结果表明采用的方法是很有效的,大大缩短了测试用例表的响应时间,最后对海量数据的优化方法提出了实用性的建议。

关键词:海量数据;Oracle 数据库;查询优化;数据查询。 1 引 言 在直升机飞行地面数据处理平台中,需要查询历史飞行数据来进行飞行状态的模拟及

其飞行事故的分析,从而对当前飞机状态进行评判。其数据量非常巨大。如何对其进行快速访问,提高系统响应时间就显得十分重要。在实际应用中,往往采用各种优化措施,使得SQL 查询经过数据库优化器的处理,得到最佳的执行计划,即数据访问路径,来达到提高响应速度的目的。由于项目采用的是 Oracle 数据库,以下考虑对 Oracle 数据库进行的优化情况。

2 Oracle查询顺序及其调整 Oracle 优化的一般顺序如下:环境调整(服务器、网络、磁盘)、Oracle 实例调整 、

Oracle 对象调整、Oracle SQL 调整。我们的测试采用的 Oracle 数据表容量为 50 M,记录条数为 50 万条。测试方法为:根据用户的查询要求计算得到用户需要浏览的数据记录的起止位置,然后在 SQL 语句中加入此位置,执行 SQL 语句,查询该数据表,得到用户想要浏览的记录集合。使 用的 SQL 语句如下:

  SELECT*FROM(SELECT*FROM(SELECT*FROM BIG) WHERE ROWNUM<TOPOS ORDER

BYROWNUM DESC)WHERE ROWNUM<TOPOSFROMPOS+1;

使用该 SQL 查询得到结果集需要 5~6 s,这个响应速度难以满足用户浏览要求,因此必须对其优化以提高响应速度。我们是在假定环境调整已经完成的条件下通过对 Oracle实例、对象、SQL 查询语句的调整得出结论的,其中重点是对 SQL 语句的调整。

2.1 实例调整 首先进行 Oracle 实例调整。Oracle 实例涉及到 SGA 内存区和一组 Oracle 后台处理

进程。对 Oracle 实例的调整就是对 SGA 内存区和 Oracle 后台处理进程的调整。在对该问题的解决中,主要是针对 SGA 内存区的调整。

Page 2: Oracle数据库中大型表查询优化研究

2.1.1 SGA内存区结构 SGA 就是系统全局区,是指内存中允许多个进程相互通信的区域。在 Oracle 中,

SGA 对所有进程来说都是全局的可用的。图 1 为 SGA 结构图。 缓冲区高速缓存是 SGA 中为所有用户和系统进程保存数据的区域,任何数据在传递

给一个调用的应域是共享的,所以多个进程可以从这片高速缓存读取同样的数据块,而不必每次都从物理磁盘中读取。

   共享池是 SGA 中的另一个区域,其中保存着关于待执行的 SQL 语句的信息。他由两

部分组成:数据字典高速缓存,存放从数据字典中读取的信息以用于处理 SQL请求;库高速缓存,存放需要执行的 SQL 语句信息,包括每个 SQL 语句的语法分析树和执行计划。如果多个用户要执行同样的 SQL 语句,那么语法分析树和执行计划就可以重复利用,省去了语法分析步骤的昂贵花费。

2.1.2 调整SGA结构 一般来讲,在系统硬件支持的情况下,系统全局区越大越有利于数据库高效的运行。

大的缓冲区高速缓存可以缓存更多的数据块,这样可以提高缓存命中率,节省物理磁盘读取的高昂代价;大的共享池意味着大的库高速缓存。库缓存的内存结构如图 2 所示。

  

Page 3: Oracle数据库中大型表查询优化研究

库缓存越大,可以保存的 SQL 语法分析信息越多;此外,数据库中的一些对象,如表、索引、过程、触发器、软件包等也在首次执行后进驻库高速缓存。大的库缓存可以保证对这些对象的高命中率,从而节省解析和载入代价。

作为一个通用的优化原则,我们在解决该问题时,适当增大了 SGA 的容量,从而保证Oracle 实例可以比较高效的运行。设置缓冲区高速缓存的容量为 32 M,设置共享池的大小为 56 M。运行 rpt_lib.sql 程序检查库高速缓存不足率(还没有运行该脚本),表明库缓存足够。

2.2 对象调整 这一步骤我们要对每一个 Oracle 对象进行调整从 而优化性能,包括对所有的存储参

数进行正确的设置,尤其是对影响输入输出的参数进行设置 。Pctfree,pctused,freelist参数的设置都会对 SQL 性能产生重要影响。

在解决该问题时,我们没有对对象的存储参数进行调整。对象的存储参数的调整要建立在具体对象的基础之上,我们使用的测试大表除了在容量上模拟可能的实际对象之外,和实际对象并没有多少可比之处。举例来说,pctfree参数是指在实际的存储块中,留出来为块中的记录扩展所用的空闲空间占该存储块容量的百分比,这个参数和实际表记录的长度及可扩展性有关,要在设计出实际表之后进行调整。因此我们对对象的存储参数使用了数据库的缺省设置。数据库的对象还包括索引、过程、包等,对对象的调整要包括对他们的调整,这里一并略去。

2.3 SQL语句调整 SQL 语言是一种灵活的语言,相同的功能可以使用不同的语句来实现,但是语句的执

行效率是很不相同,一般考虑如下规则: (1)添加索引 在对大表进行扫描时,首先要避免不必要的全表扫描。最通常的做法就是给大表添加

索引。所谓全表扫描,就是在访问表时,从磁盘上存储该表的起始位置开始逐记录读数据,直到该表的结束位置。给大表添加索引后,我们可以通过访问索引的方式获得记录的物理位置,从而达到访问表的目的。设想一下,对于一个拥有大量字段的表,如果只需要返回其中少量字段,那么在这些字段上建立索引,通过索引访问获得记录,将大大降低物理磁盘读写次数,从而降低了整个查询响应时间(事实上,这种情况下根本没有必要访问数据表,只是访问索引就足够了)。在我们的测试用表中,只有 4 个字段,显然无法发挥索引的这一优势。我们的测试用表的特点是记录条数多,达到 50 万条,但每次返回的记录数只有几十条,在这种情况下,使用索引同样可以起到好的效果。首先在检索条件上建立索引,在表访问时,我们通过索引来获取目的记录集的物理地址,因为返回的记录数不多,所以这种方式造成的物理读写很少,应该可以获得较满意的访问时间。在测试中,我们对测试用表的条件字段添加索引,但事实上并没有提高查询的响应时间,这是因为在 SQL 语句的执行计划中,在添加索引之前和之后,Oracle生成的执行计划中,表访问方式都是全表扫描,根本没有使用我们添加的索引。那么此时我们可以采用添加提示的方法。

Page 4: Oracle数据库中大型表查询优化研究

(2)添加提示 在 Oracle 中,我们可以在 SQL 语句中加入提示,来影响 Oracle 对优化模式的选择,

从而生成最优的执行计划。于是我们在 SQL 语句中加入提示,强制优化器在生成执行计划时将表的访问方式从全表扫描改为索引范围扫描。结果该查询花费了比全表扫描多得多的响应时间。仔细查看这个 SQL 语句的执行计划,我们发现Oracle 对这个索引进行了全索引扫描,这样造成的物理读写数量比起全表扫描不仅没有减少,反而大幅上升。寻找原因,问题出在我们索引的字段上。我们索引的 AGE字段为了测试方便,每条记录的值都不相同,这样的字段其实并不具备建立索引的条件。在该测试中,我们首先要将索引载入内存,由于索引各不相同,Oracle 采取了全索引扫描的方式访问索引,我们要读取的是 30 万条记录(AGE>200 k),通过索引,我们获得的将是 30 万个记录的 ROWID,如果这些记录在磁盘上的物理位置没有按索引顺序排序,那么我们就不得不通过 30 万个 ROWID 来访问这些记录,这样造成的物理读写是相当惊人的,这就是为什么我们使用了索引,却反而查询速度更慢的原因所在。事实上Oracle 的优化器选择全表访问是已经对不同的执行计划作过比较的了。同时,这里同样违背了一个 Oracle 优化的准则,对于没有按索引顺序排序的表,如果检索记录数小于总记录数的 7%,用索引比全表扫描快。

(3)更改优化器模式 优化器是 Oracle 数据库中接受来自产生器处理过的 SQL 语句的程序。他将对 SQL 进

行优化,生成内部执行计划,这个计划是 Oracle 存取物理磁盘数据的路径。根据优化器模式的不同,生成的内部执行计划也不同,而对于相同的 SQL,永远只有一个最优的执行计划,因此选择合适的优化器模式,是很重要的。Oracle 有 2 种优化器模式:基于规则的优化模式和基于成本的优化模式。在这次测试中,我们使用的优化器模式参数为 CHOOSE,这样 Oracle将根据 SQL 语句相关表索引的有无,统计资料的有无以及 SQL 语句中的提示,自动判断使用哪种优化模式。

(4)将调整持久化 Oracle 的执行计划是根据各种情况,比如表的统计资料变化的,但有时这种变化是

我们不希望的。为了将我们已经调整好的 SQL 执行计划固定,我们可以 用 Oracle 的工具将执行计划持久化存储。

2.4 调整结果 通过对这个测试用例的调整,我们最终将此大表的响应时间从 5 s 缩短到不足 2 s。经

过调整后的缓冲区高速缓存达到 113 M,大约占物理内存的 50%,调整后的 SQL 语句为:

  SELECT name,age,memo FROM

(SELECTname,age,memo,rownum

ASmynum FROM test2)

Page 5: Oracle数据库中大型表查询优化研究

WHEREmynum>400000 and mynum<=400010;

我们测试所用的机器配置为 CELETRON500 M,内存 256 M,硬盘为 IDE8.4 G。可以说是运行 Oracle8I 的最低配置。启动Oracle 8I 数据库后,内存使用达到 300 M 以上,也就是说已经在用虚拟内存;测试开始后,CPU 保持或接近满载,这些都会影响Oracle 的性能表现,也会影响测试结果。

3 结 语 以下几点可以作为通用的 Oracle SQL 调整原则: (1)消除不必要的全表扫描,可以通过添加索引达到。 (2)缓存小型表的全表扫描,可以通过将小型表置入缓冲区高速缓存的 KEEP池中

实现。 (3)如果表有多个索引,要保证Oracle正在使用对此 SQL 最优化的索引,可以通

过添加提示实现。