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

PHP 分頁效能優化:從雙查詢到單查詢的終極方案

     編輯:PHP 相關知識

傳統分頁需要兩次資料庫查詢:COUNT(*) 取總筆數,再 LIMIT 取當頁資料。面對大數據量與高併發,這造成嚴重效能瓶頸。本文提出「首次查詢總數,後續透過 URL 參數傳遞」的優化策略,將分頁查詢從 2N 降為 N+1。

傳統雙查詢模式(低效)

// 每次分頁皆執行
$sqlCount = "SELECT COUNT(*) AS total FROM tablename";
$total = mysql_fetch_assoc(mysql_query($sqlCount))['total'];

$sqlData = "SELECT * FROM tablename LIMIT " . ($page-1)*$pageSize . ", $pageSize";
$data = mysql_query($sqlData);

缺點:翻頁、排序、篩選每次皆觸發 COUNT(*),鎖表、掃描全表,MyISAM 尤其明顯。

優化策略:總數快取於 URL 參數

// 首次載入或無 total 參數時查詢總數
if (isset($_GET['total'])) {
    $total = intval($_GET['total']);
} else {
    $sqlCount = "SELECT COUNT(*) AS total FROM tablename";
    $total = mysql_fetch_assoc(mysql_query($sqlCount))['total'];
}

$page = max(1, intval($_GET['page'] ?? 1));
$sqlData = "SELECT * FROM tablename LIMIT " . ($page-1)*$pageSize . ", $pageSize";
$data = mysql_query($sqlData);

// 分頁連結攜帶 total 參數
$url = "url.php?total=$total&page=";
echo $pagination->render($url, $total, $pageSize, $page);

進階優化方案比較

方案原理優點缺點
URL 傳遞 total客戶端保持狀態零伺服器快取、實作簡單URL 較長、用戶可竄改總數
Redis/Memcached 快取總數伺服器端快取 5-60 秒精準度高、不暴露參數需維護快取失效策略
SQL_CALC_FOUND_ROWSMySQL 內建一次查詢同時獲取總數單次查詢、語法標準MySQL 8.0 棄用、鎖表風險
游標分頁以唯一遞增 ID 為游標極高效能、無 OFFSET 深分頁問題不支援跳轉任意頁、需 ID 連續
預估總數EXPLAIN rows 或資訊統計表零成本不精確、僅適用大數據近似

最佳實踐建議

  1. 中小型專案:URL 傳遞 total + Redis 快取 30 秒雙重保險。
  2. 大數據/高併發:改用游標分頁,前端改為「載入更多」無限滾動。
  3. 安全性:intval() 強制轉型,防止 SQL 注入;總數參數加簽名驗證。
  4. 現代框架:Laravel paginate()、Symfony Paginator 內建最佳化,優先使用。

避坑指南

  • 勿在迴圈中執行 COUNT(*)(N+1 問題)。
  • 避免 OFFSET 1000000 LIMIT 10 深分頁,改用 WHERE id > last_id LIMIT 10。
  • InnoDB COUNT(*) 無 WHERE 條件較快,有條件需走索引,考慮觸發器維護計數表。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved