首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 效能優化實戰總結:15 個提升執行速度的關鍵技巧

     編輯:PHP 綜合知識

前言:效能是體驗的基石

PHP 解釋執行特性決定了程式碼層面的優化空間巨大。本文整理 15 個實戰驗證的優化技巧,涵蓋變數處理、迴圈判斷、資料庫查詢、輸出緩衝、檔案操作等核心場景。

1. 函式傳回陣列:return 優於 global

<?php
// ✅ 推薦:return 回傳,區域變數,無副作用
function parseUser($str) {
    return explode('|', $str);
}
$user = parseUser($raw);

// ❌ 不推薦:global 污染全域命名空間,難除錯
function parseUserGlobal($str) {
    global $detail;
    $detail = explode('|', $str);
}
parseUserGlobal($raw);
$user = $detail;
?>

原因: global 破壞封裝,增加耦合,JIT 編譯器難以優化。

2. 取得專案基礎 URL:REQUEST_URI 優於 HTTP_REFERER

<?php
// ✅ 穩定、快速、不依賴客戶端 Header
$parts = explode('/', $_SERVER['REQUEST_URI']);
array_pop($parts);
$baseUrl = 'https://' . $_SERVER['HTTP_HOST'] . implode('/', $parts);

// ❌ HTTP_REFERER 可被偽造、瀏覽器可能不送、HTTPS→HTTP 會丟失
$refParts = explode('/', $_SERVER['HTTP_REFERER']);
array_pop($refParts);
$baseUrl = implode('/', $refParts);
?>

3. 嚴格比較 === 優於 ==

<?php
$a = 2; $b = '2';
// ❌ 型別轉換開銷
if ($a == $b) { ... }

// ✅ 直接比較型別與值,效能略高且邏輯更嚴謹
if ($a === $b) { ... } // false
if ((int)$a === (int)$b) { ... } // true,明確轉型
?>

註:現代 PHP (7.4+) 差異微小,但 === 避免隱性轉型 Bug,建議作為預設習慣。

4. MySQL 查詢:WHERE IN 替代深分頁 LIMIT offset, n

<?php
// ❌ 深分頁效能指數級下降
// SELECT * FROM logs ORDER BY id DESC LIMIT 1000000, 20;

// ✅ 使用 ID 範圍查詢(需連續或近似連續 ID)
$lastId = 1000000; // 上一頁最大 ID
$stmt = $pdo->prepare("SELECT * FROM logs WHERE id < ? ORDER BY id DESC LIMIT 20");
$stmt->execute([$lastId]);

// ✅ 或使用 WHERE IN 查詢已知 ID 列表(如從 Redis 取得熱門 ID)
$ids = [1001, 1005, 1010, 1020];
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $pdo->prepare("SELECT * FROM logs WHERE id IN ($placeholders)");
$stmt->execute($ids);
?>

原理: LIMIT offset, n 需掃描前 offset 行;WHERE id < last_id 可直接利用索引定位。

5. 作業系統選擇:Linux/Unix 優於 Windows (NT)

PHP 進程模型、檔案系統、記憶體管理在 Linux 下更穩定高效。生產環境**強制使用 Linux**。

6. 輸出緩衝:ob_start() 加速輸出,ob_gzhandler 更強

<?php
// ✅ 開啟輸出緩衝,減少網路封包碎片
ob_start();

// ✅ 進階:啟用 GZIP 壓縮傳輸(需 zlib 擴展)
ob_start('ob_gzhandler');

echo "大量 HTML 內容...";
// 腳本結束自動 flush
?>

效果: 減少 TCP 封包數量,降低頻寬,提升首字節時間 (TTFB)。

7. 判斷寫法:if ($var) 與 if (empty($var)) 最快

<?php
// ✅ 直接判斷真假值,內部優化最好
if ($online) { ... }
if (empty($data)) { ... }

// ❌ 顯式比較較慢
if ($online == true) { ... }
if ($data == '') { ... }
if ($data === '') { ... }
?>

8. 不等比較:!= 與 <> 效能相當

選擇團隊風格統一即可,推薦 != 可讀性較佳。

9. 字串定界:單引號 '...' 與雙引號 "..." 現代 PHP 差異極小

舊版本單引號不解析變數略快,PHP 7+ 優化後差異可忽略。**統一風格**較重要(推薦單引號,雙引號僅用於需插值處)。

10. 規範 SQL:利於解析器優化

  • 大寫關鍵字:SELECT, FROM, WHERE
  • 避免 SELECT *,明確列出欄位
  • 使用參數化查詢(預處理語句可快取執行計畫)
  • 適當加索引,EXPLAIN 分析執行計畫

11. setcookie() 即時生效技巧

<?php
// ✅ 先賦值給變數,再 setcookie,下一行即可讀取 $_COOKIE
if ($online) {
    $online1 = $online;
    setcookie('online1', $online, $expire, $path, $domain, $secure);
    // 當前請求即可用 $_COOKIE['online1']
}

// ❌ 直接 setcookie,需下一次請求才能讀取
if ($online) {
    setcookie('online1', $online, $expire, $path, $domain, $secure);
}
?>

原理: PHP 會在 setcookie 後更新內部 $_COOKIE 超全域陣列(僅限賦值後的變數名)。

12. 檔案讀取:fopen + flock + fread 優於 file()

<?php
// ✅ 穩定、可控、支援鎖定、大檔案不佔記憶體
function readFileSafe($filename) {
    $handle = @fopen($filename, 'rb');
    if (!$handle) return false;
    @flock($handle, LOCK_SH);
    $data = @fread($handle, filesize($filename));
    @fclose($handle);
    return $data;
}

// ❌ file() 將整檔讀入陣列,大檔案記憶體爆炸,無鎖定機制
$lines = file($filename);
?>

13. 字串截斷優化:避免多位元組截半產生亂碼

<?php
function substr_utf8($str, $len, $suffix = '...') {
    if (mb_strlen($str, 'UTF-8') <= $len) return $str;
    return mb_substr($str, 0, $len, 'UTF-8') . $suffix;
}

// 使用範例
$title = substr_utf8($article['title'], 30);
?>

原版代碼用 ord() 判斷中文雙位元組,僅適用 GBK/Big5,**UTF-8 環境請改用 mb_substr**。

14. 大小寫檢查:ctype_upper() / 正則優於手動 ASCII 迴圈

<?php
// ✅ 內建函式,C 層實作,極快
if (preg_match('/[A-Z]/', $username)) { /* 含大寫 */ }

// ✅ 或 ctype 函式(僅 ASCII)
if (ctype_upper($username)) { /* 全大寫 */ }

// ❌ 手動迴圈檢查 ASCII 碼,慢且易錯
for ($i = 65; $i <= 90; $i++) { ... }
?>

15. 讀取大檔案逐行處理:Generator 記憶體友善

<?php
function readLines($filename) {
    $handle = fopen($filename, 'r');
    while (($line = fgets($handle)) !== false) {
        yield rtrim($line);
    }
    fclose($handle);
}

// 使用:逐行處理,記憶體恆定
foreach (readLines('huge.log') as $line) {
    process($line);
}
?>

總結:優化優先級排序

  1. 架構層:快取策略、資料庫索引、查詢優化、非同步處理
  2. 資料層:減少資料傳輸、序列化優化、避免 N+1 查詢
  3. 程式碼層:本文 15 項技巧(微優化,效果有限但值得養成習慣)

**黃金法則:先測量(Profiling),再優化。** 使用 Xdebug、Blackfire、Tideways 找出真正瓶頸,針對性修正,避免過早優化。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved