Keyset Pagination (Truy vấn theo Last ID) – Giải Pháp Tối Ưu Cho Dữ Liệu Lớn

0 0 0

Người đăng: Sang Le

Theo Viblo Asia

Keyset Pagination (Truy vấn theo Last ID) – Giải Pháp Tối Ưu Cho Dữ Liệu Lớn

Khi làm việc với các cơ sở dữ liệu lớn, vấn đề truy vấn hiệu quả là một thách thức không hề nhỏ. Đặc biệt là khi bảng dữ liệu của bạn có tới hàng triệu bản ghi, việc sử dụng phân trang truyền thống bằng OFFSET sẽ khiến mọi thứ trở nên chậm chạp. Để giải quyết tình huống này, Keyset Pagination (hay truy vấn theo Last ID) là một kỹ thuật rất hữu ích giúp tối ưu hóa hiệu suất truy vấn mà mình muốn chia sẻ với các bạn.

Vấn đề với Phân trang Truyền thống (OFFSET)

Khi chúng ta muốn truy vấn dữ liệu phân trang, phương pháp truyền thống là sử dụng LIMIT kết hợp với OFFSET. Ví dụ, để lấy 50 bản ghi đầu tiên, mình sẽ thực hiện câu lệnh SQL như sau:

SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50 OFFSET 0;

Nếu muốn lấy 50 bản ghi tiếp theo, mình sẽ tăng giá trị OFFSET:

SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50 OFFSET 50;

Vấn đề là khi bảng dữ liệu càng lớn, việc sử dụng OFFSET khiến cơ sở dữ liệu phải bỏ qua một lượng bản ghi nhất định trước khi trả về kết quả. Khi bảng của bạn có hàng chục triệu bản ghi, như mình đã thử nghiệm thực tế với 70 triệu bản ghi, hiệu suất của cách làm này giảm đi rất nhanh.

Giải pháp: Keyset Pagination (Truy vấn theo Last ID)

Keyset Pagination sẽ giúp cải thiện hiệu suất truy vấn khi làm việc với dữ liệu lớn. Thay vì sử dụng OFFSET, kỹ thuật này dựa vào giá trị ID của bản ghi cuối cùng từ lần truy vấn trước đó để tiếp tục truy vấn các bản ghi tiếp theo. Phương pháp này không yêu cầu cơ sở dữ liệu phải quét qua các bản ghi không cần thiết, giúp tiết kiệm rất nhiều thời gian.

Cách thức hoạt động của Keyset Pagination

  1. Lấy một số lượng bản ghi nhất định (ví dụ 50 bản ghi đầu tiên): Đầu tiên, chúng ta lấy 50 bản ghi được sắp xếp theo thứ tự tăng dần của cột ID hoặc một khóa chính nào đó.

    SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50;
    
  2. Lưu giá trị ID của bản ghi cuối cùng: Sau khi có kết quả, mình sẽ lưu lại giá trị của ID từ bản ghi cuối cùng để dùng cho lần truy vấn kế tiếp.

  3. Truy vấn các bản ghi tiếp theo dựa trên lastId: Lần tiếp theo, thay vì sử dụng OFFSET, mình sẽ chỉ truy vấn những bản ghi có ID lớn hơn giá trị ID cuối cùng từ lần truy vấn trước.

    SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 AND id > lastId ORDER BY id LIMIT 50;
    

Bằng cách này, cơ sở dữ liệu không cần phải quét toàn bộ các bản ghi để bỏ qua, giúp tăng tốc độ truy vấn đáng kể.

Demo Code: Phân Trang Truyền thống vs Keyset Pagination

Phân trang Truyền thống (OFFSET)

-- Lấy 50 bản ghi đầu tiên
SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50 OFFSET 0; -- Lấy 50 bản ghi tiếp theo
SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50 OFFSET 50; -- Lấy thêm 50 bản ghi nữa
SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50 OFFSET 100;

Nhược điểm:

  • Khi OFFSET tăng lên, hiệu suất giảm đi vì cơ sở dữ liệu phải bỏ qua nhiều bản ghi hơn.
  • Không hiệu quả khi bảng dữ liệu lớn, như trong thử nghiệm của mình với 70 triệu bản ghi.

