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

PHP 分頁技術核心:LIMIT 子句實作與效能優化指南

     編輯:PHP 綜合知識

學習目標

  • 掌握 MySQL LIMIT offset, count 分頁核心語法
  • 理解分頁參數邊界處理與安全防護
  • 認識深分頁效能陷阱與優化策略

核心原理:LIMIT 子句

SELECT * FROM `table_name` LIMIT {$offset}, {$pageSize};
  • offset:跳過的筆數 (起始索引 0-based),第 1 頁為 0,第 N 頁為 (N-1) * pageSize。
  • count:每頁筆數。

完整分頁邏輯實作 (PDO 版)

<?php
// 設定
$pageSize = 10;
$page     = max(1, (int)($_GET['page'] ?? 1));

// 1. 取得總筆數 (必要)
$stmt = $pdo->query("SELECT COUNT(*) FROM `articles`");
$totalRows = $stmt->fetchColumn();
$totalPages = (int)ceil($totalRows / $pageSize);

// 2. 邊界修正
if ($page > $totalPages) $page = max(1, $totalPages);

// 3. 計算 offset
$offset = ($page - 1) * $pageSize;

// 4. 查詢當頁資料
$sql = "SELECT `id`, `title`, `created_at` FROM `articles` 
        ORDER BY `id` DESC 
        LIMIT :offset, :limit";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 5. 產生分頁導航 (簡易版)
$nav = '';
if ($totalPages > 1) {
    $nav .= '<a href="?page=1">首頁</a> ';
    $nav .= ($page > 1) ? '<a href="?page=' . ($page-1) . '">上一頁</a> ' : '上一頁 ';
    $nav .= ($page < $totalPages) ? '<a href="?page=' . ($page+1) . '">下一頁</a> ' : '下一頁 ';
    $nav .= '<a href="?page=' . $totalPages . '">末頁</a>';
    $nav .= " (第 {$page} / {$totalPages} 頁,共 {$totalRows} 筆)";
}

// 輸出模板 (略)
?>

進階優化:深分頁效能陷阱與解法

問題現象

當 OFFSET 極大 (如第 10 萬頁) 時,MySQL 仍需掃描前 100 萬筆再捨棄,導致查詢緩慢甚至超時。

優化策略對比

策略適用場景原理代價
延遲關聯單表、主鍵有序先只查 ID:SELECT id FROM t ORDER BY id LIMIT 100000, 10,再 JOIN 回表取欄位需額外 JOIN,但大幅減少掃描行
游標/Keyset 分頁無限捲動、API 分頁記住上一頁最大 ID:WHERE id > :last_id ORDER BY id LIMIT 10,不使用 OFFSET無法隨機跳頁、需唯一排序鍵
覆蓋索引查詢欄位少索引包含所有查詢欄位,避免回表索引體積增大、寫入略慢
預先計算/快取熱門列表、首頁Redis 快取分頁 HTML 或 ID 陣列資料一致性處理複雜

延遲關聯實戰範例

$sql = "SELECT a.* FROM `articles` a
        INNER JOIN (
            SELECT `id` FROM `articles` ORDER BY `id` DESC LIMIT :offset, :limit
        ) b USING (`id`)
        ORDER BY a.`id` DESC";

安全與體驗細節

  • 參數型別強制轉換:(int)$_GET['page'] 防 SQL 注入。
  • pageSize 白名單:in_array($pageSize, [10,20,50,100]) 防止惡意設定巨大值導致 OOM。
  • SEO 友善:使用 <link rel="prev/next">、canonical、結構化資料 ItemList。
  • 無障礙:分頁連結加 aria-label、當前頁 aria-current="page"。

結語

分頁看似簡單,實則涉及資料庫索引設計、查詢優化、前端體驗、SEO 等多維考量。掌握 LIMIT 基礎語法後,務必根據資料量級選擇適合的優化策略,並在架構層面引入快取與非同步載入,打造高效能、可擴展的列表系統。

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