核心邏輯與安全改良版
<?php
// 1. 連線(使用 PDO 預處理防注入)
$pdo = new PDO(
"mysql:host=localhost;dbname=your_db;charset=utf8mb4",
'user', 'pass',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// 2. 參數驗證
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = 20;
$offset = ($page - 1) * $perPage;
// 3. 總筆數(可快取)
$stmt = $pdo->query("SELECT COUNT(*) FROM your_table");
$total = $stmt->fetchColumn();
$totalPages = (int)ceil($total / $perPage);
// 4. 分頁查詢(利用覆蓋索引)
$stmt = $pdo->prepare("SELECT id, title, created_at FROM your_table ORDER BY id DESC LIMIT ?, ?");
$stmt->bindValue(1, $offset, PDO::PARAM_INT);
$stmt->bindValue(2, $perPage, PDO::PARAM_INT);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!-- 5. 顯示資料 -->
<table>
<thead><tr><th>ID</th><th>標題</th><th>建立時間</th></tr></thead>
<tbody>
<?php foreach ($rows as $row): ?>
<tr><td><?= $row['id'] ?></td><td><?= htmlspecialchars($row['title']) ?></td><td><?= $row['created_at'] ?></td></tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- 6. 分頁導航 -->
<nav>
<?php
$prev = $page > 1 ? $page - 1 : 1;
$next = $page < $totalPages ? $page + 1 : $totalPages;
?>
<a href="?page=1">首頁</a>
<a href="?page=<?= $prev ?>">上一頁</a>
<span>第 <?= $page ?> / <?= $totalPages ?> 頁</span>
<a href="?page=<?= $next ?>">下一頁</a>
<a href="?page=<?= $totalPages ?>">尾頁</a>
效能優化關鍵點
| 問題 | 解決方案 |
| OFFSET 深分頁慢 | 改用游標分頁:WHERE id > ? ORDER BY id LIMIT ? |
| COUNT(*) 慢 | 資訊表估算 SHOW TABLE STATUS / 快取總數 / 觸發器維護計數表 |
| SELECT * | 只查需要欄位,利用覆蓋索引 |
| 頻繁 COUNT | Redis 快取總數,定期同步 |
游標分頁範例(百萬級資料適用)
-- 首頁
SELECT id, title FROM articles WHERE status=1 ORDER BY id DESC LIMIT 20;
-- 後續頁(記住上一頁最後一筆 id)
SELECT id, title FROM articles WHERE status=1 AND id < :last_id ORDER BY id DESC LIMIT 20;
前端增強建議
- 無限滾動:IntersectionObserver + fetch 下一頁
- URL 狀態:History API 保持分頁狀態可分享
- 載入狀態:Skeleton screen 提升感知速度
- 上一篇文章: MySQL 資料類型深度解析:TEXT、DATE、SET、ENUM 與通配符實戰
- 下一篇文章: 從 MySQL 原生 API 遷移至 ADODB:資料庫抽象層實戰指南
Copyright ©
程式碼之家 All Rights Reserved