標籤:

你會在框架中用到orm嗎?

平時在php用框架開發項目的時候?寫sql語句的時候?你會用到原生sql還是用到框架的orm?原因是什麼?


我歪個樓

http://www.linkedin.com/pulse/how-hibernate-almost-ruined-my-career-kishan-kumar


其實我是特別建議用原生sql的。因為每個框架的orm語法不同,所以特別麻煩。再說了orm最後不還得解析成sql語句,效率比原生sql低了不少。

我覺得orm唯一的優勢就是提升了代碼的可維護性,僅此而已。


PHP中使用"PDO+SQL+關聯數組"要比"ORM+對象"更加簡單高效.PDO統一資料庫操作介面,SQL能夠最直接地表達資料庫邏輯,PHP關聯數組無縫對接查詢結果.框架是魔鬼.

ORM沒有黑科技,底層照樣使用PDO的這套方案防止SQL注入,我並不覺得PDO的寫法有什麼麻煩.像一些資料庫獨有的非標準的SQL,如全文檢索MySQL是MATCH(`content`) AGAINST(? IN BOOLEAN MODE),SQLite則是`content` MATCH ?,又比如MySQL支持SELECT FOR UPDATE的寫法,而SQLite又不支持,又比如MySQL可以用SHOW TABLE STATUS FROM `mydb` LIKE "mytable"查看錶信息,拿到表大概的行數,而SQLite並不支持這種方法,這時"高大上"的ORM還不是得去執行原始SQL.ORM的通用是建立在PDO和SQL通用的基礎上的,不要本末倒置.不同PHP框架的ORM各不相同,所以真要說通用性,PDO+SQL反而比各種ORM更通用.更不要為了對象而對象,萬物不一定都是對象,別被面向對象洗腦了.

&prepare($sql);
$stmt-&>execute($params);

// SELECT
return $stmt-&>fetchAll(PDO::FETCH_ASSOC);

// INSERT/UPDATE/DELETE
return ($stmt-&>rowCount() === 0) ? false : true;

// INSERT(表中包含自增欄位,插入一條記錄時)
return ($stmt-&>rowCount() === 0) ? false : $db-&>lastInsertId();
}


我覺得還是用原生比較好。

第一個問題就是,一直說換庫,換庫。你跟我說說,你用了mysql之後,你到底換過庫么。

第二個問題就是,你見過ORM生成的SQL是什麼樣子的么。有的ORM比如實現軟刪除是怎麼實現的,至少我看到Laravel的是使用`is_null("deleted_at")`來判斷的,光是這樣,我覺得就該正確的對待ORM了。

我不否認laravel是個非常棒的框架,並且我也在公司中在跟同事安利這個框架。但是不可否認,我們都應該正確的看待ORM,冷靜分析。到底我是不是非用ORM不可了。


看你,畢竟我習慣把聯表這種行為分成多個單表查詢。。。這樣可以做資料庫緩存

所以我面向用戶端的項目用的都是這種單表,單表查詢就可以用orm來的簡單

公司人員用的後台,各種統計查詢比較複雜,習慣用原生

畢竟mysql原生統計扯上統計,一般用聯表,可以練練自己的explain水平..


ORM 或者 PDO 或者 自己封裝個MODEL類 不過也和PDO差不多吧……

只不過實現方式 可能沒有 框架的ORM 那麼成熟……

當然也有維護老工程 / DISCUZ 之類的時候 直接上SQL……

其實我都好久沒有接觸資料庫了- -


從DBA的角度來看,O跟R建模方法都不一樣,根本沒法完美映射的。


直接寫的確SQL簡單快捷,PDO封裝了各個資料庫的API,抽象了DBMS調用層面的內容,但是SQL在不同的資料庫間是存在差異的,更不用說各式NoSql。一定規模下開發效率上ORM也不一定比寫SQL高。如果業務需求要更換數據載體,或者實施分庫分表,甚至分散式存儲,那麼你可能面臨的是修改所有的SQL甚至重寫數據訪問層的代碼,甚至可能需要動業務層的代碼。ORM的意義在於抽象數據的存取,是在PDO更上層的東西,本身並不衝突,它使開發人員本身不需要關注下面是mysql、mssql還是mongodb。

