兩種Oracle應用程式開發介面之簡要分析

noter發表於2007-06-05

引言 

Oracle以其優越的穩定性和卓越的效能在眾多領域裡有著廣泛的應用,其高效能是Oracle優於其他資料庫的關鍵因素。然而影響終端應用程式的效能不只是Oracle服務程式及硬體環境,應用程式的開發語言和開發方式也有著重要的影響。

目前,可以在多種開發語言中開發Oracle應用程式,比如可以在VB、Delphi等高階 開發語言中開發,可以以C++開發,也可以以Java語言開發,甚至可以通過ASP、JSP、Perl等指令碼語言來訪問Oracle。這些語言環境各有其 優勢,C++無疑是追求極致速度的首選。

在C++中我們也可以有多種介面方式,可以使用ADO通用介面,可以使用OCI/OCCI, 還可以使用ODBC、OO4O及OLEDB等方式。在這些方式中,ADO與OCI是應用最為廣泛的兩種方式,本文將集中力量介紹在Visual C++ 6.0 中這兩種介面的開發方法及它們的特點對比。

一、ADO開發介面簡介 

ADO(ActiveX Data Objects,ActiveX資料物件)是Microsoft為強大的資料訪問介面 OLEDB(物件連結和嵌入資料庫)而設計的,是一個便於使用的應用層的程式設計介面。使用 ADO編寫的應用程式可以通過OLEDB提供者訪問和運算元據庫伺服器中的資料。ADO 最主要的優點是易於使用、可以訪問多種資料庫及可以在多種語言中開發。

由於ADO建立在自動化(Automation)的基礎上,所以ADO的應用場合非常廣泛, 不僅可在Visual Basic這樣的高階語言開發環境中使用,還可以在一些指令碼語言中使用,這對於開發Web應用和在ASP(Active Server Page,動態伺服器主頁)的指令碼程式碼中訪問資料庫提供了操作應用的捷徑。

ADO訪問資料庫的模型示意參見圖1。

498)this.style.width=498;">
圖1:ADO模型示意圖

從上圖可以看出ADO是以OLE DB為基礎,它對OLE DB進行了封裝,所以ADO其實是OLE DB的應用層介面,是介於OLE DB與應用程式之間的中間層。這種結構為一致的資料訪問介面提供了很好的擴充套件性,不再侷限於特定的資料來源,只要OLE DB支援的資料來源,ADO都可以很好地支援。

ADO的另一個特性是使用簡單,它封裝了OLE DB的複雜的介面,以Connection、Recordset、Command三個主體物件及Errors、Properties、Parameters和Fields四個集合物件搭建起了ADO物件模型,見下圖: 

498)this.style.width=498;">
圖2:ADO物件模型

 

二、OCI開發介面簡介

OCI(Oracle Call Interface)是Oracle 資料庫呼叫介面,是由Oracle提供的用於開發前端應用程式及中介軟體的C/C++開發類庫。通過OCI,可以控制所有型別的SQL語句的執行,包括 DDL、控制語句(事務、會話、系統)、查詢、DML、PL/SQL,以及嵌入式SQL。OCI能夠最大程度地控制程式的執行,執行Oracle伺服器所 允許的多有資料庫操作,可以訪問Oracle資料庫伺服器裡的所有資料型別,包括標量值、集合和所有物件型別的例項,可以以引用的方式訪問物件及其元數 據,可以動態獲取、修改物件的屬性值。

OCI程式既具有SQL非過程性的優點,也具有第三代程式設計語言的過程性和靈活性,使開發的程式設計技術具有更強的資料處理能力。

同時,OCI在所有執行Oracle的平臺上具有良好的可移植性,程式無須太大修改即可執行在Unix/Linux/Windows甚至嵌入式環境下。

OCI還是其他Oracle開發介面的底層實現,如ADO、JDBC都是在OCI上層的封 裝,由於OCI是比較底層的介面,少了很多層的封裝,可以提供應用程式與Oracle的直接連線,所以OCI可以提供最佳的效能。正是基於此, Oracle自身的一些工具及許多著名的Oracle 資料庫工具也都是用OCI開發的,如大名鼎鼎的Toad。筆者的OraExplorer也是基於OCI介面開發。

