本文來源于網(wǎng)頁設計愛好者web開發(fā)社區(qū)http://www.html.org.cn收集整理,歡迎訪問。 摘 要 客戶機/服務器的應用邏輯設計是否合理,直接影響到客戶機/服務器方式應用系統(tǒng)的處理性能。本文以oracle 7服務器為平臺提出一些方法,以確定如何劃分應用邏輯,使客戶機/服務器應用系統(tǒng)有較高的處理效率。
關鍵詞 pl/sql 觸發(fā)子 客戶機/服務器
一、問題的提出
80年代末到90年代初,許多應用系統(tǒng)從主機終端方式、文件共享方式向客戶機/服務器方式過渡??蛻魴C/服務器系統(tǒng)比文件服務器系統(tǒng)能提供更高的性能,因為客戶機和服務器將應用的處理要求分開,同時又共同實現(xiàn)其處理要求(即"分布式應用處理")。服務器為多個客戶機管理數(shù)據(jù)庫,而客戶機發(fā)送請求和分析從服務器接收的數(shù)據(jù)。在一個客戶機/服務器應用中,數(shù)據(jù)庫服務器是智能化的,它只封鎖和返回一個客戶機請求的那些行,保證了并發(fā)性,使網(wǎng)絡上的信息傳輸減到最少,因而可以改善系統(tǒng)的性能。
在客戶機/服務器系統(tǒng)中,應用的處理是分布在網(wǎng)絡上的,所以在設計客戶機方數(shù)據(jù)庫應用程序時,若把過多的負擔加在網(wǎng)絡上,沒有充分利用數(shù)據(jù)庫的存儲過程,沒有把網(wǎng)絡訪問最小化,結果是應用程序要執(zhí)行過多的網(wǎng)絡i/o,使網(wǎng)絡飽和,從而降低了整個系統(tǒng)的性能。要開發(fā)好的客戶機/服務器應用系統(tǒng),必須搞清楚如何在組成系統(tǒng)的各部分之間分布應用功能。
本文提出一些方法來確定客戶機/服務器數(shù)據(jù)庫系統(tǒng)中哪些功能應放在哪里實現(xiàn)??蛻魴C應用程序主要側重于用某種方便用戶的方式表示和(或)分析數(shù)據(jù)。開發(fā)客戶機應用程序時,網(wǎng)絡傳輸量是應重點考慮的問題之一。應注意應用程序如何向數(shù)據(jù)庫服務器發(fā)送信息或從數(shù)據(jù)庫服務器接收信息以及發(fā)送和接收多少數(shù)據(jù)。通常客戶機/服務器系統(tǒng)上網(wǎng)絡i/o是應用程序性能的瓶頸,一個應用程序引起的網(wǎng)絡上i/o越少,應用及整個系統(tǒng)的運行情況越好。要從一個客戶機應用中消除不必要的網(wǎng)絡傳輸量,需要理解和利用sql命令及數(shù)據(jù)庫上的其它一些特征。
二、一個例子
下面,我們來考慮這樣一個例子:一個數(shù)據(jù)庫應用程序完成顯示每個銷售訂單的所有行的金額合計。
一般算法分兩步:
(1)每行項目中數(shù)量乘以單價=金額;
(2)把每行金額累加。
第一種方法:
每次一行,然后,用應用程序累加,即
select orderid, quantity ,unitprice
from item ,stock
where stock.id=item.id
order by orderid
結果為:
orderid quantity unitprice
1 1 6.03
1 1 21.4
1 4 87.12
2 2 8.97
2 3 21.4
采用這種方法,若業(yè)務量增大,則其網(wǎng)絡的傳輸量相應增大。
第二種方法:
讓數(shù)據(jù)庫服務器進行計算,然后只把結果從網(wǎng)上取過來,即:
select orderid ,sum(quantity *unitprice)
from item , stock
where item.id=stock.id
group by orderid
order by orderid
結果為:
orderid sum(quantity*unitprice)
1 265.87
2 82.14
如上所示,由于第二種查詢使用了一個sql的組合,即一個sql函數(shù)(sum)以及一個group by子句,讓服務器來執(zhí)行計算。因此,只需從網(wǎng)上傳輸較少的數(shù)據(jù)。
這個簡單例子說明:
1.在客戶機/服務器環(huán)境中如何用sql函數(shù)減少網(wǎng)絡上的傳輸量;
2.開發(fā)人員必須完全熟悉sql才能做出好的客戶機數(shù)據(jù)庫應用程序。
三、提高性能的方法
下面我們介紹幾種提高性能的方法。
1.使用完整性約束
所有客戶機應用程序必須遵循一系列預先定義的數(shù)據(jù)完整性規(guī)劃及業(yè)務規(guī)則,以保證所有數(shù)據(jù)庫數(shù)據(jù)是合法的。可以使用兩種方法來實施一個簡單的完整的規(guī)則:讓應用程序執(zhí)行完整性檢查;使用oracle7的完整性約束。
(1)讓應用程序執(zhí)行完整性檢查
例如,任何一個訂單( orders)的顧客號必須是客戶機表( customer)中的顧客戶機號。這是一個最簡單的引用完整性,可以用應用程序本身執(zhí)行完整性檢查。
declare
flag integer;
begin
select id into flag
from customer
where id=3
for update of id;
if sql%found then
insert into orders
values(5,3,sysdate,null,null,'f');
-- 其他應用邏輯
commit;
end if;
end;
這個過程只是在應用程序內部用于實施引用完整性規(guī)則的一種方法,但可以看出,為實施一個簡單的完整性規(guī)則,應用程序要花大量的時間通過網(wǎng)絡來請求和發(fā)送數(shù)據(jù)。
(2)使用oracle 7的完整性約束
create table orders
(
id integer primary key,
customer id integer not null references customer,
orderdate date not null,
shipdate date default sysdate,
paidate date default sysdate,
status char(1) default ‘f' check(status in(‘f'
,‘b'))
);
實施簡單完整性規(guī)則(如引用完整性)的更好方法是使用oracle 7的完整性約束。該方法的好處是明顯的:
?、俣x一個表的同時,方便地建立完整性約束,開發(fā)人員不需為實施一個簡單的完整性規(guī)則而創(chuàng)建測試、排錯復雜的數(shù)據(jù)完整性邏輯,提高了工作效率;
②用集中化的方法實現(xiàn)完整性規(guī)則;
③無需任何網(wǎng)絡i/o,客戶機/服務器系統(tǒng)也就不會因為網(wǎng)絡訪問而降低性能。
2.使用數(shù)據(jù)庫觸發(fā)器
應用程序經(jīng)常需要實施復雜的業(yè)務規(guī)則,這些規(guī)則無法用完整性規(guī)則表示,所以最好不要按照常規(guī)思路在應用程序中實施完整性規(guī)則;而是用數(shù)據(jù)觸發(fā)子(triggers)來實施業(yè)務規(guī)則。其優(yōu)點是容易創(chuàng)建,可集中進行規(guī)則實施,避免不必要的網(wǎng)絡i/o。利用數(shù)據(jù)庫觸發(fā)子可以使其他一些應用程序集中化和自動化。 比如,計算item 表中的total 列的值是所訂零件的數(shù)量乘以零件的單價,而零件單價存放在stock表中,當插入一個新的行項目時,應用程序計算total列的值有兩種方法。
方法一:讓應用程序通過sql命令執(zhí)行這個操作
declare total real;
begin
select unitprice*quantity into total
from stock, item
where id=4;
insert into item values(...);
end
應用程序通過網(wǎng)絡發(fā)出請求,取得某一些零件單價,然后插入這個含有該行計算值(tota l)的行。修改item表中某行數(shù)量值,應用程序需要包含相似的邏輯來計算。此外,多個用戶還可能同一時刻插入和修改訂單??傊?用這種方法來計算total 列時會在客戶機/服務器系統(tǒng)中產生大量的網(wǎng)絡傳輸。
方法二:用數(shù)據(jù)庫觸發(fā)子, 從一個行項目自動導出total 的值, 當用戶在item表中插入新行或修改quantity時,無需任何網(wǎng)絡訪問。
create trigger linetotal
before insert or update of quantity,stockid
on item
for each row
delare
itemprice real;
begin
select unitprice
into itemprice
from stock
where id=:new.stockid;
:new.tolal:=new.quantity*itemprice;
end linetotal;
當創(chuàng)建觸發(fā)器linetotal后, 應用開發(fā)人員在編寫應用程序時就不需考慮保持total列為最新值的問題,而且網(wǎng)絡數(shù)據(jù)庫上所有應用都會因此受益。
3.利用過程和包優(yōu)化性能
這里主要討論如何利用完整性約束和數(shù)據(jù)庫觸發(fā)器把應用邏輯移到數(shù)據(jù)庫服務器中執(zhí)行以便減少網(wǎng)絡i/o,提高性能。其它類型應用處理邏輯分布到數(shù)據(jù)庫服務器亦可以減少客戶機/服務器應用中的網(wǎng)絡i/ o,應用程序不必再用包含多個網(wǎng)絡操作的sql語句去執(zhí)行數(shù)據(jù)庫服務器操作,而是簡單且有效地調用存儲過程。包是一種用來把多個有關的過程在數(shù)據(jù)庫中封裝起來的方法。 下面是用sql和用存儲過程例子的差異:
例如要插入某些行項目的訂單,用sql實現(xiàn)過程:
insert into orders values(...)
insert into item values(1,..)
update stock set onhand=...
insert into orders values(...)
insert into item values(2,..)
update stock set onhand=...
insert into orders values(...)
insert into item values(3,..)
update stock set onhand=...
commit;
要創(chuàng)建一個新銷售訂單并插入它的三個行項目,應用程序必須用7個不同的的sql語句來實現(xiàn),每個語句都要通過網(wǎng)絡傳輸數(shù)據(jù),要減少這些sql語句在客戶機/服務器系統(tǒng)中產生的網(wǎng)絡傳輸量,可以創(chuàng)建兩個簡單的過程來插入訂單及行項目。
create procedure placeorder(custid in integer) as
begin
insert into orders
values(orderseq.nextval,custid,sysdate,null,null,‘f
');
end placeorder;
create procedure placeitem
(itemid in integer,partid in integer, quan in integer)
as
begin
insert into item(id,orderid,stockid,quantity)
values(itemid,orderseq.currval,partid,quan);
update stock
set onhand=onhand-quan
where id=partid;
end placeitem;
應用程序只需簡單調用這幾個過程。
placeorder(3);
placeitem(1,3,2);
placeitem(2,8,1);
placeitem(3,9,3);
當一個應用程序調用存儲過程時,通過網(wǎng)絡發(fā)送的數(shù)據(jù)只有過程調用及參數(shù)。本文提出的提高客戶機/服務器應用系統(tǒng)性能的方法,主要是采用合理分布處理邏輯于客戶機端與服務器端,并充分利用數(shù)據(jù)庫服務器來提高執(zhí)行速度。該方法的有效性,已在我們開發(fā)的多項客戶機/服務器應用系統(tǒng)中得到證實。此外,在提高性能的措施和方法中,sql語句的查詢優(yōu)化問題也不可忽視。綜合上述兩種方法,才能從根本上提高客戶機/服務器應用系統(tǒng)的性能。