개요

최근에 기업 프로젝트의 PR을 보다가 이전에 보지 못했던 매퍼 파일에서 반환형을 보게 되었습니다. 주소록 그룹에서 대량 팩스 번호를 검색하는 쿼리의 반환 유형은 다음과 같습니다. 커서

이런 이유로 커서리스트처럼 많이 반복할 수 있지만 다른 장점도 있을 것 같아서 내용을 정리해 보았습니다.
커서?
반복자를 사용하여 항목 가져오기를 느리게 처리하는 커서 계약입니다. 커서가 완벽하게 일치합니다.
일반적으로 메모리에 맞지 않는 수백만 개의 항목 쿼리를 처리합니다.
위의 문장은 공식 MyBatis 문서에서 확인된 커서의 정의입니다. 번역하면 Iterator는 항목 가져오기 속도를 늦추는 데 사용할 수 있으며 일반적으로 메모리에 맞지 않는 대규모 검색 쿼리에 적합합니다.오전. 이렇게 하면 개요에서 추측한 목록과 비교할 수 있는 이점이 있습니다. 빅데이터 처리안에서 발견되었다

커서는 마이바티스 3.5.0 이상 버전에서 사용 가능 제공 상호 작용 그 중 하나이며 많은 양의 데이터를 처리할 때 메모리를 효율적으로 사용할 수 있습니다. 반복 가능
추가 커서 잠금 가능 인터페이스도 확장되어 있으므로 try 문에서 사용하거나 close() 메서드로 닫아야 하지만 프레임워크의 도움으로 이러한 부분을 지정하지 않고 사용할 수 있습니다.
대량 처리의 이점
목록을 사용한 대량 처리

DB에서 많은 양의 데이터를 불러와 사용할 경우 위 그림과 같이 메모리에 모든 데이터를 로드한 후에야 데이터를 사용할 수 있습니다. 데이터가 너무 많은 경우 메모리 오류 외부발생하거나 발생하지 않더라도 너무 많은 메모리를 차지하기 때문에 문제가 될 수 있습니다.
커서로 대량 처리

반면 커서를 사용하면 모든 데이터가 메모리에 로드되지 않아도 DB의 데이터를 소비할 수 있습니다. Cursor가 반환하는 데이터는 반복을 반복할 수 있는 경우 사용할 수 있도록 커서를 반환합니다.
이는 DB 연결이 살아있는 동안(트랜잭션이 살아있는 동안) 계속되고 프레임워크는 트랜잭션이 종료된 것을 발견하면 연결을 닫습니다.
커서의 적용
커서는 사용하기 매우 쉽습니다. 과거에 Dao는 반환 유형을 목록으로 사용했습니다. 커서로 변경하면 됩니다.
// DAO
public class CursorMapper {
@Select(...)
List<String> getFaxNumbers(); // List 사용
@Select(...)
Cursor<String> getFaxNumbers(); // Cursor 사용
}
// Service
@RequiredArgsConstructor
public class CursorService {
private final CursorMapper cursorMapper;
public void test() {
Cursor<String> faxNumbers = cursorMapper.getFaxNumbers(); // 어떤 값이 들어있을까?
}
}
위와 같이 CursorMapper에서 Cursor로 메소드를 생성하고 CursorService에서 해당 Mapper로 데이터를 받으면 항상 빈 값만 조회됩니다.
@Transactional 사용
커서는 주어진 단위로 데이터를 처리할 수 있게 해주지만, 데이터 처리가 완료되면 다음 단위를 읽어야 하므로 모든 데이터가 통과할 때까지 DB 연결을 유지해야 하기 때문이다.
그래서 커서를 사용하고 싶다면 이 서비스 방식에서 @거래 주석을 추가하여 트랜잭션 상태를 유지해야 하며 추가로 메서드를 종료하기 전에 커서로 모든 작업을 완료해야 합니다.. 위의 코드를 보면 test() 메서드 내에서 커서를 사용하는 모든 작업을 종료해야 합니다.
// Service
@RequiredArgsConstructor
public class CursorService {
private final CursorMapper cursorMapper;
@Transactional // 중요!
public void test() {
Cursor<String> faxNumbers = cursorMapper.getFaxNumbers();
}
}
스트림도 사용할 수 있나요?
루프와 관련된 코드 아래 for 또는 foreach 대신 스트림 사용일부 개발 코드가 있습니다. 리스트에 루프문을 주로 쓰는데 비슷한 유형의 커서에 스트림을 사용할 수 있는지 궁금했는데 아쉽네요. Cursor는 Collection을 구현하지 않기 때문에 스트림을 사용할 수 없습니다…

커서를 적용할 때 고려할 사항
커서는 모든 데이터를 메모리에 로드하지 않고 처리할 수 있기 때문에 작업에 과도한 메모리를 사용하지 않는 장점이 있습니다. 하지만 리스트형과 달리 DB에서 계속해서 데이터를 가져온다. DB와의 통신 횟수 증가~처럼이를 위해 네트워크 리소스 비용이 증가할 수 있음.
메모리에 로드된 데이터 처리는 네트워크 통신에 필요한 시간보다 몇 배나 빠르기 때문에 대용량 처리에 커서를 사용하면 독이 될 수 있습니다.
- 가져오기 크기 높은 ⇒ 메모리 할당 높은, 네트워크 리소스 아래에
- 가져오기 크기 아래에 ⇒ 메모리 할당 아래에네트워크 리소스 높은
커서로 데이터를 가져올 때 가져오기 크기고정이 가능하며, 그에 따른 메모리 사용량과 네트워크 자원 비용 간의 trade-off를 조정하고 최적의 값을 찾아 적용하는 것이 필요해 보인다.(회사 프로젝트에서 테스트를 해보려 했으나 시간이 부족하여 테스트를 못했습니다..)
참조
마이바티스 커서
Mybatis와 Cursor를 한글로 쿼리하면 100 100에서 “Oracle Cursors”로 쿼리됩니다. 이 목적으로 주로 사용되기 때문에 Cu …
dev.to
마이바티스의 fetchSize와 커서의 역사
컴퓨터는 정해진 규칙에 따라 작동하기 때문에 처리를 수행하려면 입력에서 필요한 숫자를 계산하거나 알려진 숫자를 기반으로 결정을 내려야 합니다. 네트워크 통신의 기본 바이트
git.lily.rs


