0

Trino SQL Bài học 9: Sắp xếp dữ liệu (ORDER BY) và phân trang (LIMIT, OFFSET)

Mục tiêu bài học:

  • Nắm vững cách sắp xếp dữ liệu theo một hoặc nhiều tiêu chí.

  • Làm chủ cách định vị các giá trị rỗng (NULL) trong kết quả sắp xếp.

  • Sử dụng LIMIT và OFFSET để giới hạn kết quả và phân trang.

  • Đặc biệt quan trọng: Hiểu chi phí hiệu năng (performance cost) cực lớn của việc sắp xếp toàn cục trong kiến trúc phân tán và cách tối ưu.

1. Mệnh đề ORDER BY: Sắp xếp dữ liệu

Trong cơ sở dữ liệu quan hệ hay hệ thống phân tán, dữ liệu được lưu trữ và trả về một cách không có thứ tự mặc định. Để kết quả hiển thị theo một trật tự có ý nghĩa, bạn bắt buộc phải dùng ORDER BY.

  • ASC (Ascending - Mặc định): Sắp xếp tăng dần (A-Z, 0-9, Cũ-Mới).

  • DESC (Descending): Sắp xếp giảm dần (Z-A, 9-0, Mới-Cũ).

Sắp xếp theo một cột: Tìm danh sách đơn hàng được sắp xếp theo tổng giá trị giảm dần (đơn to nhất lên đầu).

SQL

SELECT orderkey, totalprice, orderdate
FROM tpch.tiny.orders
ORDER BY totalprice DESC;

Sắp xếp theo nhiều cột: Trino sẽ ưu tiên sắp xếp theo cột đầu tiên. Nếu có nhiều dòng trùng giá trị ở cột đầu, nó mới dùng cột thứ hai để quyết định thứ tự.

SQL

-- Sắp xếp khách hàng theo phân khúc thị trường (A-Z),
-- trong cùng một phân khúc, ai có số dư lớn hơn sẽ xếp trước.
SELECT name, mktsegment, acctbal
FROM tpch.tiny.customer
ORDER BY mktsegment ASC, acctbal DESC;

2. Kiểm soát giá trị NULL (NULLS FIRST / NULLS LAST)

Khi cột bạn dùng để sắp xếp có chứa giá trị NULL, một câu hỏi đặt ra là: NULL lớn hơn hay nhỏ hơn các số bình thường?

Trong Trino, theo mặc định giá trị NULL được xem là lớn nhất. Tuy nhiên, để kiểm soát chính xác vị trí của dữ liệu khuyết thiếu, bạn nên khai báo tường minh bằng từ khóa:

  • NULLS FIRST: Đẩy tất cả các dòng có giá trị NULL lên trên cùng.

  • NULLS LAST: Đẩy tất cả các dòng có giá trị NULL xuống dưới cùng.

SQL

-- Lấy danh sách khách hàng, những người chưa có số điện thoại (NULL) sẽ hiển thị lên đầu
SELECT name, phone, acctbal
FROM tpch.tiny.customer
ORDER BY phone ASC NULLS FIRST;

3. Giới hạn kết quả với LIMIT

Khi phân tích Big Data, bảng của bạn có thể chứa hàng tỷ dòng. Việc SELECT * hoặc sắp xếp mà không có giới hạn sẽ làm treo công cụ BI, tốn băng thông và làm chậm cả hệ thống.

LIMIT n chỉ thị cho Trino chỉ trả về đúng n dòng dữ liệu đầu tiên.

SQL

-- Truy vấn Top 5 khách hàng giàu nhất
SELECT name, mktsegment, acctbal
FROM tpch.tiny.customer
ORDER BY acctbal DESC
LIMIT 5;

4. Bỏ qua dữ liệu với OFFSET (Phân trang)

Nếu LIMIT dùng để cắt lấy phần đầu, thì OFFSET n dùng để bỏ qua n dòng đầu tiên trước khi bắt đầu lấy dữ liệu. Sự kết hợp giữa LIMIT và OFFSET tạo ra cơ chế Phân trang (Pagination).

SQL

-- Lấy khách hàng giàu thứ 6 đến thứ 10 (Trang 2, mỗi trang 5 kết quả)
SELECT name, mktsegment, acctbal
FROM tpch.tiny.customer
ORDER BY acctbal DESC
OFFSET 5 ROWS  -- Bỏ qua 5 người đầu tiên
LIMIT 5;       -- Lấy 5 người tiếp theo

(Lưu ý: Từ khóa ROWS sau OFFSET là tùy chọn theo chuẩn SQL, bạn có thể viết gọn là OFFSET 5 LIMIT 5).

5. Góc nhìn Kỹ sư: Nút thắt cổ chai (Bottleneck) của ORDER BY

Đây là kiến thức phân biệt một người biết gõ SQL và một Kỹ sư Dữ liệu thực thụ trên Trino.

Trong kiến trúc phân tán (như đã học ở Bài 1), dữ liệu được xử lý song song trên nhiều Worker node.

  • Nếu bạn chỉ gõ SELECT * FROM table, các Worker đọc xong sẽ ném thẳng kết quả về Coordinator. Tốc độ cực nhanh.

  • Nhưng nếu bạn gõ ORDER BY totalprice, Trino buộc phải gom TOÀN BỘ dữ liệu từ tất cả các Worker về một node duy nhất để sắp xếp toàn cục (Global Sorting). Quá trình này ngốn một lượng RAM khổng lồ, dễ gây ra lỗi Query Exceeded Memory Limit và làm chậm toàn bộ cụm.

Cách tối ưu (Best Practice): Luôn luôn kết hợp ORDER BY với LIMIT nếu có thể. Khi Trino thấy cấu trúc ORDER BY ... LIMIT N, nó không gom tất cả dữ liệu lại nữa. Thay vào đó, nó kích hoạt thuật toán Top-N Operator: Mỗi Worker tự sắp xếp dữ liệu nội bộ của mình và chỉ gửi đúng N dòng lớn nhất về Coordinator. Coordinator chỉ việc gộp các nhóm nhỏ này lại. Tốc độ sẽ nhanh hơn hàng trăm lần và không tốn RAM.

Cảnh báo về OFFSET: Tránh dùng OFFSET quá lớn (ví dụ: OFFSET 1000000 LIMIT 10). Để bỏ qua 1 triệu dòng, Trino vẫn phải quét, tính toán và sắp xếp đủ 1 triệu dòng đó trên bộ nhớ rồi mới vứt đi.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí