《SQL语言艺术(PDF格式)》第5章


如果计划逛好几家商店,你会首先决定在每家店买哪些东西。从这一刻起,就要计划按何种顺 
序购物才能少走冤枉路。每逛一家店,计划东西购买完毕,才逛下一家。这是常识,但其中蕴 
含的道理许多数据库应用却不懂得。 
要从一个表中提取多段信息时,采用多次数据库访问的做法非常糟糕,即使多段信息看似“无关” 
(但事实上往往并非如此)。例如,如果需要多个字段的数据,千万不要逐个字段地提取,而应 
…………………………………………………………Page 12……………………………………………………………
一次操作全部完成。 
很不幸,面向对象(OO)的最佳实践提倡为每个属性定义一个get方法。不要把 OO 方法与关 
系数据库处理混为一谈。混淆关系和面向对象的概念,以及将表等同于类、字段等同于属性, 
都是致命的错误。 
总结:在合理范围内,利用每次数据库访问完成尽量多的工作。 
DBMS 
接近DDBBMMSS核心 
Closeness to the DBMS Kernel 
CClloosseenneessss ttoo tthhee DDBBMMSS KKeerrnneell 
代码的执行越接近DBMS 核心,则执行速度越快。数据库真正强大之处就在于此,例如,有些 
数据库管理产品支持扩展,你可以用C等较底层的语言为它编写新功能。用含有指针操作的底 
层语言有个缺点,即一旦指针处理出错会影响内存。仅影响到一个用户已很糟糕,何况数据库 
服务器(就像“服务器”名字所指的一样)出了问题会影响众多“用户”——服务器内存出了问题, 
所有使用这些数据的无辜的应用程序都会受影响。因此,DBMS 核心采取了负责任的做法,在 
沙箱(sandbox)环境中执行程序代码,这样,即使出了问题也不会影响到数据。例如,Oracle 在 
外部函数(external function)和它自身之间实现了一套复杂的通信机制,此机制在某些方面很 
像控制数据库连结的方法,以管理两个(或多个)服务器上的数据库实例之间的通信。到底采 
用PL/SQL 存储过程还是外部 C 函数,应综合比较后决定。如果精心编写外部 C 函数获得的 
好处超过了建立外部环境和上下文切换(context…switching)的成本,就应采用外部函数。但需 
要处理一个大数据量的表的每一行时,不要使用外部函数。这需要平衡考虑,解决问题时应完 
全了解备选策略的后果。 
如要使用函数,始终应首选DBMS自带的函数。这不仅仅是为了避免无谓的重复劳动,还因为 
自带函数在执行时比任何第三方开发的代码更接近数据库核心,相应地其效率也会高出许多。 
下面这个简单例子是用 Oracle SQL编写的,显示了 使用Oracle 函数所获得的效率。假设手工 
输入的文本数据可能包含多个相邻的“空格”,我们需要一个函数将多个空格 
替换为一个空格。如果不采用OracleDatabase 10g 开始提供的正规表达式(regularexpression), 
函数代码将会是这样: 
createor replace function squeeze1(p_string invarchar2) 
returnvarchar2 
is 
v_stringvarchar2(512):=""; 
c_char char(1); 
n_len number :=length(p_string); 
i binary_integer :=1; 
j binary_integer; 
begin 
while (i0) 
loop 
v_string:=substr(v_string; 1;i) 
||ltrim(substr(v_string; i+1)); 
i:=instr(v_string; " "); 
end loop; 
returnv_string; 
end; 
/ 
…………………………………………………………Page 14……………………………………………………………
还有第三种方法: 
createor replace function squeeze3(p_string invarchar2) 
returnvarchar2 
is 
v_stringvarchar2(512):=p_string; 
len1 number; 
len2 number; 
begin 
len1 :=length(p_string); 
v_string:=replace(p_string; " ";""); 
len2 := length(v_string); 
while (len2 select squeeze1("azeryt hgfrdt r") 
2 from dual 
3 / 
azeryt hgfrdtr 
Elapsed: 00:00:00。00 
SQL》select squeeze2("azeryt hgfrdt r") 
2 from dual 
3 / 
azeryt hgfrdtr 
Elapsed: 00:00:00。01 
SQL》select squeeze3("azeryt hgfrdt r") 
2 from dual 
3 / 
azeryt hgfrdtr 
Elapsed: 00:00:00。00 
…………………………………………………………Page 15……………………………………………………………
那么,如果每天要调用该空格替换操作几千次呢?我们构造一个接近现实负载的环境,下面的 
代码将建立一个用于测试的表并填入随机数据,已检测上面三个函数是否有性能差异: 
createtable squeezable(random_text varchar2(50)) 
/ 
declare 
i binary_integer; 
j binary_integer; 
k binary_integer; 
v_string varchar2(50); 
begin 
foriin1。。10000 
loop 
j:=dbms_random。value(1; 100); 
v_string:=dbms_random。string("U"; 50); 
while (j
小说推荐
返回首页返回目录