Why Spring Boot Prefers Slice Over Page for Massive Data Sets

The article analyzes Spring Data JPA's Page and Slice pagination options, explains the hidden COUNT(*) overhead of Page, demonstrates both approaches with code examples, compares performance and UX impacts, and provides guidance on when to choose Slice for large‑scale or infinite‑scroll scenarios.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Why Spring Boot Prefers Slice Over Page for Massive Data Sets

1. Introduction

In massive‑data scenarios, the choice of pagination method directly affects system performance and user experience. Spring Data JPA offers Page and Slice as two pagination schemes. Although their usage looks similar, their underlying mechanisms and performance characteristics differ significantly, and many projects default to Page while overlooking the extra count query overhead.

2. Page Pagination

2.1 Concept

Pageable

defines page number, page size and sorting. A typical repository method returns a Page<User> or a List<User> when a Pageable is passed.

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> queryUserBySex(Pageable pageable, Integer sex);
}

Calling the method with a Pageable makes Spring Data add LIMIT and OFFSET to the SQL.

public List<User> queryUsers() {
    Pageable pageable = PageRequest.of(0, 20, Sort.by("age").ascending());
    return userRepository.queryUserBySex(pageable, "0");
}

The Page object (fully qualified name org.springframework.data.domain.Page) provides rich metadata:

getContent()

getTotalElements()

getTotalPages()

getNumber()

getSize()

hasNext(), hasPrevious(), isFirst(), isLast()

Because Page must return totalElements and totalPages, it executes two SQL statements per request:

Main query: fetches the current page data using LIMIT / OFFSET.

Separate count query: runs SELECT COUNT(*) to compute the total number of matching rows.

Full example:

public interface UserRepository extends JpaRepository<User, Integer> {
    Page<User> findUserBySex(Pageable pageable, String sex);
}

public Page<User> findUsers() {
    Pageable pageable = PageRequest.of(0, 10, Sort.by("age").ascending());
    Page<User> page = userRepository.findUserBySex(pageable, "0");
    System.out.println("Total users: " + page.getTotalElements());
    System.out.println("Total pages: " + page.getTotalPages());
    return page;
}

Running this generates two SQL statements.

2.2 When to Use Page

Traditional paginated UI that needs to display "Page X of Y" or total record count.

Reporting / data‑analysis scenarios that require the full data range.

Small data sets where the extra COUNT(*) cost is negligible.

In very large tables or complex queries, the COUNT(*) can become a performance bottleneck.

3. Slice Pagination

3.1 Concept

Slice

(fully qualified name org.springframework.data.domain.Slice) is a lightweight alternative designed for infinite‑scroll or "load more" UI patterns. It only knows the current page data and whether a next page exists; it does not expose total element or total page counts.

getContent()

getNumber()

getSize()

hasNext(), hasPrevious()

Key difference: Slice lacks getTotalElements() and getTotalPages().

3.2 Performance Advantage

Because no total‑count query is needed, a Slice request executes only one SQL statement. To determine hasNext(), Spring Data fetches N+1 rows; the extra row is discarded after the check.

// Repository
Slice<User> queryUserBySex(String sex, Pageable pageable);

// Service
public Slice<User> selectUsers(int page, int size) {
    Pageable pageable = PageRequest.of(page, size, Sort.by("age").descending());
    Slice<User> commentSlice = userRepository.queryUserBySex("0", pageable);
    System.out.println("Current slice content size: %s".formatted(commentSlice.getNumberOfElements()));
    System.out.println("Has next slice? %s".formatted(commentSlice.hasNext()));
    return commentSlice;
}

The result shows only one SQL execution.

3.3 When to Use Slice

Infinite‑scroll feeds or "load more" buttons.

Mobile, SPA, or other clients that only need the current page and a "more data" flag.

Very large data sets where COUNT(*) would be extremely slow.

Performance‑first scenarios that aim to halve database query load.

Slice sacrifices total‑count visibility, which may be a drawback in contexts that require a complete overview.

4. Comparative Evaluation

4.1 Performance

Page (with COUNT) : 2 SQL statements per request; count query can become a bottleneck on huge tables.

Slice (no COUNT) : 1 SQL statement per request (plus one extra row for next‑page detection); better scalability for massive data.

4.2 UX Impact

Page UI : Shows total records and pages, suitable for traditional admin panels; navigation is static and requires explicit page jumps.

Slice UI : Provides smooth, continuous loading; ideal for modern mobile/web experiences, but cannot display total record count.

5. Best Practices & Common Pitfalls

Prefer Slice and fall back to Page only when total count is explicitly required.

Always specify an ORDER BY when using Pageable to ensure stable pagination.

Do not force‑modify Slice to obtain total counts; use Page instead.

Avoid Pageable.unpaged() on massive tables—it disables pagination and may cause full‑table scans.

Design appropriate database indexes for filter and sort columns to improve query efficiency.

// Recommended Pageable with sorting
Pageable pageable = PageRequest.of(0, 10, Sort.by("id").ascending());
// Not recommended: no sorting leads to unstable pagination
// Pageable pageable = PageRequest.of(0, 10);
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

backendPerformanceSpring Bootpaginationinfinite-scrollslicepagespring-data-jpa
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.