본문 바로가기
mybatis

sprintboot with mybatis - 캐시 및 readonly 적용

by khds 2023. 3. 5.

 

평소에 JPA를 통해서만 프로젝트를 진행하였지만 mybatis도 다루고 싶엇기에 스프링부트와 mybatis를 통한 프로젝트를 진행하였고 repository구간을 작성하던 중에 문득 생각이 들었다.

mybatis에서는 쿼리힌트로 readOnly옵션을 적용할 수 있는가?

JPA를 사용할 때에는 쿼리힌트로 readOnly옵션을 줘가지고 메모리 성능향상을 이루었다. 이에 대해 궁금한 사항은 아래를 참고하길 바란다. 

https://khdscor.tistory.com/20

 

JPA 읽기전용으로 데이터를 조회하여 성능 향상(메모리, 속도)

JPA를 사용하면서 영속성 컨텍스트에 엔티티를 넣으면서 1차 캐시 및 쓰기 지연 등 여러 가지 이점을 얻을 수 있었다. 여기서 조회기능만을 사용하는 상황에서는 단순히 읽기 전용 기능으로 데이

khdscor.tistory.com

 

하지만 mybatis에는 jpa처럼 영속성컨테스트도 없고 애초에 쿼리힌트라는게 있는것인가 궁금하였다.

mybatis에서 readonly를 적용하여 성능개선을 이루고 싶었기에 이에 대해 자세히 살펴보았다.

먼저 mybatis에는 jpa처럼 쿼리힌트라는 것이 없고 sql구분에 인덱스를 적용할 때처럼 sql구문에 힌트를 적용하는 방식이라고 한다. 

그리고 readonly라는 옵션이 있는데 이는 캐시에 연결되어 있었다...!

프로젝트에 캐시를 적용해야지 계속 생각만 하다가 이렇게 캐시에 접근하게 되었다.

 

jpa에 영속성컨테스트라는 것이 있듯이 mybatis 에는 캐시가 있었다. 찾아보면서 알게된 내용을 간략하게 작성해보고자 한다.

 

mybatis를 적용하면 내장되어있는 캐시가 두 종류가 있다. 

  1. local session cache
  2. second level cache

위 두가지이다. readOnly 옵션은 second level cache에 속성이다.

 

1. Local session cache

local session cache는 무조건 적용이 되는 캐시이고 우리가 끌 수 없는 기능이다. 하지만 범위만큼은 수정이 가능하다. 

secone level cache는 mapper namespace 단위로 동작한다. 그렇기에 <cache />를 통해 쉽게 적용할 수 있다. 

먼저 local session cache부터 작성하겠다.

 

local session cache 는 SqlSession 객체마다 가지고 있는 캐시이다. 

앞서 말했듯이 local session cache는 범위를 조정이 가능한데 config파일에 아래와 같이 작성하면 적용 범위를 수정할 수 있다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
	PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<settings>
		<setting name="localCacheScope" value="STATEMENT" /> <!-- STATEMENT / SESSION -->
	</settings>
</configuration>
//출처: https://12bme.tistory.com/364

 

범위 속성은 SESSION과 STATEMENT 둘중 하나로 설정 가능하고 디폴트는 SESSION이다. 

SESSION은 트랜젝션이 실행하는 도중 캐시를 유지하는 것이다. 그렇기에 commit나 rollback, insert, update, delete가 일어나면 Local cache내 기록되어 있던 캐시가 사라진다. 

STATEMENT 는 mapper에 정의된 SQL 하나당 하나의 statement다. 즉 각 SQL마다 캐싱이 이루어지는 것이다. 

여기서 SESSION 설정은 한가지 문제가 있다.

SESSION으로 설정하면 동일한 SqlSession으로 반복 조회를 하면 계속 캐싱된 결과를 받게 된다. 매 조회마다 새로운 SqlSession을 받아서 처리하거나 SqlSession을 매번 clear 하지 않으면 계속 캐싱된 결과를 받게 될 것이다.

기본값은 SESSION이지만 캐싱을 방지하기 위해서 STATEMENT로 설정해야 한다.

단순한 SQL만을 사용했다면 STATEMENT 설정은 사실상 OFF 설정으로 봐도 된다.

출처: http://dveamer.github.io/backend/MybatisCache.html

 

Dveamer

현실에서 살고 있지만 이상에 대한 꿈을 버리지 못한 몽상가의 홈페이지 입니다. 개인적인 기록을 주 목적으로 하며 일상과 프로그래밍 관련 글을 포스팅합니다.

