oracle pl/sql 实战学习 -避免误用

这几天看了下 oracle pl/sql 实战 这本书,出于对sql语句性能的研究,先研究下游标对代码的影响。

1.逐行处理

程序声明了一个游标c1,然后用游标for循环隐式地打开了这个游标,对从游标c1取出的每一行,程序查询customers表,并把first_name和last_name的值填充到变量,随后插入一行数据到top_sales_customers表。

问题1:

代码清单1-1的编程方法很有问题。即使在循环中调用的SQL语句是高度优化的,程序的执行还是会消耗大量时间。假设查询customers表的SQL语句消耗0.1秒,INSERT语句也消耗0.1秒,那么在循环中每次执行就要0.2秒。如果游标c1取出了100 000行,那么总时间就是100 000乘以0.2秒,即20 000秒,也就是大约5.5小时。很难去优化这个程序的结构。基于显而易见的理由,TomKyte把这种处理方式定义为慢之又慢的处理(slow-by-slow
processing)。

问题2:

代码清单1-1的代码还有一个固有的问题。从PL/SQL的循环中调用的SQL语句会反复在PL/SQL引擎和SQL引擎之间切换执行,这种两个环境之间的切换称作上下文切换。上下文切换增加了程序运行的时间,并增加不必要的CPU开销。你应当通过消除或减少这种两个环境之间的切换来减少上下文切换的次数。一般应当禁止逐行处理,更好的编程实践是把代码清单1-1的程序转换成一个SQL语句。代码清单1-2重写了代码,完全避免了PL/SQL

代码清单1-2除了解决逐行处理的缺陷以外,还有更多的优势。重写后的SQL语句可以使用并行执行来调优,使用多个并行执行进程可以大幅地减少执行时间。并且,代码变得简明且可读性强。

2.嵌套的逐行处理

代码清单1-3中,c1、c2和c3是嵌套游标。游标c1是顶级游标,从表t1取得数据,c2是开放游标,传递从游标c1取得的值,c3也是开放游标,传递游标c2取得的值。有一个UPDATE语句对游标c3返回的每一行执行一次。尽管UPDATE语句已经优化为执行一次只要0.01秒,但程序的性能还是会由于深度嵌套游标而难以忍受的。假设游标c1、c2和c3分别返回20、50和100行,那么上述代码需要循环100 000行,程序的总执行时间超过了1000秒。对这类程序的调优通常需要完全重写它。

代码清单1-3中代码的另一个问题在于先执行一个UPDATE语句。如果UPDATE 语句产生了

no_data_found异常④,那么再执行一个INSERT语句。这种类型的问题可以利用MERGE语句从PL/SQL

转到SQL引擎处理。

从概念上讲,代码清单1-3中的三重循环表示表t1、t2和t3之间的等值连接。代码清单1-4展示

了根据上述逻辑改写的使用表别名t的SQL语句。UPDATE和INSERT逻辑的结合用MERGE语句代替,

MERGE语法提供了更新存在的行和插入不存在的行的功能。

不要在PL/SQL语言中编写深度嵌套游标的代码。审查这类代码的逻辑,看是否能用SQL语句来代替。

3.查找式查询

查找式查询(lookup query)一般用于填充某些变量或执行数据的合法验证。但在循环中执行查找式查询会导致性能问题。在代码清单1-5中,高亮显示的部分就是使用查找式查询来得到country_name值。程序对游标c1中的每一行都要执行一个查询来取得country_name的值。当从游标c1中取得的行数增加时,执行查找式查询的次数也增加了,这导致代码的效率低下。

代码清单1-5的代码是过分简化的,对country_name的查找式查询实际上可以重写为主游标c1本身中的一个连接。第一步,应将查找式查询修改为连接,可是在实际的应用程序中,并不一定可以实现这种改写。如果无法利用改写代码来减少查找式查询的执行次数,那么还有另一个选择。你可以定义一个关联数组来缓存查找式查询的结果,以便在随后的执行中重用这个数组,这样也能有效地减少查找式查询的执行。代码清单1-6演示了数组缓存技术。不必再在游标c1返回的每一行中执行查询来得到country_name,而是用一个名为l_country_names的关联数组来存储本例中的country_id
和country_name键—值对。关联数组和索引类似,任意给定的值都可以通过一个键值来访问。在执行查找式查询前,通过EXISTS操作对一个数组中是否存在一个匹配country_id键值的元素做一个存在性验证,如果数组中存在这么一个元素,那么country_name就从数组中获取而不需

