虎虎漫画小说

繁体版 简体版
虎虎漫画小说 > > SQL语言艺术最新章节 > 第 3 章

第 3 章 免费阅读

begin

len1 := length(p_string);

v_string := replace(p_string, ' ', ' ');

len2 := length(v_string);

while (len2 < len1)

loop

len1 := len2;

v_string := replace(v_string, ' ', ' ');

len2 := length(v_string);

end loop;

return v_string;

end;

/

SQL> select squeeze1('azeryt hgfrdt r')

2 from dual

3 /

azeryt hgfrdt r

Elapsed: 00:00:00.00

SQL> select squeeze2('azeryt hgfrdt r')

2 from dual

3 /

azeryt hgfrdt r

Elapsed: 00:00:00.01

SQL> select squeeze3('azeryt hgfrdt r')

2 from dual

3 /

azeryt hgfrdt r

Elapsed: 00:00:00.00

那么,如果每天要调用该空格替换cāo作几千次呢?我们构造一个接近现实负载的环境,下面的

代码将建立一个用于测试的表并填入随机数据,已检测上面三个函数是否有xìng能差异:

create table squeezable(random_text varchar2(50))

/

declare

i binary_integer;

j binary_integer;

k binary_integer;

v_string varchar2(50);

begin

for i in 1 .. 10000

loop

j := dbms_random.value(1, 100);

v_string := dbms_random.string('U', 50);

while (j < length(v_string))

loop

k := dbms_random.value(1, 3);

v_string := substr(substr(v_string, 1, j) || rpad(' ', k)

|| substr(v_string, j + 1), 1, 50);

j := dbms_random.value(1, 100);

end loop;

insert into squeezable

values(v_string);

end loop;

上面的脚本在测试表中建立了10 000条记录(决定SQL 语句要执行多少次时,这是数字比较适

中)。要执行该测试,运行下列语句:

我运行这个测试时,关闭了所有头信息(headers)和屏幕的显示。禁止输出可确保结果反映的

是替换空格算法所花费的时间,而不是显示结果所花费的时间。这些语句会执行多次,以确保

不受缓存(caching)的影响。

表2-2显示了在测试机上的运行结果。

表2-2:处理10 000条记录中空格所花的时间

commit;

end;

/

select squeeze_func(random_text)

from squeezable;

函数机制时间

squeeze1

用PL/SQL 循环处理字符0.86 秒

尽管都在1秒内完成了10 000次调用,但squeeze2的速度是squeeze1的1.8 倍,而squeeze3

则是它的2.2 倍。为什么呢?原因很简单,因为SQL 函数比PL/SQL“离核心更近”。当函数只偶

尔执行一次时,xìng能差异微乎其微,但在批处理程序或高负载的OLTP 服务器中xìng能差异就非

常明显。

总结:代码喜欢SQL内核——离核心越近,它就运行得越快。

只做必须做的

Doing

Only

What

Is

Required

开发者使用count(*)往往只是为了测试“是否存在”。这通常是由以下的需求说明引起的:

如果存在满足某条件的记录

那么处理这些记录

用代码直接实现就是:

当然,在90% 的情况下,count(*) 是完全不必要的,正如上面的例子。要对多项记录进行cāo

作,直接做即可,不必用count(*)。即使一个cāo作对任何记录都没有影响,也没有关系,不用

count(*)没有什么不好。而且,即使要对未知的记录进行复杂处理,也能通过第一个cāo作就确定

并返回受影响的记录——要么通过特殊的API (例如PHP 中的mysql_affected_rows()),要么

采用系统变量(Transact-SQL 中为@@ROWCOUNT,PL/SQL 中为SQL%ROWCOUNT),若使

用内嵌式SQL,则使用SQL通讯区(SQL Communication Area,SQLCA)的特殊字段。有时,

squeeze2 Instr() + ltrim()

0.48 秒

squeeze3 循环调用replace() 0.39 秒

select count(*)

into counter

from table_ncom

where <certain_condition>

if (counter > 0) then

可以通过函数访问数据库然后直接返回要处理的记录数,例如JDBC 的executeUpdate()方法。

总之,统计记录数极可能意味着重复全部搜索,因为它对相同数据处理了两次。

此外,如果是为了更新或chā入记录(常使用count检查键是否已经存在),一些数据库系统会提

供专用的语句(例如Oracle 9i 提供MERGE 语句),其执行效率要比使用count高得多。

总结:没必要编程实现那些数据库隐含实现的功能。

SQL

语句反映业务逻辑

SQL Statcomnts Mirror Business Logic

大多数数据库系统都提供监控功能,我们可以借此查看当前正在执行的语句及其执行的次数。

同时,必须对有多少个“业务单元(business units)”正在执行心里有数——例如待处理的订单、

需处理的请求、需结账的客户,或者业务管理者了解的任何事情。我们应检查上述语句活动和

业务活动的数量关系是否合理(并不要求绝对精确)。换言之,如果客户数量一定,那么数据库

初始化活动的数量是否与之相同?如果查询custcomrs 表的次数比同一时间正在处理的客户量

多20 倍,那一定是某个地方出了问题,或许该查询对表中相同记录做了重复(而且多余)的

访问,而不是一次就从表中找出了所需信息。

总结:检查数据库活动,看它是否与当时正进行的业务活动保持合理的一致xìng。

把逻辑放到查询中

Program Logic into Queries

在数据库应用程序中实现过程逻辑(procedural logic)的方法有几种。SQL语句内部可实现某

种程度上的过程逻辑(尽管SQL语句应该说明做什么,而不是怎么做)。即便内嵌式SQL的宿主

语言(host language)非常完善,依然推荐尽量将上述过程逻辑放在SQL语句当中,而不是宿

主语言当中,因为前一种做法效率更高。过程xìng语言(Procedural language)的特点在于拥有

执行迭代(循环)和条件(if ... then ... else 结构)逻辑的能力。SQL不需要循环能力,因为它

本质上是在cāo作集合,SQL只需要执行条件逻辑的能力。

条件逻辑包含两部分——IF和ELSE。要实现IF的效果相当容易——where子句可以胜任,困难

的是实现ELSE 逻辑。例如,要取出一些记录,然

松语文学免费小说阅读_www.16sy.com

『加入书签,方便阅读』