2011-09-07 112 views
6

我是ORM的對象 - 關係映射的粉絲,我在過去的一年半中一直在使用它。在此之前,我使用JDBC編寫原始查詢,並使數據庫通過存儲過程進行繁重的工作。使用ORM,我最初很樂意做類似coach.managermanager.coaches這些非常簡單易讀的內容。對象關係映射的缺點

但隨着時間的推移,在衆多的協會中爬行,最後我做了a.b.c.d,它們在幕後向各個方向發射查詢。使用rails和ruby,垃圾收集器變得瘋狂並且花費了瘋狂的時間來加載一個非常複雜的頁面,這個頁面涉及的數據相對較少。我不得不用一個簡單的存儲過程替換這個ORM樣式代碼,我看到的結果是巨大的。耗時50秒的頁面現在只需要2秒鐘。

有了這個巨大的差異,我應該繼續使用ORM嗎?與原始查詢相比,它有非常明顯的開銷。

一般來說,使用像Hibernate,ActiveRecord這樣的ORM框架的一般缺陷是什麼?

+0

您是否在使用懶惰抓取?基本上'ORM'的加載和你說的一樣多... –

+0

@Petar Minichev:嗯,我不能直接回答這個問題,因爲我正在做所有類型的訪問,ORM允許我。在任何地方都有一點折衷 – bragboy

回答

5

我想你已經確定了與ORM軟件相關的主要折衷。每當你添加一個新的抽象層試圖提供一個你曾經手動完成的事情的泛化實現時,會出現性能/效率的一些損失。

正如您所指出的那樣,遍歷多個關係(如a.b.c.d)可能效率低下,因爲大多數ORM軟件將爲每個.進行一次獨立的數據庫查詢。但我不確定這意味着你應該完全消除ORM。大多數ORM解決方案(或者至少當然是Hibernate)允許你指定自定義查詢,你可以在單個數據庫操作中準確地返回你想要的。這應該和專用SQL一樣快。

真的這個問題是關於理解ORM層如何在幕後工作,並意識到雖然像a.b.c.d這樣的東西很容易編寫,但它導致ORM層執行的操作並非如此。作爲一般規則,我總是使用最簡單的方法開始,然後在有意義的區域編寫優化的查詢/顯而易見的是簡單的方法不會擴展。

12

ORM只是一個工具。如果你沒有正確使用它,你會得到不好的結果。

沒有什麼能夠阻止您使用專用的HQL /條件查詢與取指連接或投影,以儘可能少的查詢返回頁面必須顯示的信息。這或多或少會與專用的SQL查詢相同。當然,如果您只是通過ID獲取所有內容,然後在沒有意識到生成多少查詢的情況下瀏覽對象,則會導致加載時間較長。關鍵是要確切瞭解ORM在現場的作用,並決定是否合適,或者是否需要採取其他策略。

3

我想說,應該爲不同的任務使用適當的工具。例如,對於CRUD操作,像Hibernate這樣的ORM框架可以加速開發,並且它的性能會很好。有時你需要做一些必要的調整來達到可接受的性能。我不確定,你的任務(Hibernate耗時50秒)無法用Hibernate完成,因爲你沒有向我們提供細節。另一方面,例如涉及成千上萬條記錄的批量操作並不是您期望Hibernate將執行的任務類型,而不會造成顯着的性能損失。

1

我與Petar從你的評論中提到了懶惰的取材。假設你有一個html表格填充來自對象a.b.c.d的字段。你可以找到你的框架將數據庫往返數千次(可能還有更多)。在這種情況下ORM的缺點是你必須仔細閱讀文檔。大多數框架支持禁用延遲獲取,許多框架甚至支持添加自己的處理邏輯來綁定數據集。

淨的是,幾乎所有的ORM幾乎無疑比你自己寫的任何東西都要好。你會發現自己揹負着大量的樣板庫,或者一遍又一遍地寫同樣的代碼。

2

如前所述,ORM只是一個工具,您可以使用它的好壞。

ORM中最典型的性能問題之一是1 + N查詢問題。它是由列表中的每個對象加載其他對象引起的。這是由列表中每個元素的1對n關係實體的急切獲取引起的,該交易使用HQL查詢,指定投影中的字段或將1對n關係提取爲懶惰的標記。

任何時候,您都必須知道ORM在做什麼才能獲得良好的性能。不理解在後臺執行的操作是一種災難(由於不必要的錯誤編寫的解決方法而導致運行緩慢,錯誤且難以分析代碼)。

0

我們正在研究從我們自己的數據存儲層切換到傳輸對象和數據訪問對象的清晰分離到JPA。我們使用一個生成器來創建TOs,DAO和SQL DDL以及docbook格式的一些文檔。通過文檔,數據庫結構和生成的Java類,我們所有的東西始終與數據庫本身的良好文檔同步。

是我們目前爲止使用JPA發現:

  1. 外鍵引用不能用於進口,一些特殊 查詢等,因爲它們不能被放置在一個管理 實體。 JPA只允許目標課程在那裏。
  2. 對某些用戶會話範圍的訪問很難完成。我們 仍然不知道如何在某些PrePersist方法中將用戶標識放入 'userWhoLastMadeAnUpdate'列中。
  3. 對於ORM來說,預計會很容易,即「類 映射」根本不起作用。我們在內部使用HalDateTime (http://sourceforge.net/projects/haldatetime/)。 特別是在客戶端。雖然HalDateTime支持它,但直接使用JPA映射它並不是 。由於JPA限制 ,我們必須在實體中使用兩個字段。
  4. JPA使用一個XML文件來描述映射。所以你必須至少將 分成兩個文件才能理解Java類和數據庫之間的關係 。對於大型應用程序來說,XML文件變得非常龐大。
  5. 或者,ORM在Java類本身中提供註釋。所以 它更容易學習和理解的關係。但它會強制您查看客戶端層中的所有數據庫內容(其中的 完全打破了適當的分層)。
  6. 您將不得不限制自己儘可能地保持一個乾淨的 數據庫結構。否則,您將確定 最終會導致ORM查詢和聲明混亂。
  7. 使用一個ORM,它提供了一種接近於SQL 本身的查詢語言(JPA在這裏看起來完全可以接受)。 ORM引發的語言 使得支持大型應用程序的成本非常昂貴。