# 性能優化
有許多因素影響你的 Web 應用程序的性能。有些是環境,有些是你的代碼,而其他一些與 Yii 本身有關。 在本節中,我們將列舉這些因素并解釋如何通過調整這些因素來提高應用程序的性能。
## 優化你的 PHP 環境
一個好的 PHP 環境是非常重要的。為了得到最大的性能,
* 使用最新穩定版本的 PHP 。 PHP 的主要版本可能帶來顯著的性能提升。
* 啟用字節碼緩存?[Opcache](http://php.net/opcache)(PHP 5.5或更高版本)或?[APC](http://ru2.php.net/apc)?(PHP 5.4或更早版本)。字節碼緩存省去了每次解析和加載 PHP 腳本所帶來的開銷。
## 禁用調試模式
對于運行在生產環境中的應用程序,你應該禁用調試模式。 Yii 中使用名為?`YII_DEBUG`?的常量來定義調試模式是否應被激活。 若啟用了調試模式,Yii 將需要額外的時間來產生和記錄調試信息。
你可以將下面的代碼行放在?[入口腳本](http://www.yiichina.com/doc/guide/2.0/structure-entry-scripts)?的開頭來禁用調試模式:
~~~
defined('YII_DEBUG') or define('YII_DEBUG', false);
~~~
> 提示:?`YII_DEBUG`?的默認值是 false 。所以如果你確信你不在你應用程序代碼中別的地方更改其默認值, 你可以簡單地刪除上述行來禁用調試模式。
## 使用緩存技術
你可以使用各種緩存技術來提高應用程序的性能。例如,如果你的應用程序允許用戶以 Markdown 格式輸入文字, 你可以考慮緩存解析后的 Markdown 內容,避免每個請求都重復解析相同的 Markdown 文本。 請參閱?[緩存](http://www.yiichina.com/doc/guide/2.0/caching-overview)?一節,了解 Yii 提供的緩存支持。
## 開啟 Schema 緩存
Schema 緩存是一個特殊的緩存功能,每當你使用[活動記錄](http://www.yiichina.com/doc/guide/2.0/db-active-record)時應該要開啟這個緩存功能。如你所知, 活動記錄能智能檢測數據庫對象的集合(例如列名、列類型、約束)而不需要手動地描述它們。活動記錄是通過執行額外的SQL查詢來獲得該信息。 通過啟用 Schema 緩存,檢索到的數據庫對象的集合將被保存在緩存中并在將來的請求中重用。
要開啟 Schema 緩存,需要配置一個?`cache`?[應用組件](http://www.yiichina.com/doc/guide/2.0/structure-application-components)來儲存 Schema 信息, 并在?[配置](http://www.yiichina.com/doc/guide/2.0/concept-configurations)?中設置 yii\db\Connection::enableSchemaCache 為?`true`?:
~~~
return [
// ...
'components' => [
// ...
'cache' => [
'class' => 'yii\caching\FileCache',
],
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=mydatabase',
'username' => 'root',
'password' => '',
'enableSchemaCache' => true,
// Duration of schema cache.
'schemaCacheDuration' => 3600,
// Name of the cache component used to store schema information
'schemaCache' => 'cache',
],
],
];
~~~
## 合并和壓縮資源文件
一個復雜的網頁往往包括許多 CSS 和 JavaScript 資源文件。為減少 HTTP 請求的數量和這些資源總下載的大小,應考慮將它們合并成一個單一的文件并壓縮。 這可大大提高頁面加載時間,且減少了服務器負載。想了解更多細節,請參閱[前端資源](http://www.yiichina.com/doc/guide/2.0/structure-assets)部分。
## 優化會話存儲
默認會話數據被存儲在文件中。這是好的對處于發展項目或小型項目。但是,當涉及要處理大量并發請求時,最好使用其他的會話存儲方式,比如數據庫。 Yii 支持各種會話存儲。你可以通過在[配置](http://www.yiichina.com/doc/guide/2.0/concept-configurations)中配置?`session`?組件來使用這些存儲,如下代碼:
~~~
return [
// ...
'components' => [
'session' => [
'class' => 'yii\web\DbSession',
// Set the following if you want to use DB component other than
// default 'db'.
// 'db' => 'mydb',
// To override default session table, set the following
// 'sessionTable' => 'my_session',
],
],
];
~~~
以上配置是使用數據庫來存儲會話數據。默認情況下,它會使用?`db`?應用組件連接數據庫并將會話數據存儲在?`session`?表。 因此,你必須創建如下的?`session`?表,
~~~
CREATE TABLE session (
id CHAR(40) NOT NULL PRIMARY KEY,
expire INTEGER,
data BLOB
)
~~~
你也可以通過使用緩存來存儲會話數據 yii\web\CacheSession 。理論上講,你可以使用只要支持[數據緩存](http://www.yiichina.com/doc/guide/2.0/caching-data#supported-cache-storage)。 但是請注意,某些緩存的存儲當達到存儲限制會清除緩存數據。出于這個原因,你應主要在不存在存儲限制時才使用這些緩存存儲。 如果你的服務器支持[Redis](http://redis.io/),強烈建議你通過使用 yii\redis\Session 來作為會話存儲。
## 優化數據庫
執行數據庫查詢并從數據庫中取出數據往往是一個 Web 應用程序主要的性能瓶頸。 盡管使用[數據緩存](http://www.yiichina.com/doc/guide/2.0/caching-data)技術可以緩解性能下降,但它并不完全解決這個問題。 當數據庫包含大量的數據且緩存數據是無效的,獲取最新的數據可能是最耗性能的假如在沒有適當地設計數據庫和查詢條件。
一般來說,提高數據庫查詢的性能是創建索引。例如,如果你需要找一個用戶表的“用戶名”,你應該為“用戶名”創建一個索引。 注意,盡管索引可以使選擇查詢的速度快得多,但它會減慢插入、更新和刪除的查詢。
對于復雜的數據庫查詢,建議你創建數據庫視圖來保存查詢分析和準備的時間。
最后,在“SELECT”中使用“LIMIT”查詢。這可以避免從數據庫中取出大量數據。
## 使用普通數組
盡管[活動記錄](http://www.yiichina.com/doc/guide/2.0/db-active-record)對象使用起來非常方便,但當你需要從數據庫中檢索大量數據時它的效率不如使用普通的數組。 在這種情況下,你可以考慮在使用活動記錄查詢數據時調用?`asArray()`?,使檢索到的數據被表示為數組而不是笨重的活動記錄對象。例如,
~~~
class PostController extends Controller
{
public function actionIndex()
{
$posts = Post::find()->limit(100)->asArray()->all();
return $this->render('index', ['posts' => $posts]);
}
}
~~~
在上述代碼中,$posts 將被表中的行填充形成數組。每一行是一個普通的數組。要訪問 第 i 行的?`title`?列,你可以使用表達式`$post[$i]['title']`?。
你也可以使用[DAO](http://www.yiichina.com/doc/guide/2.0/db-dao)以數組的方式來構建查詢和檢索數據。
## 優化 Composer 自動加載
因為 Composer 自動加載用于加載大多數第三方類文件,應考慮對其進行優化,通過執行以下命令:
~~~
composer dumpautoload -o
~~~
## 處理離線數據
當一個請求涉及到一些資源密集操作,你應該想辦法在無需用戶等待他們完成脫機模式時來執行這些操作。
有兩種方法可以離線數據處理:推和拉。
在拉中,只要有請求涉及到一些復雜的操作,你創建一個任務,并將其保存在永久存儲,例如數據庫。然后,使用一個單獨的進程(如 cron 作業)拉任務,并進行處理。 這種方法很容易實現,但它也有一些缺點。例如,該任務過程中需要定期地從任務存儲拉。如果拉頻率太低,這些任務可以延遲處理; 但是如果頻率過高,將引起的高開銷。
在推中,你可以使用消息隊列(如 RabbitMQ ,ActiveMQ , Amazon SQS 等)來管理任務。 每當一個新的任務放在隊列中,它會啟動或者通知任務處理過程去觸發任務處理。
## 性能分析
你應該配置你的代碼來找出性能缺陷,并相應地采取適當措施。 以下分析工具可能是有用的:
* [Yii debug toolbar and debugger](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md)
* [XDebug profiler](http://xdebug.org/docs/profiler)
* [XHProf](http://www.php.net/manual/en/book.xhprof.php)
- 介紹(Introduction)
- 關于 Yii(About Yii)
- 從 Yii 1.1 升級(Upgrading from Version 1.1)
- 入門(Getting Started)
- 安裝 Yii(Installing Yii)
- 運行應用(Running Applications)
- 第一次問候(Saying Hello)
- 使用 Forms(Working with Forms)
- 玩轉 Databases(Working with Databases)
- 用 Gii 生成代碼(Generating Code with Gii)
- 更上一層樓(Looking Ahead)
- 應用結構(Application Structure)
- 結構概述(Overview)
- 入口腳本(Entry Scripts)
- 應用(Applications)
- 應用組件(Application Components)
- 控制器(Controllers)
- 模型(Models)
- 視圖(Views)
- 模塊(Modules)
- 過濾器(Filters)
- 小部件(Widgets)
- 前端資源(Assets)
- 擴展(Extensions)
- 請求處理(Handling Requests)
- 運行概述(Overview)
- 引導(Bootstrapping)
- 路由引導與創建 URL(Routing and URL Creation)
- 請求(Requests)
- 響應(Responses)
- Sessions and Cookies
- 錯誤處理(Handling Errors)
- 日志(Logging)
- 關鍵概念(Key Concepts)
- 組件(Components)
- 屬性(Properties)
- 事件(Events)
- 行為(Behaviors)
- 配置(Configurations)
- 別名(Aliases)
- 類自動加載(Class Autoloading)
- 服務定位器(Service Locator)
- 依賴注入容器(Dependency Injection Container)
- 配合數據庫工作(Working with Databases)
- 數據庫訪問(Data Access Objects): 數據庫連接、基本查詢、事務和模式操作
- 查詢生成器(Query Builder): 使用簡單抽象層查詢數據庫
- 活動記錄(Active Record): 活動記錄對象關系映射(ORM),檢索和操作記錄、定義關聯關系
- 數據庫遷移(Migrations): 在團體開發中對你的數據庫使用版本控制
- Sphinx
- Redis
- MongoDB
- ElasticSearch
- 接收用戶數據(Getting Data from Users)
- 創建表單(Creating Forms)
- 輸入驗證(Validating Input)
- 文件上傳(Uploading Files)
- 收集列表輸入(Collecting Tabular Input)
- 多模型同時輸入(Getting Data for Multiple Models)
- 顯示數據(Displaying Data)
- 格式化輸出數據(Data Formatting)
- 分頁(Pagination)
- 排序(Sorting)
- 數據提供器(Data Providers)
- 數據小部件(Data Widgets)
- 操作客戶端腳本(Working with Client Scripts)
- 主題(Theming)
- 安全(Security)
- 認證(Authentication)
- 授權(Authorization)
- 處理密碼(Working with Passwords)
- 客戶端認證(Auth Clients)
- 安全領域的最佳實踐(Best Practices)
- 緩存(Caching)
- 概述(Overview)
- 數據緩存(Data Caching)
- 片段緩存(Fragment Caching)
- 分頁緩存(Page Caching)
- HTTP 緩存(HTTP Caching)
- RESTful Web 服務
- 快速入門(Quick Start)
- 資源(Resources)
- 控制器(Controllers)
- 路由(Routing)
- 格式化響應(Response Formatting)
- 授權驗證(Authentication)
- 速率限制(Rate Limiting)
- 版本化(Versioning)
- 錯誤處理(Error Handling)
- 開發工具(Development Tools)
- 調試工具欄和調試器(Debug Toolbar and Debugger)
- 使用 Gii 生成代碼(Generating Code using Gii)
- TBD 生成 API 文檔(Generating API Documentation)
- 測試(Testing)
- 概述(Overview)
- 搭建測試環境(Testing environment setup)
- 單元測試(Unit Tests)
- 功能測試(Functional Tests)
- 驗收測試(Acceptance Tests)
- 測試夾具(Fixtures)
- 高級專題(Special Topics)
- 高級應用模版(Advanced Project Template)
- 從頭構建自定義模版(Building Application from Scratch)
- 控制臺命令(Console Commands)
- 核心驗證器(Core Validators)
- 國際化(Internationalization)
- 收發郵件(Mailing)
- 性能優化(Performance Tuning)
- 共享主機環境(Shared Hosting Environment)
- 模板引擎(Template Engines)
- 集成第三方代碼(Working with Third-Party Code)
- 小部件(Widgets)
- Bootstrap 小部件(Bootstrap Widgets)
- jQuery UI 小部件(jQuery UI Widgets)
- 助手類(Helpers)
- 助手一覽(Overview)
- Array 助手(ArrayHelper)
- Html 助手(Html)
- Url 助手(Url)