LIMIT cấp SQL
Để hạn chế kích thước tập hợp kết quả truy vấn SQL, bạn có thể sử dụng cú pháp SQL:008:
SELECT title
FROM post
ORDER BY created_on DESC
OFFSET 50 ROWS
FETCH NEXT 50 ROWS ONLY
hoạt động trên Oracle 12, SQL Server 2012 hoặc PostgreSQL 8.4 hoặc các phiên bản mới hơn.
Đối với MySQL, bạn có thể sử dụng các mệnh đề LIMIT và OFFSET:
SELECT title
FROM post
ORDER BY created_on DESC
LIMIT 50
OFFSET 50
Ưu điểm của việc sử dụng phân trang mức SQL là kế hoạch thực thi cơ sở dữ liệu có thể sử dụng thông tin này.
Vì vậy, nếu chúng ta có một chỉ mục trên created_on
cột:
CREATE INDEX idx_post_created_on ON post (created_on DESC)
Và chúng tôi thực hiện truy vấn sau sử dụng LIMIT
mệnh đề:
EXPLAIN ANALYZE
SELECT title
FROM post
ORDER BY created_on DESC
LIMIT 50
Chúng ta có thể thấy rằng công cụ cơ sở dữ liệu sử dụng chỉ mục vì trình tối ưu hóa biết rằng chỉ có 50 bản ghi được tìm nạp:
Execution plan:
Limit (cost=0.28..25.35 rows=50 width=564)
(actual time=0.038..0.051 rows=50 loops=1)
-> Index Scan using idx_post_created_on on post p
(cost=0.28..260.04 rows=518 width=564)
(actual time=0.037..0.049 rows=50 loops=1)
Planning time: 1.511 ms
Execution time: 0.148 ms
JDBC Statement maxRows
Theo setMaxRows
Javadoc
:
Điều đó không yên tâm lắm!
Vì vậy, nếu chúng ta thực hiện truy vấn sau trên PostgreSQL:
try (PreparedStatement statement = connection
.prepareStatement("""
SELECT title
FROM post
ORDER BY created_on DESC
""")
) {
statement.setMaxRows(50);
ResultSet resultSet = statement.executeQuery();
int count = 0;
while (resultSet.next()) {
String title = resultSet.getString(1);
count++;
}
}
Chúng tôi nhận được kế hoạch thực thi sau trong nhật ký PostgreSQL:
Execution plan:
Sort (cost=65.53..66.83 rows=518 width=564)
(actual time=4.339..5.473 rows=5000 loops=1)
Sort Key: created_on DESC
Sort Method: quicksort Memory: 896kB
-> Seq Scan on post p (cost=0.00..42.18 rows=518 width=564)
(actual time=0.041..1.833 rows=5000 loops=1)
Planning time: 1.840 ms
Execution time: 6.611 ms
Bởi vì trình tối ưu hóa cơ sở dữ liệu không biết rằng chúng ta chỉ cần tìm nạp 50 bản ghi, nó giả định rằng tất cả 5000 hàng cần được quét. Nếu một truy vấn cần tìm nạp một số lượng lớn các bản ghi, chi phí quét toàn bảng thực sự thấp hơn nếu chỉ sử dụng một chỉ mục, do đó kế hoạch thực thi sẽ hoàn toàn không sử dụng chỉ mục.
Kết luận
Mặc dù nó trông giống như setMaxRows
là một giải pháp di động để giới hạn kích thước của ResultSet
, phân trang mức SQL hiệu quả hơn nhiều nếu trình tối ưu hóa máy chủ cơ sở dữ liệu không sử dụng JDBC maxRows
tài sản.