### 2018 年 11 月 18 日 發布
說到應用性能,涉及到的方方面面實在是太多了,關于服務器優化和前端優化的文章網上很多,所以就不再累述了。本文僅拋磚引玉淺述下ThinkPHP`5.1`應用開發中(尤其是部署環境)可能涉及的一些性能優化手段和注意事項。
>[danger] 首先要強調一點:框架并不是應用性能的瓶頸,架構設計、數據庫和人才是。框架在設計之初,出于通用性考慮,不會特意針對某個應用做深入優化,但提供了一些可能的手段和配置參數讓你進行針對性的調優,下面就列舉一些可能的優化手段,在開發的時候可以根據情況調整。
正確的性能優化步驟應該是:架構優化、數據庫優化、代碼優化。
## 架構優化
架構優化涉及到技術、存儲、網絡、服務的選型和構架,盡量使用成熟和現代的開發架構和設計模式。前后端完全分離設計,便于前后端的獨立優化,也更加便于測試工作。
如果你的應用遇到了性能瓶頸,這個時候要考慮的就是優化架構而不是優化代碼本身,因為架構層面的優化效果往往是最顯著的。
>[info] 架構的優化需要根據自身運營情況來調整,切忌不可按圖索驥提前優化,反而容易得不償失,導致技術成本提高甚至“負優化”。
## 關閉調試模式
部署環境千萬不要忘記關閉調試模式,這不僅僅是出于性能考慮,更多是基于安全因素。事實上,建議通過環境變量來配置關閉調試模式,這樣部署后不需要更改任何配置文件。
因為調試模式影響日志記錄信息、額外的調試信息和緩存失效,關閉調試模式能夠帶來一定的性能提升。
## 使用單模塊
使用多模塊功能會增加文件的`I/O`開銷和額外的配置及檢查,如非必要在規劃你的應用架構的時候盡量考慮使用單一模塊,然后使用控制器分級來解決控制器過多的問題。
使用單一模塊的性能優勢,在部署到`swoole`的時候可以得到更加充分的體現,因為應用文件一旦啟動服務,就會載入內存,而模塊的相關文件則會每次請求重新加載。
## 路由設計及優化
在定義路由規則的時候,不要使用數組方式,盡量使用方法注冊路由,并且多使用路由分組(或者資源路由)。分組路由可以減少路由的匹配次數,從而提升路由性能。如果你有多個域名的不同路由,也要按域名規劃使用路由。
盡可能設計在路由中進行當前路由的數據驗證和權限檢查等操作,一方面比較清晰,另外一方面可以盡量把驗證操作提前,而不必等到控制器執行。
在分組比較多的情況下,開啟路由的延遲解析。
```
// 開啟路由延遲解析
'url_lazy_route' => true,
```
如果同一個分組下面有比較多的路由規則,建議合并路由規則。
```
// 合并分組路由規則
'route_rule_merge' => true,
```
對于`GET`請求的路由,可以設置路由的請求緩存。
```
// 定義GET請求路由規則 并設置3600秒的緩存
Route::get('new/:id','News/read')->cache(3600);
```
部署階段,可以開啟路由緩存。
```
// 開啟路由緩存(僅部署模式有效)
'route_check_cache' => true,
```
## 查詢優化
首先保持良好的開發習慣,了解[Db類和模型的正確使用姿勢](https://blog.thinkphp.cn/810719),數據庫本身的性能優化可以參考[MySQL性能優化的最佳21條經驗](http://www.thinkphp.cn/topic/54536.html),下面主要是對框架中數據查詢相關的優化策略。
### 合理使用查詢緩存
盡量減少每次請求的查詢次數,并對實時性要求不高的數據查詢合理規劃數據查詢緩存(優先考慮使用`Redis`緩存)。
```
Blog::where('id', 10)
->cache(30)
->find();
```
如果使用了關聯查詢,`cache`方法只能用于主模型的數據緩存,但你可以使用`Cache`類的`remember`方法進行方便的數據緩存。
```
$users = Cache::remember('users', function(){
return User::with('profile')
->where('status', 1)
->select();
},30);
```
### 不要過于糾結查詢次數
盡量減少查詢次數是出于性能考慮,但不是必須,使用最少的查詢不代表性能就一定是最高。一個復雜的`JOIN`查詢性能不見得有兩次簡單的查詢高,而使用簡單的查詢反而更清晰易懂,并且更方便進行數據查詢緩存。
### 正確使用模型關聯
不要總是以為模型的性能一定比`Db`類低,框架的ORM查詢設計經過了較為合理的優化,正確使用模型一樣可以有出色的性能,而且比`Db`查詢要方便很多。
尤其是對于一些復雜的設計來說使用模型關聯顯得比直接用Db更加簡單,例如使用關聯預載入查詢就可以避免`N+1`查詢問題。
```
User::with(['profile','book'])->select();
```
如果用`Db`類自己實現的話,費時費力,性能還不一定優。
### 大量數據處理優化
對于大量數據的處理操作,使用`chunk`分批處理方法。
```
User::chunk(100, function($users) {
foreach ($users as $user) {
// 處理數據
}
});
```
對于內存開銷比較大的應用,在做大量數據查詢和處理的時候,使用`cursor`方法,可以利用PHP的生成器特性,減少內存占用。
```
$cursor = User::cursor();
foreach($cursor as $user){
// 處理數據
}
```
你會發現用戶數據不論是1萬還是10萬級別,內存開銷并沒有大的變化。
>[danger] 涉及到對大量數據的處理,包括數據遷移、批量更新,盡量使用命令行指令運行,否則會因為超時而中斷。
### 善用數據集方法避免多次查詢
可以通過數據集的方法完成的子集或者排序操作不要再次查詢,例如:
```
// 模型查詢返回數據集對象
$users = User::select();
// 按照用戶的成績由高到低排序
$list1 = $users->order('score', 'desc');
// 篩選成績在90分以上的用戶
$list2 = $users->where('score', '>=', 90);
```
### 字段緩存
利用下面指令在部署后生成字段緩存,可以減少每次數據表的字段查詢開銷。
```
php think optimize:schema
```
更多用法可以參考官方手冊的[數據字段緩存](http://www.hmoore.net/manual/thinkphp5_1/354145)。
>[danger] 注意:一旦數據庫的表結構發生變化,必須重新生成。
## 配置和公共文件緩存
每次在應用初始化或者模塊初始化的時候會有一定的`I/O`開銷,如果已經開啟`OpCache`的話對性能影響甚微,如果比較在意的也可以通過命令行指令生成配置緩存(包括相關的公共文件和各種定義文件)。
生成應用配置緩存:
```
php think optimize:config
```
生成模塊配置緩存:
```
php think optimize:config index
```
>[danger] 注意:一旦配置或者公共文件發生變化,必須重新生成。
## 生成類庫映射
類庫映射可以提升類庫的自動加載性能,使用下面的指令可以生成系統類庫和應用類庫的類庫映射(包括`extend`目錄下的類庫)。
```
php think optimize:autoload
```
`vendor`目錄下的類庫可以使用`composer`的`dump-autoload`指令優化加載性能。
```
composer dump-autoload -o
```
該命令把 `PSR-0` 和 `PSR-4` 轉換為一個類映射表,來提高類的加載速度。
- 值得升級到5.1的18個理由
- 5.1.7版本新特性
- JSON字段類型在ORM中的使用
- 文件下載響應對象
- 教你使用5.1的數組對象查詢
- 模型三大利器之一:搜索器
- 在ThinkPHP中使用Yaconf
- 掌握命令行的表格輸出
- 5.1.25查詢參數綁定的改進
- ThinkPHP安全規范指引
- 巧用數據集的排序功能實現統計排序
- think-orm ——基于5.1的獨立ORM庫
- think-template——基于ThinkPHP的獨立模板引擎
- ThinkPHP5.1.26版本發布——修正版本,包含安全更新
- ThinkPHP5.0和3.2再發安全更新
- 官宣:ThinkPHP發布首個LTS版本
- 你真的了解Db類和模型的正確使用姿勢么?
- 如何更有效的記錄和管理日志
- 模型三大利器之二:修改器
- ThinkPHP5.1.28版本發布——修正上一版本問題,改進關聯查詢
- 模型三大利器之三:獲取器
- API版本控制的幾種思路
- ThinkPHP5.2第一個Beta版本發布測試
- 讓你少犯錯的數據查詢基本原則
- ThinkPHP發布5.1.29版本——常規更新
- 這15個好習慣讓你更容易升級到5.2
- 如何有效提高ThinkPHP的應用性能
- 讓你提高開發效率的查詢技巧
- 模型關聯查詢不完全指南
- 5.2發布Beta2版本——統一和精簡大量用法
- ThinkPHP發布5.1.30版本——支持微秒時間字段寫入
- ThinkPHP的數據緩存使用
- ThinkPHP5.2安裝及入口文件
- ThinkPHP榮獲2018 年度最受歡迎中國開源開發框架第1名
- 5.1路由使用心得技巧
- ThinkPHP5.*版本發布安全更新
- ThinkPHP項目及代碼規范指北
- 5.2版本的設計規范指導
- ThinkPHP5.1.32版本發布——圣誕快樂
- 利用Trait特性給模型增加樂觀鎖功能
- 5.2數據庫和模型的變化(摘要)
- ThinkPHP模板引擎實現和常見問題
- ThinkPHP5.0.24版本發布——安全更新
- 不忘初心,方得始終——ThinkPHP十三周年報告
- ThinkPHP5+相關資源匯總
- 異步社區ThinkPHP周年慶專享優惠活動
- 5.2路由的調整和改進
- ThinkPHP發布5.1.33版本——包含安全更新
- ThinkPHP擴展開發指南
- ThinkPHP發布5.2Beta3版本
- ThinkPHP發布5.1.34版本——喜迎新年
- ThinkPHP發布5.2RC1版本
- ThinkPHP發布5.1.35版本——常規更新
- 5.2配置類的調整
- 5.2時間查詢的改進和優化
- 5.2RC版本升級不完全指導(僅供學習參考)
- ThinkPHP5.2版本正式變更為6.0版本
- ThinkPHP百度云云虛擬主機專享免費活動
- 事件系統以及查詢事件、模型事件的使用
- ThinkPHP6.0RC2版本發布——架構升級、精簡核心
- ThinkPHP5.1.36LTS版本發布——常規更新
- 新版Session和Cookie設計變化
- ThinkPHP5.1.37版本發布——常規更新
- ThinkPHP6.0RC3版本發布——細節完善,體驗優化
- 6.0中間件使用詳解
- Composer各大廠商鏡像地址
- ThinkPHP6.0發布計劃公告
- 「ThinkPHP開發者周刊」招募志愿者
- ThinkPHP6.0日志變化
- ThinkPHP5.1.38版本發布——常規更新
- ThinkPHP6.0RC4版本發布——ORM獨立,日志多通道支持
- ThinkORM2.0開發指南上線
- ThinkPHP6.0RC5版本發布——多應用模式獨立,中間件機制調整
- ThinkPHP6.0版本發布——程序員節福利
- ThinkPHP5.1.39LTS版本發布——常規更新
- ThinkPHP6.0.1版本發布——圣誕快樂!
- 回顧2019,展望2020!
- ThinkPHPV6.0.2版本發布——2020新春快樂!
- 周年福利系列:Swoole合作優惠
- 億速云成為ThinkPHPV6.0獨家贊助發布商??
- 新冠疫情工具和限免資源專題(保持更新中)
- 周年福利系列:創宇信用認證合作優惠
- 周年福利系列:碼云企業版限時10%優惠
- 周年福利系列:想天短說抵現優惠
- think-swoole直播:從零開始掌握swoole開發
- 周年福利系列:B2C開源電商ShopXO授權8折優惠
- 周年福利系列:LayuiAdmin 永久授權限時優惠
- ThinkPHP資源導航站上線——構建生態 服務未來
- ThinkPHP官方技術支持服務和應用服務市場上線公測
- ThinkPHP市場精選——推廣基本要素
- ThinkPHP市場精選——客服聊天專題
- ThinkPHPV6.0.3版本發布——端午安康
- ThinkPHP開發者扶持計劃
- 6.0.3版本關鍵更新及升級事項
- 「ThinkPHP開發者周刊」改版重啟
- ThinkPHP市場精選——企業建站專題
- ThinkPHP 提供統一API接口服務
- ThinkPHP市場精選——直播電商專題
- ThinkAPI服務SDK發布
- 官方服務市場啟用獨立子域名
- ThinkPHP市場精選——刷臉支付專題
- ThinkAPI推出會員服務計劃
- ThinkPHPV6.0.4版本發布——中秋國慶雙節快樂
- ThinkPHPV5.1.40版本發布——常規更新
- 1024程序員節福利走一波
- ThinkPHP V6.0.5版本發布——兼容Composer2.0
- 知識圖譜應用場景——源論技術沙龍
- ThinkPHP5.*版本改進Composer2.0的兼容
- 官方市場雙十一精選推薦
- 技術人做產品有機會么(文末送課程)
- 本周秒殺——古德云售后獲客營銷系統
- ThinkAPI服務更新——支持接口分組和PHP版本依賴調整
- PHP8新特性盤點
- PHP8新特性系列:構造器屬性提升使用及注意事項
- ThinkPHP2021新年寄語
- ThinkPHP V6.0.6&V5.1.41版本發布——兼容PHP8.0
- PHP如何更優雅地調用API接口
- ThinkPHP V6.0.7發布——修正版本
- ThinkAPI服務更新——IP白名單
- 最新版ThinkORM對于時間字段的調整
- ThinkAPI短信接口正式上線
- ThinkPHP V6.0.8版本發布——多環境變量配置支持
- 頂想云寫作服務開啟第一次公測
- ThinkSSL上線——官方SSL/TLS證書服務
- MDBootstrap國內用戶福利——ThinkPHP官方市場首發
- ThinkPHP V6.0.9版本發布——常規更新
- ThinkORM功能盤點——虛擬模型
- 全面支持主流GIT版本庫——云寫作服務第二次公測
- 云寫作服務私有化部署方案之:版本庫私有化
- 看云雙十一活動
- ThinkPHP V6.0.10LTS發布——兼容PHP8.1
- ThinkPHP V6.0.12發布——命令行兼容8.1
- 頂想云知識管理上線公測——構建企業文檔中心和知識庫
- 頂想云上線——助力生態數字化建設
- 618活動進行中——官方市場迎來一波更新
- 頂想云知識管理正式上線——看云文檔啟動遷移服務
- ThinkPHP V6.0.13發布——常規更新
- 頂想云網站助理服務上線——構建產品支持服務
- ThinkPHP發布6.1.0&6.0.14版本——安全更新
- ThinkPHP新版社區上線試運營
- ThinkAPI上架人臉核身接口——助力網站實名認證
- 辭舊迎新——舊版社區停止注冊及發帖
- ThinkPHP6.1.2版本發布——兼容PHP8.2