PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

SQL LIMIT so với JDBC Statement setMaxRows. Cái nào tốt hơn?

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. lỗi:Xác thực danh tính không thành công cho người dùng

  2. LỖI:cột quan hệ không tồn tại PostgreSQL, Không thể chạy truy vấn chèn

  3. Lấy nhận xét từ cơ sở dữ liệu PostgreSQL

  4. Cách nhóm có điều kiện thành cột mà không cần sử dụng FULL OUTER JOIN

  5. Django ConnectionAbortedError:[WinError 10053] Một kết nối đã thiết lập đã bị phần mềm trong máy chủ của bạn hủy bỏ