但由於C/C++的學習難度比較大,所以OCI的開發難度與ADO、JDBC等開發介面相比要大許多,OCI的每一個函式的引數都非常多,且比較難以理解,而國內關於OCI開發的學習資料非常少,所以使用OCI開發應用程式的程式設計師相對ADO的程式設計師要少得多.

三、對比實驗設計

本文將通過一個具體的實驗來對比ADO與OCI的效能差距,資料庫訪問介面的效能主要體現在 兩個方面,一個是資料讀取速度,另一個是資料寫入速度,所以本文將基於ADO和OCI各自開發一個Visual C++ 6.0應用程式來進行這兩個方面的實驗,每個程式完成功能如下:

1) 建立連線

首先,需要連線到Oracle伺服器,在這一步需要使用者提供SID、使用者名稱和密碼資訊。

2) 資料初始化

為了實驗的通用性及方便讀者重現,本實驗直接在System使用者下操作,需要一個記錄數比較多的表來,首先對all_objects表映象,生成my_objects表,然後對My_objects表自身進行五次遞迴映象,最生成一個百萬記錄的表。相關SQL語句如下:

Truncate table my_objects;

Drop table my_objects;

create table my_objects as select * from all_objects;

insert into my_objects select * from my_objects;

insert into my_objects select * from my_objects;

insert into my_objects select * from my_objects;

insert into my_objects select * from my_objects;

insert into my_objects select * from my_objects;

3) 資料讀取

遍歷資料表,讀取Object_name欄位的值,並記錄花費的時間。

4) 資料寫入

--建立新表

truncate table my_objects2;

drop table my_objects2;

create table my_objects2 (

owner varchar2(30),

object_name varchar2(30),

subobject_name varchar2(30),

object_id int,

data_object_id int);

向表中寫入10萬條記錄,並記錄花費的時間。

5) 清空環境

釋放記憶體,斷開連線。

四、ADO程式關鍵程式碼

首先需要在stdafx.h中新增如下程式碼:

//消除一些無用的警告

#pragma warning(disable:4146 4244)

//匯入ADO應用庫,並對名稱空間及EOF重新命名

#import "C:/Program Files/Common Files/System/ADO/msado15.dll" /

rename_namespace("MYADO") rename("EOF", "EndOfFile")

下面的是關鍵實現程式碼:

//初始化連線物件

hr = m_pConnection.CreateInstance(__uuidof(MYADO::Connection));

//初始化記錄集物件

m_pRs.CreateInstance(__uuidof(MYADO::Recordset));

//設定連線引數

CString strConnection;

strConnection.Format(_T("Provider=OraOLEDB.Oracle.1;"

"Password=%s;"

"User

"Data Source=%s"),

strPwd, strUser, strSID);

//連線到資料庫

m_pConnection->Open((_bstr_t)strConnection,_T(""),_T(""),-1);

//執行SQL語句

strSQL.Format("Truncate table my_objects");

m_pConnection->Execute(_bstr_t(strSQL),NULL,MYADO::adCmdText);

//開啟記錄集

strSQL.Format("Select object_name from my_objects");

m_pRs->Open((_bstr_t)strSQL,

m_pConnection.GetInterfacePtr(),

MYADO::adOpenForwardOnly,

MYADO::adLockReadOnly,

MYADO::adCmdText);

//遍歷並讀取資料

while(!m_pRs->EndOfFile)

{

varValue = m_pRs->Fields->GetItem(long(0))->GetValue();

m_pRs->MoveNext();

}

