此文首發在 InfoQ 中文站。
作者:明靈(dragon) , Fenng . Note:要轉載的朋友請注意註明這篇文章的第一作者!
這篇文章是dragon 朋友來郵探討後他做的一個總結。在 DB 中排序還是在 應用程式中排序是個很有趣的話題,dragon 第一份郵件中其實已經總結的很好了,我添加了一點建議而已。現在放上來,與大家共用。這篇文章也投稿到了 InfoQ 中文站 。
Q:列出在 PHP 中執行排序要優於在 MYSQL 中排序的原因?給一些必須在MYSQL中排序的執行個體?
A:通常來說,執行效率需要考慮 CPU、記憶體和硬碟等的負載情況,假定 MYSQL 伺服器和 PHP 的伺服器都已經按照最適合的方式來配置,那麼系統的延展性(Scalability)和使用者感知效能(User-perceived Performance)是我們追求的主要目標。在實際運行中,MYSQL 中資料往往以 HASH tables、BTREE 等方式存貯於記憶體,操作速度很快;同時 INDEX 已經進行了一些預排序;很多應用中,MYSQL 排序是首選。而在應用程式層(PHP)中排序,也必然在記憶體中進行,與 MYSQL 相比具有如下優勢:
- 1、 考慮整個網站的延展性和整體效能,在應用程式層(PHP)中排序明顯會降低資料庫的負載,從而提升整個網站的擴充能力。而資料庫的排序,實際上成本是非常高的,消耗記憶體、CPU,如果並發的排序很多,DB 很容易到瓶頸。
- 2、 如果在應用程式層(PHP)和MYSQL之間還存在資料中介層,合理利用,PHP會有更好的收益。
- 3、 PHP在記憶體中的資料結構專門針對具體應用來設計,比資料庫更為簡潔、高效;
- 4、 PHP不用考慮資料災難恢複問題,可以減少這部分的操作損耗;
- 5、 PHP不存在表的鎖定問題;
- 6、 MYSQL中排序,請求和結果返回還需要通過網路連接來進行,而PHP中排序之後就可以直接返回了,減少了網路IO。
至於執行速度,差異應該不會很大,除非應用設計有問題,造成大量不必要的網路IO。另外,應用程式層要注意PHP 的 Cache 設定,如果超出會報告內部錯誤;此時要根據應用做好評估,或者調整Cache。具體選擇,將取決於具體的應用。
列出一些 PHP 中執行排序更優的情況:
- 1、 資料來源不在 MYSQL 中,存在硬碟、記憶體或者來自網路的請求等;
- 2、 資料存在 MYSQL 中,量不大,而且沒有相應的索引,此時把資料取出來用PHP排序更快;
- 3、 資料來源來自於多個 MYSQL 伺服器,此時從多個 MYSQL 中取出資料,然後在PHP中排序更快;
- 4、 除了 MYSQL 之外,存在其他資料來源,比如硬碟、記憶體或者來自網路的請求等,此時不適合把這些資料存入 MYSQL 後再排序;
列出一些必須在 MYSQL 中排序的執行個體:
- 1、 MYSQL 中已經存在這個排序的索引;
- 2、 MYSQL 中資料量較大,而結果集需要其中很小的一個子集;比如 1000000 行資料,取TOP 10;
- 3、 對於一次排序、多次調用的情況,比如統計彙總的情形,可以提供給不同的服務使用,那麼在 MYSQL 中排序是首選的。另外,對於資料深度挖掘,通常做法是在應用程式層做完排序等複雜操作,把結果存入MYSQL即可,便於多次使用。
- 4、 不論資料來源來自哪裡,當資料量大到一定的規模後,由於佔用記憶體/Cache 的關係,不再適合 PHP 中排序了;此時把資料複製、匯入或者存在 MYSQL ,並用 INDEX 最佳化,是優於 PHP 的。不過,用 Java,甚至 C++ 來處理這類操作會更好。 [有些類似大資料集彙總或者匯總的資料,在用戶端排序得不償失。當然,也有用類似搜尋引擎的思路來解決類似應用的情況。]
從網站整體考慮,就必須加入人力和成本的考慮。假如網站規模和負載較小,而人力有限(人數和能力都可能有限),此時在應用程式層(PHP)做排序要做不 少開發和調試工作,耗費時間,得不償失;不如在 DB 中處理,簡單快速。對於大規模的網站,電力、伺服器的費用很高,在系統架構上精打細算,可以節約大量的費用,是公司持續發展之必要;此時如果能在應用程式層(PHP) 進行排序並滿足業務需求,盡量在應用程式層進行。