dveamer.github.io

 

 

2, Second level cache 

second level cache는 앞에서 언급한 것처럼 mapper namespace단위로 동작하기에 mapper.xml에 <cache />를 통해 적용할 수 있다. 

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>
  //출처: https://mybatis.org/mybatis-3/ko/sqlmap-xml.html#cache

 

local session chche와는 다르게 second level cache는 Session 범위 밖에서의 캐시사용 여부를 조정한다.

트랜젝션에서 commit을 해도 캐시 데이터가 계속 유지되는 것이다.

위의 옵션들을 살펴보자.

eviction는 어떤 방식으로 캐시 데이터를 처리할 것인다. 아래는 간략한 설명이다. 

  • LRU – Least Recently Used: 가장 오랜시간 사용하지 않는 객체를 제거
  • FIFO – First In First Out: 캐시에 들어온 순서대로 객체를 제거
  • SOFT – Soft Reference: 가비지 컬렉터의 상태와 강하지 않은 참조(Soft References )의 규칙에 기초하여 객체를 제거
  • WEAK – Weak Reference: 가비지 컬렉터의 상태와 약한 참조(Weak References)의 규칙에 기초하여 점진적으로 객체 제거

디폴트 값은 LRU이다.

flushInterval 은 양수로 셋팅할 수 있고 밀리세컨드로 명시되어야 한다. 디폴트는 셋팅되지 않으나 플러시(flush) 주기를 사용하지 않으면 캐시는 오직 구문이 호출될때마다 캐시를 지운다.

size는 양수로 셋팅할 수 있고 캐시에 객체의 크기를 유지하지만 메모리 자원이 충분해야 한다. 디폴트 값은 1024 이다.

여기서 readOnly 옵션이 나온다.

readOnly 속성은 true 또는 false 로 설정 할 수 있다.

readOnly는 second level cache에 있는 옵션으로 캐시된 객체의 원본을 리턴 할 것라고 한다. 게다가 그 객체는 변경할 수 없다. readOnly를 적용하지 않는 읽고 쓰는 캐시는 캐시된 객체의 복사본을 리턴 한다.

즉, 읽기만 하는 객체는 readonly 옵션을 적용해 준는 것이 성능향상을 이룬다.

 

이렇게 readOnly옵션을 확인하던중 mybatis내의 캐시도 알게 되었다. 

하지만 성능문제로 캐시 기능이 필요하다면 Mybatis가아닌 Redis, Encache와 같은 별도의 솔루션을 사용하는 것이 좋다고 하는데 아직 둘다 써보지를 못해서 모르겠다,,

 

차후 공부를 하면서 자세 알아봐야 겠다. 

 

참고

http://dveamer.github.io/backend/MybatisCache.html

 

Dveamer

현실에서 살고 있지만 이상에 대한 꿈을 버리지 못한 몽상가의 홈페이지 입니다. 개인적인 기록을 주 목적으로 하며 일상과 프로그래밍 관련 글을 포스팅합니다.

dveamer.github.io

 

https://12bme.tistory.com/352

 

[오픈소스] 마이바티스 cache-ref, cache 엘리먼트

cache-ref와 cache 엘리먼트는 캐시를 설정하는 엘리먼트입니다. 캐시는 매핑 구문과 파라미터 따라 사용 여부를 결정합니다. 매핑 구문과 파라미터에 따라 결정되기 때문에 사용자가 작성하는 메

12bme.tistory.com

 

http://idea-sketch.tistory.com/30

 

https://blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=tkstone&logNo=50193992290 

 

MyBatis 내장 cache 에 대해서

MyBatis 에는 2가지 내장 Cache  가 있다. 1) local session cache 2) second level cache   ...

blog.naver.com

 

https://12bme.tistory.com/364

 

[오픈소스] MyBatis 내장 cache에 대해서

MyBatis에는 2가지 내장 Cache가 존재합니다. local session cache, second level cache 두가지 입니다. local session cache는 임의로 켜거나 끌 수 없고, 무조건 활성화됩니다. 반면 second level cache는 mapper namespace 단

12bme.tistory.com

 

https://mybatis.org/mybatis-3/ko/sqlmap-xml.html#cache

 

MyBatis – 마이바티스 3 | 매퍼 XML 파일

Mapper XML 파일 마이바티스의 가장 큰 장점은 매핑구문이다. 이건 간혹 마법을 부리는 것처럼 보일 수 있다. SQL Map XML 파일은 상대적으로 간단하다. 더군다나 동일한 기능의 JDBC 코드와 비교하면

mybatis.org