PHP數組沒有額外開銷,數組很強大,數組最大的問題是它強大而且非常的自由。如果項目規模足夠大,多人開發的場景中,使用數組會增加開發難度,類尚且通過IDE工具方便有效的查看定義,不溝通不查文檔不翻代碼,誰知道返回的數組裡面有什麼東西,除此之外。還有大小寫問題,取值的規範需要額外的解決等。foreach不只是配合數組,不要忘記Itearator。如果一個程序員連排序都解決不好,沒什麼必要談什麼「性能」。

在團隊只有幾個人的情況下,溝通成本較低,代碼規範和代碼質量是可以比較好的控制的,但是當項目和團隊規模發展到十幾人甚至幾十人的時候,人員整體素質的下降,管理難度提高是不可避免的,只要一個不恰當的查詢,破壞性是極其強大的。有技術能力控制質量的人不可能也不應該花大量時間去做QC和Review的工作。規範化的工作交給設計和編碼層面是更有效率的做法。

所以ORM的「開發效率」是有一定前瞻性的,項目和團隊在一定規模下可能並不能體現其優勢,甚至更麻煩。即使當初沒有用ORM,團隊、項目經過這樣一番折騰後,自己也會發展出一套抽象數據存儲,解決規範問題的東東。

關於「性能」的討論,很多時候做設計的時候會考慮性能,理論上每抽象一層都需要付出一定的性能代價。對於PHP,多一個類可能意味著多一次磁碟IO,多耗CPU時間去解析一個PHP文件,多消費一點內存。

但你是否有考慮過為什麼PHP要做opcache、JIT,加上這些特性之後多幾個文件的開銷是不是就變得能接受了,官方是不是在支持PHP往這些方向去發展?確實對於性能有錙銖必較的要求,是不是更換技術更適合?在那些必要的網路IO面前,付出的那一點效率損耗的影響到底有多大?在日新月異的基礎技術和工具、日漸低廉的硬體成本面前,那一點效率的付出是否可以在其他方面抹平?換一個資料庫,一個程序員修改所有數據訪問層的SQL需要多久?期間工資多少?團隊每天花五分鐘反覆溝通同類問題,一年下來消耗時間折算成工資是多少?加一台VPS一年多少錢?加內存,換SSD,升級CPU成本是多少?這都是可以量化和討論的。

大部分的框架都不是「太陽能手電筒」、「挪你命3000」,它們的出現都是從解決實際問題之後提煉出來的,你的項目里用不到並不代表它們一文不值,可能是技術條件或者項目、團隊規模的原因還未有發掘到相關的需求。也可能你有更合適的解決方案。

框架不是魔鬼,自負才是。

對於原問題的回答:如果你能夠發現/預見項目發展遇到的問題,又恰好有現成的框架能有效解決且代價合適,那就用。我們的項目沒有用開源的ORM框架,但是自己也發展出一套解決方案,其實跟ORM是殊途同歸。


這個問題不只是PHP 適用的,JAVA、Python 等語言都適用。

實際上這個問題可以理解為ORM和 原生SQL哪個好的問題。

分為從軟體開發團隊角度和性能角度說

軟體開發團隊角度

簡單易懂

ORM 如 laravel, doctrine 的確有很多好的功能,它們使資料庫層抽象出來使得它們能很好的處理不同的資料庫類型和SQL 語言之間的差別。使得軟體開發人員專註他們的問題而不是資料庫。ORM 是將表映射到每個類中,很符合程序員的編程習慣。

學習成本低

程序員可以減少了對資料庫的學習投入。寫著面向對象 的 ORM倒是很符合很多不想深究資料庫的程序員,看起來也簡單。

開發成本低

在大的團隊找到精通資料庫優化和網頁開發的優秀程序員太少了。性能降了可以買伺服器硬體。和程序員所付的工資比,當然是多買幾塊CPU 容易了,公司花費最少。還有一點, 大大縮短了程序員的編碼時間。

代碼的統一也降低了項目溝通的成本。

動態的數據表映射,在數據表結構甚至資料庫發生改變時,減少了相應的代碼修改。

避免Bug

