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