strSQL.Format("Insert into my_objects2 values 

('TestTest','TestTest','TestTest',0,0)");

//寫入資料

for(int i=0;i<100000;i++)

{

m_pConnection->Execute( 

_bstr_t(strSQL),NULL,MYADO::adCmdText);

}

//關閉連線

m_pConnection->Close();

 

OCI的關鍵程式碼限於篇幅,不予羅列。

本實驗的ADO應用程式的原始碼、可執行程式以及OCI的可執行程式可以到http://www.snowywolf.net下載,OCI的原始碼因涉及技術保密問題,無法公開,敬請諒解.

五、實驗結果

為了消除網路影響,Oracle伺服器和應用程式在同一檯筆記本上執行。 

硬體環境

CPU:Intel 雙核2.0G

硬碟:7200轉 100G

記憶體:1G

軟體環境

作業系統:winXP SP2

資料庫:Oracle 9.2.0.1.0

統計結果中的程式碼行數為除去介面通用程式碼後的有效程式碼行數。 

498)this.style.width=498;">
表1

六、ADO與OCI對比分析

1、功能方面

ADO為了保持其通用性,除了對MS SQLServer支援較好外,沒有辦法對其他資料庫提供很完善的功能,對Oracle同樣如此。通過ADO訪問Oracle,可以實現比較通用的功能, 如DML、DDL、查詢、事務控制等,但對於Oracle中的物件、集合、LOB等特殊元素則不能很好地支援,對於PL/SQL的支援也很不完整。而 OCI在這方面則有著顯著的優勢,它可以很完整地支援Oracle的所有功能,可以說是對Oracle功能支援最完整的開發介面。而且OCI可以支援多種 作業系統,而ADO則只能在Windows系列作業系統下執行。

但在支援面方面,ADO則有很大優勢:一方面,它幾乎支援目前所有流行的資料庫,如MS SQLServer、Oracle、Sybase、DB II等,寫好的訪問一種資料庫的程式碼,可以稍做修改就能支援另一種資料庫,這是ADO的巨大優勢;另一方面,它也幾乎支援目前所有的開發環境,不管是採用 VC開發還是用VB開發,甚至採用Delphi、ASP等等都可以使用ADO來訪問資料庫。

2、效能方面

從上面的實驗結果可以看出,在效能方面,OCI也有著非常大的優勢,讀取資料的速度快了4倍多,寫入資料的速度快了一百多倍。

由於OCI省掉了應用程式與Oracle伺服器之間的中間封裝層,可以直接訪問資料,另外,OCI是C介面,可以直接操縱內在,所以其訪問速度非常快,佔用系統資源和網路資源也都要少得多。

在筆者的開發經驗中,對於儲存在Oracle中的二進位制資料(如空間資料、影像資料)及長字串資料,OCI的效能優勢要更加明顯。

3、開發難度方面

在這方面ADO的優勢很明顯,首先,ADO的學習難度較低,ADO是以物件導向的思想封裝 的,其物件和方法都易學易用,而且ADO的學習資料很豐富,網上可以找到大量的文件及原始碼;而OCI則是過程化封裝的開發介面,它的函式雖然不是很多, 但函式之間的關係比較複雜,且函式的引數非常多,很多函式都有十幾個引數,非常難於理解。另外,國內使用OCI開發的程式設計師比較少,可用的參考資料也非常 少,所以OCI的學習難度很大。

另一方面,OCI開發的程式的程式碼量要比ADO的多得多,且程式碼之間的關係比較複雜,不易維護。

為了解決這一方面的問題,筆者基於OCI進行了基於物件導向思想的封裝,簡化了OCI 的開發模型,並封閉了OCI的異常處理機制,使得OCI的開發難度大大降低,程式碼量能夠接近於ADO的程式碼量,且更易維護。這一部分的內容不屬於本文討論範圍,所以不在此展開論述。

七、總結與結論

 

ADO與OCI是在VC中開發Oracle應用程式的常用的兩種介面,它們各自有著自己的特點,有獨特的優勢,也都有自己的侷限性,在開發過程中我們需要根據具體情況來選擇使用哪種開發介面。

如果應用程式需要訪問多種資料庫,既要訪問儲存在Oracle中的資料,也要訪問儲存在MS SQL Server中的資料,那麼ADO是最佳選擇,它可以使用一套程式碼實現多種資料庫的訪問。

如果應用程式只需要訪問Oracle資料庫,且對效能要求很高,那OCI就是最好的選擇了


 

【來源】

相關文章