ORM避免了很多不規範,不好的SQL語句寫法,減少了引入Bug 的幾率。

一定程度的優化

對於開發來說,如果網頁程序側重於(發送請求和取出對象和遍歷對象得到數據等)一個個事務(transaction)的話,在很多情況下,ORM 是可以提高訪問速度的,因為它可以緩存經常訪問的對象,所以你不需要經常去訪問資料庫,而是訪問ORM層。

性能的角度

我猜測在這裡的大多數都是網頁工程師而非資料庫工程師。

性能測試最好用一些基準測試資料庫來說明性能。ORM 性能的確很差,ORM 的確很傻也很笨,無法生成高質量的SQL語句,所以ORM 不適合互聯網和海量數據的開發( 大數據量、大運算量、複雜查詢 ),但是一般的企業ERP 系統 和 網頁用著是沒什麼問題。題外話,如果PHP有python SQLAlchemy 那麼好的ORM的話,上述的多數性能問題是沒有的。

人可以根據關係代數和執行計劃來修改SQL 語句,而ORM 是不行的。所以ORM 的SQL執行計劃 經常執行的是全表掃描。

而且資料庫的各種優化的SQL寫法 像使用 index hints 在ORM沒有一點用武之地。

如下就是 一些使用hint 的MYSQL語句,ORM很難做到這一點。

SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1
FROM t3 WHERE f1 &> 30 AND f1 &< 33; SELECT /*+ BKA(t1) NO_BKA(t2) */ * FROM t1 INNER JOIN t2 WHERE ...; SELECT /*+ NO_ICP(t1, t2) */ * FROM t1 INNER JOIN t2 WHERE ...; SELECT /*+ SEMIJOIN(FIRSTMATCH, LOOSESCAN) */ * FROM t1 ...; EXPLAIN SELECT /*+ NO_ICP(t1) */ * FROM t1 WHERE ...;

其中 /*+ ... */ 就是query Optimizer Hints, SQL 在資料庫中解析時我們是可以使用hint 來避免性能的問題。因為資料庫對每個SQL有很多種不同的執行方式 ,但我們強制資料庫使用最好的方式。具體可以查看SQL 語義分析生成樹。

另一點

越是功能強大的ORM越是消耗內存,因為一個ORM Object會帶有很多成員變數和成員函數。

最後總結:

對於任何大規模開發來說,ORM和原生SQL都是要用到的。 ORM要用!但關鍵部位不能用!

有興趣的話,可以看看stakeoverflow 上關於這個問題的兩個回答。

ORM vs traditional database query, which are their fields?

Using an ORM or plain SQL?


任何想法都要和實際需求要聯繫起來 再原生也得需要封裝一下使用

以上


orm中使用querybuilder可以屏蔽不同驅動帶來的sql差異,意味著換庫sql不需要重寫。

將record映射為object是orm最本職的工作:用操作對象的方式操作結果集。

性能和對複雜sql的支持相對來講應該算orm需要解決的問題吧。

不過就像大家說的,性能也不是它的出發點,不過這一點在php里有所不同,php畢竟是一鎚子買賣,orm或多或少有點失去了它的意義,這一點上依賴注入容器也是一樣的情況…

很多join大多數情況下是程序員偷懶,不願意foreach+array_unique+sql in+cache get的方式代替,這點部分orm倒是可以透明實現,不過說句公道話,確實存在業務性強時某些複雜sql必不可少的情況。

所以對於我個人來講,php我不會用orm,甚至不會用activerecord,寫sql多爽,適合的人用在適合的崗位,適合的語言用在適合的場景,快就要發揮它快的優勢,軟體工程這類東西用在php上還是得掂量掂量酌情考慮。

php就該連mysql,等你考慮換庫時便是php被java重構之時。


ORM適合業務複雜,用戶訪問量少的系統,比如企業內部的ERP系統,可能客戶端的一個請求觸發資料庫中幾十個表之間的查詢修改,不適合互聯網系統。


不用任何框架,皆原生


推薦閱讀:

求助。php無限極分類。遞歸。怎麼數出來。每一個分類下面的小分類個數啊。希望有個demo?謝謝!?
怎樣深入學習php,成為php高手?

TAG:PHP | SQL |