小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

ORM之硬傷 - Kanas.Net Blog - 博客園

 xnet 2007-01-10

ORM之硬傷

園子里有些人,他們真以為自己明白了面向?qū)ο?,然后裝著滿腹經(jīng)綸,侃侃而談,一篇接一篇,不厭其煩地喊著ORM如何如何。你以為他真的明白“面向?qū)ο?#8221;么?其實,他對面向?qū)ο蟮睦斫鈨H限于教科書中的封裝、繼承和多態(tài),或者再知道一點面向?qū)ο蟮娜舾稍瓌t但其實并不真正理解。
筆者愚鈍,入行多年尚不懂面向?qū)ο?,只懂得用其形而不懂用其實。五年后的某一天終于開竅,明白了面向?qū)ο笾畬?,也僅僅是一個開始而已。當(dāng)又經(jīng)歷了另一個五年的倦怠,發(fā)現(xiàn)并理解了設(shè)計模式、面向方面等技術(shù)作為面向?qū)ο蟮谋匾a(bǔ)充后,才算是徹悟!所以當(dāng)我見過一個同學(xué),尚未出校門已然徹悟,真是羞愧!
有一天面試的時候,我問一位同學(xué),F(xiàn)ramework和Library的區(qū)別是什么?他答不上來。而另一個同學(xué)略一思考就告訴我,你的程序會調(diào)用Library,而Framework會調(diào)用你的程序。雖然精辟,但我還是要補(bǔ)充:Framework通常也會提供一個Library,所以,Library是水平的,而Framework是垂直的,此處的“水平”和“垂直”是相對應(yīng)用系統(tǒng)的層次設(shè)計而言的。如果沒有層次,其實Framework其實就是Library。Microsoft的Enterprise Library當(dāng)然就是一個Library,無法代替Framework。
如果讓那位已經(jīng)徹悟的同學(xué)舍棄ORM來實現(xiàn)復(fù)雜的業(yè)務(wù)功能,他當(dāng)然無法接受。相反,如果讓一位抱著《Thinking in Java》似懂非懂的同學(xué)用ORM來實現(xiàn)同樣的功能,他也一樣無法接受。其中的一些同學(xué)非常擅于“雞蛋里挑骨頭”,于是園子里有了這樣一堆垃圾文章或者垃圾跟貼。另外一些同學(xué)不精于這樣的能力,所以仍在徬徨之中。

此乃ORM惟一之硬傷也!如果你不理解面向?qū)ο笏枷耄拖仍囍ダ斫?,然后再來討論ORM這個話題,并發(fā)表你的高見。

再說性能
ORM提供了所有SQL語句的生成,代碼人員遠(yuǎn)離了數(shù)據(jù)庫概念。從一個概念需求(例如一個HQL)映射為一個SQL語句,并不需要什么代價,連1%的性能損失都沒有。真正的性能損失在映射過程中,更具體地講,是在對象實例化的過程中。我曾經(jīng)做過一個試驗,以“計算第N個素數(shù)”這樣的命題。我采用Delphi寫Native Win32 Console程序,又采用C#寫CLR Console程序。兩者相比,令我大失所望。

N

結(jié)果

耗時

Delphi

C#

1000

7927

0ms

2ms

10000

104743

16ms

17ms

100000

1299721

438ms

324ms

1000000

15485867

11437ms

7823ms

該命題采用的算法是找出第N個素數(shù)以前的所有素數(shù),開辟一個內(nèi)存區(qū)存貯這些素數(shù)。在Delphi中我用鏈表,在C#中我用List<int>。實際的結(jié)論是:當(dāng)列表足夠大時,鏈表的性能遠(yuǎn)不及List<int>。當(dāng)然,如果每個鏈表節(jié)點只裝一個元素,這種差異會更明顯。事實上,我測試過每個鏈表節(jié)點所裝的元素個數(shù)做了一個階梯試驗,從30個、254個、510個、1022個到2046個,每個節(jié)點所裝載的元素數(shù)越多,耗時越短,最終越來越接近C#的List<int>。
不知道各位是否已經(jīng)明白了性能在哪兒損失了:內(nèi)存分配。Native的內(nèi)存分配與釋放都是非常耗時的操作系統(tǒng)行為。但在托管環(huán)境下,內(nèi)存的釋放是GC干的事情,甚至不需要統(tǒng)計到耗時中,而內(nèi)存的分配也是一件非??旖莸氖虑椤.?dāng)然,即使是快捷也還是需要耗時的。這讓我聯(lián)想到DataSet的性能。DataSet也是一種數(shù)據(jù)容器,但是卻沒有多少人抱怨DataSet的性能。如果你明白DataSet的機(jī)制,就會發(fā)現(xiàn),DataStorage巧妙地規(guī)避了內(nèi)存分配和耗時的問題。而我們的ORM無法解決每個對象實例在構(gòu)造時分配內(nèi)存所耗時間。我做了一個不精確的評估,相比DataSet,對象集合的性能損失大約占20%左右。
如果假定ORM并沒有比傳統(tǒng)的數(shù)據(jù)訪問方式耗費額外的IO的話,除此之外,ORM再沒有任何性能損失!
再回到前提條件:ORM并沒有比傳統(tǒng)的數(shù)據(jù)訪問方式耗費額外的IO。這個條件成立么?
由于ORM的實體對象定義已經(jīng)固定,所以即使我不需要某些字段,也一樣需要加載這些字段。
OK,有的同學(xué)已經(jīng)看出來了。額外定義一個視圖的實體對象即可。定義這些視圖的實體對象的確很麻煩,但是肯定比構(gòu)造那些SQL并不斷地維護(hù)它簡單得多。
當(dāng)一張表中有1000萬行數(shù)據(jù)時,實例化1000萬個對象是不可能的。
非常正確。難道你曾經(jīng)成功地嘗試過將1000萬行數(shù)據(jù)加載到某個DataTable中并且沒有性能問題?從應(yīng)用的角度來說,在一個模型中包含的實例數(shù)超過500行就有設(shè)計不當(dāng)?shù)南右伞N覍oogle的抱怨是:當(dāng)搜索結(jié)果超過1000個時都會令我抓狂。讓我從1000行數(shù)據(jù)中找出我所需要的某一行,這是開發(fā)人員的思維,并不是用戶的思維。如果能夠在已有的結(jié)果中進(jìn)行二次、三次或者多次進(jìn)一步的篩選,可能更適合絕大多數(shù)人。我為什么不愿意在分頁中花太多的精力,其原因也是如此。我認(rèn)為用戶的眼球只能接受100行以內(nèi)的數(shù)據(jù),超過這個行數(shù)就需要采用其它的方式,或者改善領(lǐng)域設(shè)計。所以,這個問題的答案是:你不可能需要一次載入1000萬行。
當(dāng)應(yīng)用系統(tǒng)整體性能欠佳時,因為隱藏了數(shù)據(jù)訪問細(xì)節(jié),從而無法找到快速優(yōu)化的途徑。
不能同意。幾乎每一個ORM框架都提供了非??煽康臄?shù)據(jù)庫訪問日志。通過這些日志分析性能損失將比直接使用SQL語句更可靠、更方便。

