LIMIT tingkat SQL
Untuk membatasi ukuran kumpulan hasil kueri SQL, Anda dapat menggunakan sintaks SQL:008:
SELECT title
FROM post
ORDER BY created_on DESC
OFFSET 50 ROWS
FETCH NEXT 50 ROWS ONLY
yang bekerja pada Oracle 12, SQL Server 2012, atau PostgreSQL 8.4 atau versi yang lebih baru.
Untuk MySQL, Anda dapat menggunakan klausa LIMIT dan OFFSET:
SELECT title
FROM post
ORDER BY created_on DESC
LIMIT 50
OFFSET 50
Keuntungan menggunakan pagination tingkat SQL adalah bahwa rencana eksekusi database dapat menggunakan informasi ini.
Jadi, jika kita memiliki indeks pada created_on
kolom:
CREATE INDEX idx_post_created_on ON post (created_on DESC)
Dan kami menjalankan kueri berikut yang menggunakan LIMIT
klausa:
EXPLAIN ANALYZE
SELECT title
FROM post
ORDER BY created_on DESC
LIMIT 50
Kita dapat melihat bahwa mesin database menggunakan indeks karena pengoptimal mengetahui bahwa hanya 50 record yang akan diambil:
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
Menurut setMaxRows
Javadoc
:
Itu tidak terlalu meyakinkan!
Jadi, jika kita mengeksekusi query berikut di 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++;
}
}
Kami mendapatkan rencana eksekusi berikut di log 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
Karena pengoptimal basis data tidak tahu bahwa kita hanya perlu mengambil 50 catatan, ia mengasumsikan bahwa semua 5000 baris perlu dipindai. Jika kueri perlu mengambil sejumlah besar catatan, biaya pemindaian tabel lengkap sebenarnya lebih rendah daripada jika indeks digunakan, maka rencana eksekusi tidak akan menggunakan indeks sama sekali.
Kesimpulan
Meskipun terlihat seperti setMaxRows
adalah solusi portabel untuk membatasi ukuran ResultSet
, pagination tingkat SQL jauh lebih efisien jika pengoptimal server database tidak menggunakan maxRows
JDBC properti.