Keyset Pagination (Truy vấn theo Last ID)

-- Lấy 50 bản ghi đầu tiên
SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 ORDER BY id LIMIT 50; -- Lấy 50 bản ghi tiếp theo dựa trên lastId (ID cuối cùng của kết quả trước)
SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 AND id > lastId ORDER BY id LIMIT 50; -- Lặp lại cho các bản ghi tiếp theo
SELECT * FROM my_table WHERE type = 'bank' AND isDeleted = 0 AND id > lastId ORDER BY id LIMIT 50;

Ưu điểm:

  • Hiệu suất ổn định ngay cả khi làm việc với bảng dữ liệu lớn.
  • Truy vấn nhanh hơn vì không cần quét lại các bản ghi đã bỏ qua.

Thử nghiệm thực tế

Trong quá trình thử nghiệm với bảng có 70 triệu bản ghi, mình nhận thấy Keyset Pagination vượt trội so với phương pháp dùng OFFSET. Khi dữ liệu lớn dần, phương pháp OFFSET chậm hẳn đi, trong khi Keyset Pagination vẫn giữ được tốc độ ổn định. Đây là kết quả rất ấn tượng khi xử lý những tập dữ liệu lớn trong môi trường sản xuất.

Khi nào nên dùng Keyset Pagination?

  • Khi cần phân trang dữ liệu lớn.
  • Khi muốn tăng tốc độ truy vấn và tránh việc cơ sở dữ liệu phải quét qua nhiều bản ghi không cần thiết.
  • Khi cột ID hoặc khóa chính của bảng là duy nhất và liên tục.

Kết luận

Keyset Pagination là một kỹ thuật cực kỳ hiệu quả khi làm việc với dữ liệu lớn. Bằng cách sử dụng giá trị ID để phân trang thay vì dựa vào OFFSET, kỹ thuật này giúp chúng ta giữ được hiệu suất ổn định và nhanh chóng ngay cả khi làm việc với bảng dữ liệu lớn như mình đã thử nghiệm với 70 triệu bản ghi. Nếu bạn đang gặp vấn đề với hiệu suất khi truy vấn dữ liệu lớn, hãy thử áp dụng kỹ thuật này, chắc chắn bạn sẽ thấy sự khác biệt đáng kể! 1

Bình luận

Bài viết tương tự

- vừa được xem lúc

Performance Optimization 103: Nghệ thuật tìm kiếm bottleneck

Những phương pháp thượng thừa để biến bạn trở thành bậc thầy bới lông tìm vết à bới hệ thống tìm bottleneck. Nếu là phe cảnh, bạn sẽ học được cách bắt bớ.

0 0 48

- vừa được xem lúc

Tối Ưu Ảnh Với Laravel Cực Đơn Giản ( Có Demo )

Hôm nay mình sẽ làm một demo Tối ưu hóa dung lượng ảnh trước khi gửi lên storage của server với Laravel. Công việc này chắc hẳn các bạn làm back-end vẫn thường xuyên phải xử lý và khá đau đầu phải khô

0 0 403

- vừa được xem lúc

010: Exclusive lock và Shared lock

Bài viết nằm trong series Performance optimization với PostgreSQL. Nếu execute single query:. UPDATE TABLE X SET COLUMN = 'Y' WHERE ID = 1;. .

0 0 49

- vừa được xem lúc

009: Optimistic lock và Pessimistic lock

Bài viết nằm trong series Performance optimization với PostgreSQL. Nghe có vẻ nguy hiểm nhưng cách giải quyết không có gì phức tạp, sử dụng các cơ chế mutual exclusion là giải quyết được vấn đề này.

0 0 57

- vừa được xem lúc

Performance Optimization 106: Caching - con đường lắm chông gai

Con đường vươn tới những hệ thống tải cao đầy chông gai và cỏ dại. Caching luôn là một con đường chông gai bởi vì nó không có hồi kết.

0 0 99

- vừa được xem lúc

013: Thực hành Vacuum với PostgreSQL

Bài viết nằm trong series Performance optimization với PostgreSQL. 1) Reindex.

0 0 35