ORM到底是用還是不用?

ORM即Object/Relation Mapping的簡寫,一般稱作「對象關係映射」,在Web開發中最常出沒於和關係型數據庫交互的地方。接口、中間件、庫、包,你都可以這麼稱呼它。

我們可以結合PHP和MySQL,從ORM的四個核心理念來認識它:

  • 簡單:ORM以最基本的形式建模數據。比如ORM會將MySQL的一張表映射成一個PHP類(模型),表的字段就是這個類的成員變量
  • 精確:ORM使所有的MySQL數據表都按照統一的標準精確地映射成PHP類,使系統在代碼層面保持準確統一
  • 易懂:ORM使數據庫結構文檔化。比如MySQL數據庫就被ORM轉換為了PHP程序員可以讀懂的PHP類,PHP程序員可以只把注意力放在他擅長的PHP層面(當然能夠熟練掌握MySQL更好)
  • 易用:ORM的避免了不規範、冗餘、風格不統一的SQL語句,可以避免很多人為Bug,方便編碼風格的統一和後期維護 


接下來再通過一個很基本的例子來說明一下ORM的使用,還以PHP和MySQL為例。
user這個數據模型是再普遍不過的了。假設我們有一張user數據表,結構如圖:
在OOP中通常我們需要寫一個對應的class User來作為user數據表的數據模型:

// 聲明class User
class User{
    $id;
    $name;

    function create(){/*...*/}
    function load($id){/*...*/}
}

// 使用class User
$user = new User();
$user->name = 'fancy';
$user->create();

但是通過ORM,我們可以不用去聲明class User,可以直接繼承ORM提供的工廠類,比如:

// 直接使用!對於熟悉MVC的親知道這個意義之所在!
$user = new ORM('user');  // ORM都有自己的規則,這裡直接使用了MySQL的表名
$user->name = 'fancy';    // MySQL的表的字段就是$user對象的成員變量
$user->save();            // 掉用ORM提供的接口函數

ORM一般都針對數據模型提供了一下常見的接口函數,比如:create(), update(), save(), load(), find(), find_all(), where()等,也就是講sql查詢全部封裝成了編程語言中的函數,通過函數的鏈式組合生成最終的SQL語句。

所以由這些來看,ORM對於敏捷開發和團隊合作開發來說,好處是非常非常大的。這裡就羅列一下我想到的ORM顯著的優點

  • 大大縮短了程序員的編碼時間,減少甚至免除了對Model的編碼
  • 良好的數據庫操作接口,使編碼難度降低,使團隊成員的代碼變得簡潔易讀、風格統一
  • 動態的數據表映射,在數據表結構甚至數據庫發生改變時,減少了相應的代碼修改
  • 減少了程序員對數據庫的學習成本
  • 可以很方便地引入數據緩存之類的附加功能 

但是ORM並不是一個完美的東西,它同時也有其自身不可避免的缺點

  • 自動化進行關係數據庫的映射需要消耗系統性能。其實這裡的性能消耗還好啦,一般來說都可以忽略之,特別是有cacha存在的時候
  • 在處理多表聯查、where條件複雜之類的查詢時,ORM的語法會變得複雜且猥瑣
  • 越是功能強大的ORM越是消耗內存,因為一個ORM Object會帶有很多成員變量和成員函數。有一次修復bug時就遇見,使用ORM查詢的時候會佔用12MB的內存,而使用SQL的查詢時只佔用了1.7MB……

ORM就是這麼一個讓人又愛又恨的東西。回到我們開始的問題:「ORM到底是用還是不用?」。

Fancy個人的觀點是:ORM要用!但關鍵部位不能用!

因為對於一般的Web應用開發來說,使用ORM確實能帶來上述的諸多好處,而且在大部分情況下涉及不到ORM的不好的地方。但是在系統裡面有大數據量、大運算量、複雜查詢的地方,就不要用ORM。ORM的性能問題將給你帶來災難。在這些地方就可以使用純SQL或者其他簡單輕量的DB Helper庫了。在詳細瞭解ORM之後,你就可以揚長避短讓ORM發揮其最大效用了。

原文鏈接: http://www.fancycedar.info/2013/01/orm/

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>