要执行查找式查询。如果没有这样的元素,那么就执行查找式查询,并且把查到的结果作为一个新元素存入数组。你还需要理解,这种技术非常适用于不同的键值很少的语句,在本例中,当country_id列的唯一值个数越少时,查找式查询的执行次数可能也越少。如使用示例模式,执行查找式查询的次数最多是23,因为country_id列只有23个不同的值。

注意 关联数组所需内存是在数据库服务器中专用服务器进程的PGA(Program Global Area,程序全局区)中分配的,如果数千个连接都要把程序的中间结果缓存到数组中,那么内存的占用将会大幅增加。你应当掌握每个进程的内存使用增加情况,并设计数据库服务器以适应内存的增长。

时间: 2024-11-10 06:57:07

oracle pl/sql 实战学习 -避免误用的相关文章

Oracle PL/SQL实战代码下载

最近在学习PL/SQL编程,算是一个进阶吧,书没带光盘,所以按照书中的地址去下载样例,无法下载,到图灵官网找到了源代码下载地址,无法下载的留邮箱,我发给大家 下载地址: http://www.ituring.com.cn/book/850 内容截图:

Oracle PL\SQL 基础学习三

一. PL/SQL 与 SQL的交互 1. 使用select语句.into是必须的, 查询只能返回一条或0条数据 declare       v_fname employees.first_name%TYPE;  --更正规的写法       --v_fname varchar2(25);    begin       select first_name into v_fname       from employees where employee_id=200;       DBMS_OUT

[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天才在于积累!) ——通过知识共享树立个人品牌.   继上七篇:            [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)            [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之

ORACLE PL/SQL异常处理(Exception)学习笔记

1.PL/SQL错误类型 错误类型 报告者 处理方法 编译时错误 PL/SQL编译器 交互式地处理:编译器报告错误,你必须更正这些错误 运行时错误 PL/SQL运行时引擎 程序化地处理:异常由异常处理子程序引发并进行捕获 2.异常的声明 有两种异常:用户自定义异常和预定义异常 用户自定义异常就是由程序员自己定义的一个错误.该错误还不是非常重要,所以并没有将整个错误包含在Oracle的错误中.例如,它可能是一个与数据有关的错误.而预定义异常则对应于一般的SQL和PL/SQL错误. 用户自定义异常是

学习《Oracle PL/SQL 实例讲解 原书第5版》----创建账户

通过readme.pdf创建student账户. 以下用sys账户登录时都是sysdba. 一.PL/SQL 登录oracle. SYS/123  AS SYSDBA 账户名:sys:密码:123:作为sysdba角色登录. 二.查询DEFAULT TABLESPACE和TEMPORIRY TABLESPACE. SELECT tablespace_name FROM dba_tablespaces ORDER BY tablespace_name; 注:tablespaces are area

ORACLE PL/SQL编程详解

ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设计语言,该语言专门用于在各种环境下对ORACLE数据库进行访问.由于该语言集成于数据库服务器中,所以PL/SQL代码可以对数据进行快速高效的处理.除此之外,可以在ORACLE数据库的某些客户端工具中,使用PL/SQL语言也是该语言的一个特点.本章的主要内容是讨论引入PL/SQL语言的必要性和该语言的

【强烈强烈推荐】《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航

原文:[强烈强烈推荐]<ORACLE PL/SQL编程详解>全原创(共八篇)--系列文章导航 <ORACLE PL/SQL编程详解> 系列文章目录导航 ——通过知识共享树立个人品牌. 本是成书的,但后来做其他事了,就无偿的贡献出来,被读者夸其目前为止最“实在.经典”的写ORACLE PL/SQL编程的文章-! 觉得对你有帮助,请留言与猛点推荐,谢谢. [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) 本篇主要内容如下:第一章 PL/S

ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)

原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!)   继上篇:ORACLE PL/SQL编程之八:把触发器说透 得到了大家的强力支持,感谢.接下来再下猛药,介绍下一篇,大家一定要支持与推荐呀~!我也才有动力写后面的.   本篇主要内容如下: 6.1 引言 6.2 创建函数 6.3 存储过程 6.3.1 创建过程 6.3.2 调用存储过程 6.3.3 AUTHID 6.3.4 

[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)

原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日之功) 继上四篇:ORACLE PL/SQL编程之八:把触发器说透                ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)                [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) [推荐]