#1
Working with large datasets can slow down your Firebird application if queries or memory usage are not managed properly. This guide explains practical techniques to efficiently handle big data in Spring Boot using pagination, streaming, and batch operations.

1. Use Pagination for Data Retrieval

When retrieving thousands of rows, always paginate results instead of loading everything into memory. Here’s how to add pagination with Spring Data JPA:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    Page<Employee> findAll(Pageable pageable);
}
Then, you can request pages in your service:
Page<Employee> employees = employeeRepository.findAll(PageRequest.of(0, 100));
employees.getContent().forEach(System.out::println);
This loads only 100 records per request, reducing memory consumption significantly.

2. Stream Data for Processing

If you need to process all records but don’t want to keep them in memory, use Java 8 streams.
@Query("SELECT e FROM Employee e")
Stream<Employee> streamAll();
And consume it efficiently:
try (Stream<Employee> stream = employeeRepository.streamAll()) {
    stream.forEach(e -> processEmployee(e));
}
This approach keeps memory usage low because data is fetched lazily from Firebird.

3. Use Batch Inserts and Updates

When inserting or updating a large number of records, batch processing can dramatically improve performance.
Enable batch mode in your application.properties:
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
Then, in your service:
@Transactional
public void saveEmployees(List<Employee> employees) {
    for (int i = 0; i < employees.size(); i++) {
        employeeRepository.save(employees.get(i));
        if (i % 50 == 0) {
            employeeRepository.flush();
        }
    }
}
This groups operations into batches, minimizing communication with the database.

4. Optimize Queries with Indexes

Firebird performs best when queries use proper indexes. Identify columns frequently used in filters or sorting and create indexes for them.
Example:
CREATE INDEX IDX_EMPLOYEE_DEPARTMENT ON EMPLOYEE(DEPARTMENT_ID);
You can verify query performance using Firebird’s PLAN keyword or database monitoring tools.

5. Limit Fetch Size

Set the fetch size for the JDBC driver to control how many rows are retrieved per network call:
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setFetchSize(200);
This reduces network overhead for very large queries.

6. Use Stored Procedures for Heavy Computation

If your logic involves complex aggregations, consider moving it closer to the database with stored procedures.
Example Firebird procedure:
CREATE PROCEDURE GET_TOTAL_SALARY 
RETURNS (TOTAL NUMERIC(15,2))
AS
BEGIN
  SELECT SUM(SALARY) FROM EMPLOYEE INTO :TOTAL;
  SUSPEND;
END
Then call it from Spring Boot:
@Query(value = "EXECUTE PROCEDURE GET_TOTAL_SALARY", nativeQuery = true)
BigDecimal getTotalSalary();
This minimizes data transfer and improves execution time.
#ads

image quote pre code