分頁查詢需同時返回:當頁資料 + 總符合行數(供前端計算總頁數)。傳統做法兩條查詢:
SELECT COUNT(*) FROM t WHERE cond; -- 總數
SELECT * FROM t WHERE cond LIMIT 10, 20; -- 分頁資料
SELECT SQL_CALC_FOUND_ROWS * FROM t WHERE cond LIMIT 10, 20;
SELECT FOUND_ROWS(); -- 返回不帶 LIMIT 的總行數
FOUND_ROWS() 必須緊跟在帶 SQL_CALC_FOUND_ROWS 的查詢之後
SELECT SQL_CALC_FOUND_ROWS t3.id, a, bunch, of, other, stuff
FROM t1, t2, t3
WHERE (associate t1,t2,and t3 with each other)
GROUP BY t3.id
LIMIT 10, 20;
SELECT FOUND_ROWS() AS total_groups;
返回分組後的總組數,而非原始行數。配合分頁顯示分組列表(如:按用戶分組的訂單統計)完美適用。
SQL_CALC_FOUND_ROWS 標記棄用,未來版本移除
-- 第一次查詢快取總數(Redis Key: total:cond_hash, TTL 30s)
SELECT COUNT(*) FROM t WHERE cond;
-- 後續分頁直接讀快取
SELECT * FROM t WHERE cond LIMIT 10, 20;
EXPLAIN SELECT * FROM t WHERE cond;
-- rows 欄位為優化器估算行數,極快但不精確
CREATE TABLE stats (cond_hash CHAR(32) PRIMARY KEY, total BIGINT, updated_at TIMESTAMP);
-- INSERT/UPDATE/DELETE 觸發器增減 total
-- 查詢總數變為單行點查,極快
SELECT *, COUNT(*) OVER() AS total
FROM t WHERE cond
LIMIT 10, 20;
-- 單次查詢返回資料+總數,但需掃描所有符合行計算窗口
-- 簡單分組計數
SELECT column_id, COUNT(*) AS cnt FROM my_table GROUP BY column_id;
-- 多欄位分組
SELECT dept_id, status, COUNT(*) FROM emp GROUP BY dept_id, status;
-- 分組過濾
SELECT dept_id, AVG(sal) FROM emp GROUP BY dept_id HAVING AVG(sal) > 2000;
SQL_CALC_FOUND_ROWS + FOUND_ROWS() 是 MySQL 經典分頁總數技巧,GROUP BY 同樣適用。但 8.0 棄用、大數據量效能一般,生產建議:快取 COUNT(*)、估算 rows、物化計數表、窗口函數 四選一視業務容忍度而定。