为什么ORM性能比iBATIS好?
?緩存是有很多層次的,有web server前端緩存,有動態(tài)頁面靜態(tài)化,有頁面片斷緩存,有查詢緩存,也有對象緩存。不同層面的緩存適用于不同的應用場景,作用也各自不同,如果可以,你全部一起用上,他們不矛盾,但這個話題比較大,現(xiàn)在不展開談。?
針對OLTP類型的web應用,只要代碼寫的質量沒有問題,最終的性能瓶頸毫無疑問還是數(shù)據(jù)庫查詢。應用服務器層面可以水平擴展,但是數(shù)據(jù)庫是單點的,很難水平擴展,所以如何有效降低數(shù)據(jù)庫查詢頻率,減輕數(shù)據(jù)庫壓力,是web應用性能問題的根源。?
以上所有的緩存方式都可以直接或者間接的降低數(shù)據(jù)庫訪問,但緩存是有應用場景的,雖然新聞網(wǎng)站非常適合使用動態(tài)頁面靜態(tài)化技術,但是例如電子商務網(wǎng)站就不適合動態(tài)頁面靜態(tài)化,而頁面緩存和查詢緩存可以使用的場景也不多。但是對象緩存是所有緩存技術當中適用場景最廣泛的,任何OLTP應用,即使實時性要求很高,你也可以使用對象緩存,而且好的ORM實現(xiàn),對象緩存是完全透明的,不需要你的程序代碼進行硬編碼。?
用不用對象緩存,怎么用對象緩存,不是一個調優(yōu)的技巧問題,而是整個應用的架構問題。在你開發(fā)一個應用之前,你就要想清楚,這個應用最終的場景是什么?會有多大的用戶量和數(shù)據(jù)量。你將采用什么方式來架構這個應用:?
OK,也許你偏愛SQL,那么你選擇iBATIS,數(shù)據(jù)庫設計當中大表有很多冗余字段,會盡量消除大表之間的關聯(lián)關系,最終用戶量和訪問量很高以后,你會選擇使用Oracle,雇傭資深的DBA,進行數(shù)據(jù)庫調優(yōu)和SQL調優(yōu),這是大多數(shù)公司走的路。?
但是我告訴你,你還有另外一條路可以走。你可以選擇ORM(不見得一定是Hibernate),數(shù)據(jù)庫設計當中避免出現(xiàn)大表,比較多的表關聯(lián)關系,通過ORM以對象化方式操作。當用戶量和訪問量很高以后,除了數(shù)據(jù)庫端本身的優(yōu)化,你還有對象緩存這條途徑。對象緩存是怎樣提高性能的呢?隨便舉個例子:?
論壇的列表頁面,需要顯示topic的分頁列表,topic作者的名字,topic最后回復帖子的作者,如果是iBATIS,你準備怎么做??
你需要通過join user表來取得topic作者的名字,然后你還需要join post表取得最后回復的帖子,post再join user表取得最后回貼作者名字。?
也許你說,我可以設計表冗余,在topic里面增加username,在post里面增加username,所以通過大表冗余字段,消除了復雜的表關聯(lián):?
OK,且不說冗余字段的維護問題,現(xiàn)在仍然是兩張大表的關聯(lián)查詢。然后讓我們看看ORM怎么做??
就這么一條SQL搞定,比上面的關聯(lián)查詢對數(shù)據(jù)庫的壓力小多了。?
也許你說,不對阿,作者信息呢?回貼作者信息呢?這些難道不會發(fā)送SQL嗎?如果發(fā)送SQL,這不就是臭名昭著的n+1條問題嗎??
你說的對,最壞情況下,會有很多條SQL:?
事實上何止n+1,根本就是3n+1條SQL了。那你怎么還說ORM性能高呢??
因為對象緩存在起作用,你可以觀察到后面的3n條SQL語句全部都是基于主鍵的單表查詢,這3n條語句在理想狀況下(比較繁忙的web網(wǎng)站),全部都可以命中緩存。所以事實上只有一條SQL,就是:?
這條單表的條件查詢和iBATIS通過字段冗余簡化過后的大表關聯(lián)查詢相比,當數(shù)據(jù)量大到一定程度以后(十幾萬條),查詢的速度會差至少一個數(shù)量級,而且對數(shù)據(jù)庫的壓力很小,這就是對象緩存的真正威力!?
更進一步分析,使用ORM,我們不考慮緩存的情況,那么就是3n+1條SQL。但是這3n+1條SQL的執(zhí)行速度一定比iBATIS的大表關聯(lián)查詢慢嗎?不一定!因為使用ORM的情況下,第一條SQL是單表的條件查詢,在有索引的情況下,速度很快,后面的3n條SQL都是單表的主鍵查詢,在繁忙的數(shù)據(jù)庫系統(tǒng)當中,3n條SQL幾乎可以全部命中數(shù)據(jù)庫的data buffer。但是使用iBATIS的大表關聯(lián)查詢,很可能會造成全表掃描,這樣性能是非常差的。?
所以結論就是:即使不使用對象緩存,ORM的n+1條SQL性能仍然很有可能超過iBATIS的大表關聯(lián)查詢,而且對數(shù)據(jù)庫造成的壓力要小很多。這個結論貌似令人難以置信,但經(jīng)過我的實踐證明,就是事實。前提是數(shù)據(jù)量和訪問量都要比較大,否則看不出來這種效果?
還是拿上面這個例子的應用場景來說,由于JavaEye網(wǎng)站用RoR的ActiveRecord,所以這個場景事實上就會發(fā)送3n+1條SQL語句。我從log里面看到這密密麻麻的SQL,著實非常擔憂性能,所以嘗試使用了find的:include選項去eager fetch,迫使ActiveRecord發(fā)送單條復雜的關聯(lián)查詢。但非常不幸的是,在網(wǎng)站服務器的production.log里面經(jīng)過前后對比,發(fā)現(xiàn)使用:include以后,單條復雜關聯(lián)查詢耗時更多,數(shù)據(jù)庫壓力更大。?
在使用memcached之后,比3n+1條的性能進一步明顯提升。所以性能對比就是這樣的:?
ORM + Cache > ORM n+1 > iBATIS 關聯(lián)查詢?
那為什么應用Cache可以進一步提高性能,是因為訪問Cache的開銷比訪問數(shù)據(jù)庫小的得多造成的。?
應用程序根據(jù)主鍵key去Cache Server取value,是非常簡單的算法,開銷極小。?
而發(fā)送一條主鍵查詢的SQL到數(shù)據(jù)庫,要經(jīng)過非常復雜的過程,有SQL的解析,執(zhí)行計劃的優(yōu)化,占位符參數(shù)的代入,只讀事務的保護和隔離等等,最終雖然也命中了數(shù)據(jù)庫的data buffer,但是開銷確實很大。?
BerkeleyDB就是一個極好的證明,它號稱其查詢速度是Oracle的1000倍,不是因為它做的比Oracle牛,而是因為它本質上就是一個大Cache,查詢沒有額外的開銷。
轉載自:http://robbin.iteye.com/blog/77338
轉載于:https://blog.51cto.com/visionsky/659659
總結
以上是生活随笔為你收集整理的为什么ORM性能比iBATIS好?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于 IE的文档模式的指定
- 下一篇: EonerCMS——做一个仿桌面系统的C