Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Phân trang (pagination) trong MySQL: SELECT hàng theo lô (batch) với LIMIT và OFFSET

Để lấy dữ liệu theo từng trang/lô (batch) thay vì tải toàn bộ, MySQL cung cấp LIMIT (số hàng tối đa) và OFFSET (bỏ qua bao nhiêu hàng đầu).

Cú pháp

SELECT * FROM ten_bang
ORDER BY cot_sap_xep
LIMIT so_hang_moi_lot OFFSET so_hang_bo_qua;

Hoặc viết gọn: LIMIT offset, count (thứ tự ngược: offset trước, count sau).

Ví dụ minh họa

Tạo bảng 10 hàng:

mysql> CREATE TABLE DemoTable1514 (
    -> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> FirstName VARCHAR(20)
    -> );
mysql> INSERT INTO DemoTable1514(FirstName) VALUES
    -> ('Chris'),('Bob'),('Sam'),('Mike'),('Carol'),
    -> ('David'),('Robert'),('Adam'),('John'),('Jace');

Lấy lô 2 (hàng 5-8), mỗi lô 4 hàng:

mysql> SELECT * FROM DemoTable1514 LIMIT 4 OFFSET 4;

Kết quả (bỏ 4 hàng đầu, lấy 4 hàng tiếp):

+----+-----------+
| Id | FirstName |
+----+-----------+
|  5 | Carol     |
|  6 | David     |
|  7 | Robert    |
|  8 | Adam      |
+----+-----------+

Công thức phân trang

  • Trang page (bắt đầu từ 1), kích thước pageSize:
  • OFFSET = (page - 1) * pageSize
  • LIMIT = pageSize

⚠️ Vấn đề hiệu năng OFFSET lớn

Khi OFFSET lớn (trang sau), MySQL vẫn phải **đọc và bỏ qua** các hàng trước → chậm dần.

Giải pháp Keyset Pagination (Cursor-based):

-- Trang đầu
SELECT * FROM bang ORDER BY id LIMIT 20;

-- Trang sau (dùng ID cuối trang trước)
SELECT * FROM bang WHERE id > 20 ORDER BY id LIMIT 20;
  • Yêu cầu cột sắp xếp **duy nhất** (unique) và có index.
  • Không hỗ trợ nhảy trang tùy ý (chỉ next/prev).
  • Hiệu năng không đổi theo số trang.

Lưu ý

  • Luôn có ORDER BY xác định để kết quả ổn định.
  • LIMIT 0 trả về 0 hàng (hữu ích kiểm tra cấu trúc).
  • MySQL 8.0.18+ hỗ trợ OFFSET ... ROWS FETCH NEXT ... ROWS ONLY (chuẩn SQL).