首页 > 数据库 > SQL Server > 正文
oraclepl/sql实战学习-避免误用
2015-05-26       个评论    来源:wenhuahetao的专栏  
收藏    我要投稿

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

1.逐行处理

\\\

\

程序声明了一个游标c1,然后用游标for循环隐式地打开了这个游标,对从游标c1取出的每一行,程序查询customers表,并把first_name和last_name的值填充到变量,随后插入一行数据到tZ喎"/kf/ware/vc/" target="_blank" class="keylink">vcF9zYWxlc19jdXN0b21lcnOx7aGjPGJyPgo8L3A+CjxwPs7KzOIxo7o8L3A+CjxwPjxzdHJvbmc+tPrC68fltaUxLTE8L3N0cm9uZz61xLHgs8y3vbeoutzT0M7KzOKho7y0yrnU2tGtu7fW0LX308O1xFNRTNPvvuTKx7jftsjTxbuvtcSjrLPM0PK1xNa00NC7ucrHu+HP+7rEtPPBv8qxvOSho7zZyeiy6dGvY3VzdG9tZXJzse21xFNRTNPvvuTP+7rEMC4xw+ujrElOU0VSVNPvvuTSss/7usQwLjHD66OsxMfDtNTa0a27t9bQw7+0zta00NC+zdKqMC4yw+uho8jnufvTzrHqYzHIobP2wcsxMDAgMDAw0NCjrMTHw7TX3MqxvOS+zcrHMTAwIDAwMLPL0tQwLjLD66OsvLQyMCAwMDDD66Os0rK+zcrHtPPUvDUuNdChyrGho7rcxNHIpdPFu6/V4rj2s8zQ8rXEveG5uaGju/nT2s/UtvjS17z7tcTA7dPJo6xUb21LeXRlsNHV4tbWtKbA7be9yr22qNLlzqrC/dau09bC/bXEtKbA7aOoc2xvdy1ieS1zbG93CiBwcm9jZXNzaW5no6mhozxicj4KPC9wPgo8cD7OysziMqO6PC9wPgo8cD48c3Ryb25nPrT6wuvH5bWlMS0xPC9zdHJvbmc+tcS0+sLru7nT0NK7uPa5zNPQtcTOyszioaO001BML1NRTLXE0a27t9bQtffTw7XEU1FM0+++5Lvht7S4tNTaUEwvU1FM0v3H5rrNU1FM0v3H5tauvOTH0Lu71rTQ0KOs1eLW1sG9uPa7t76z1q685LXEx9C7u7PG1/fJz8/CzsTH0Lu7oaPJz8/CzsTH0Lu71Pa808HLs8zQ8tTL0NC1xMqxvOSjrLKi1Pa807K7sdjSqrXEQ1BVv6rP+qGjxOPTprWxzai5/c/7s/278rz1ydnV4tbWwb249ru3vrPWrrzktcTH0Lu7wLS89cnZyc/Pws7Ex9C7u7XEtM7K/aGj0ruw49OmtbG9+9a51vDQ0LSmwO2jrLj8usO1xLHgs8zKtbz5ysew0bT6wuvH5bWlMS0xtcSzzNDy16q7u7PJ0ru49lNRTNPvvuSho7T6wuvH5bWlMS0y1tjQtMHLtPrC66OszerIq7Hcw+LBy1BML1NRTDwvcD4KPHA+PGltZyBzcmM9"" alt="\">\

代码清单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个不同的值。

\

\

\

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

点击复制链接 与好友分享!回本站首页
相关TAG标签 实战
上一篇:12-SQLite之事务
下一篇:sql学习笔记(14)------------数据表
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站