靈活性
ORM不夠靈活?我完全不能理解,我甚至不知道這個不夠靈活是與什么基準(zhǔn)相比。相反,ORM可以讓你靈活地替換數(shù)據(jù)庫(當(dāng)然這個優(yōu)點并沒有非常重要的意義);在修改數(shù)據(jù)庫以后不需要修改服務(wù)層或者只需要進(jìn)行簡單的修改;可以對某個服務(wù)進(jìn)行單獨的測試;可以對服務(wù)進(jìn)行不依賴數(shù)據(jù)庫的、上下文一級的擴(kuò)展;可以進(jìn)行更好的層次設(shè)計;......
不能實現(xiàn)所有的查詢條件
如果是想表達(dá)“每一個Select語句可以通過面向?qū)ο蟮姆绞竭M(jìn)行查詢”的話,我覺得目前絕大部分ORM框架都已經(jīng)很好地解決。我解決這一問題的基礎(chǔ)是:我不提供超越SQL ANSI92的能力,但覆蓋SQL ANSI92的所有功能。對于解決實際應(yīng)用中的不足部分,采用運(yùn)行時算法補(bǔ)充。Hibernate采用的是HQL這樣的方式,基本上SQL能夠做到的,HQL都無一例外可以做到。ECO采用的是OCL的方式,其功能可以完全覆蓋SQL。我的框架所實現(xiàn)的查詢目前我還沒有發(fā)現(xiàn)無法解決并必須利用Native SQL來實現(xiàn)的(因此我無法理解Hibernate3為什么要提供這樣的擴(kuò)展)。Hibernate采用的策略是以面向?qū)ο鬄楹诵?,換句話說,以持久化對象為終極目標(biāo),而以加載對象以持久化對象為前提。設(shè)計一個POJO,實例化,然后保存起來,下次使用的時候可以依樣載入即可。大規(guī)模的查詢并不是框架的核心目標(biāo)。所以,如果你完全依賴Hibernate去持久化,我非常擔(dān)心你將來是否有機(jī)會用你的數(shù)據(jù)積累去做數(shù)據(jù)倉庫。而我的框架目標(biāo)則不同。在持久化與加載兩個目標(biāo)間我沒有主次之分。我也沒有超前到MDA,我的對象模型仍然基于數(shù)據(jù)庫的ER設(shè)計,我仍然提供一組非常清晰明了的數(shù)據(jù)庫視圖。
多表連接查詢
如果需要將多表的連接查詢結(jié)果轉(zhuǎn)換成一個二維視圖,顯然需要你再定義另一個視圖實體對象,將視圖映射到對象模型。如果你僅僅是要在一個對象實例的某個屬性中獲得另外一個對象的集合,似乎這不是DAL方式的優(yōu)勢,而反而是ORM的優(yōu)勢。將多個對象所依賴的多個對象放到同一個上下文中,顯然這是最好的一種方式。
統(tǒng)計查詢
從理論上講,ORM不適合做OLAP,不適合做太多統(tǒng)計查詢。其實這一點,我的框架已經(jīng)提供了非常好的解決方案,對Aggregate到面向?qū)ο蟮囊晥D處理得非常好。

開發(fā)效率
提高開發(fā)效率僅僅是一個抽象的目標(biāo),具體的手段應(yīng)該是兩個方面:一是IDE和輔助工具;一是適合將任務(wù)分解成多個解耦的部分從而可以通過增加人員來提升總的開發(fā)效率。雖然ORM僅僅是開發(fā)環(huán)節(jié)中很小的一部分,但是卻遍布應(yīng)用系統(tǒng)中的每一角落,因而對開發(fā)效率影響較大。除了ORM,難道還有更好的選擇么?
ORM后,原來精湛的SQL技能變得毫無用武之地,讓人甚是失落,但這并不是ORM的過錯。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多