반응형
"@Transactional(readOnly = true)를 사용하면 성능이 좋아진다."라는 말들을 들어봤을 것이다.그렇다면 왜 성능이 좋아지는 걸까? 그리고 항상 좋을까?에 대해 이번 포스팅에서 알아보려한다.JPA, RDBMS 둘다 최적화가 이뤄지기 때문에 각각 어떤 성능 최적화가 이뤄지는지 알아볼 것이다.(참고로 RDBMS는 MySQL 8.0 버전에 대해 다룬다.)JPA 수준의 최적화일반 트랜잭션의 경우 트랜잭션이 커밋될 때 JPA는 FlushMode.AUTO가 기본값이기 때문에 영속성 컨텍스트를 자동으로 플러시한다.하지만 @Transactional(readOnly=true)로 설정하면 Hibernate가 FlushMode를 MANUAL로 설정하여명시적으로 flush를 호출하지 않는 이상 flush가..
분산 시스템이 보편화되면서 효율적인 ID 생성 전략의 중요성이 더욱 커지고 있다.이번 포스팅에서는 DB에서 사용되는 여러 ID 생성 전략을 비교하고, Spring Boot와 JPA 환경에서의 구현 방법을 살펴보자.참고로, 각 전략의 장단점은 MySQL InnoDB 스토리지 엔진 기준으로 타 DBMS와는 차이가 있을 수 있다. Auto-Increment ID 전략Auto-increment는 가장 전통적인 ID 생성 방식이다.DB 테이블에 새 레코드가 삽입될 때마다 자동으로 증가하는 정수 값을 ID로 할당한다.@Entity@Table(name = "users")public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) /..
필자의 프로젝트는 총 2개의 EC2 인스턴스가 존재하고 각 서버에서는 총 2개의 스케줄링(배치) 작업이 중복 실행된다. 아래는 모바일 Push 알림 전송을 위해 사용하는 FCM에서 topic 기능을 사용하는데이 topic 개수 제한이 2,000개여서 주기적으로 topic을 해제할 필요가 있었다.따라서 약속 시간이 지난 모임들을 새벽 4시 마다 스케줄링하여 약속 논리 삭제와 topic 제거를 배치 처리하고 있다.아래의 update의 경우에는 중복 처리되어도 결과에 영향을 주진 않지만모든 서버가 동일한 작업에 대해 불필요하게 DB 커넥션을 사용해 동일한 쿼리를 DB에 요청하고 FCM과 통신할 필요는 없다.또한 아래 작업의 시간이 길어진다면 모든 서버들의 초기화 시간이 길어질 수 있다는 문제가 있다.@Tran..
서브쿼리는 쿼리의 여러 위치에서 사용할 수 있는데대표적으로 SELECT, FROM, WHERE 절에 사용될 수 있다.하지만 사용되는 위치에 따라 쿼리의 성능 영향도와 MySQL 서버의 최적화 방법은 완전히 달라진다.각 절마다 어떻게 최적화되는지 그리고 어떻게 쿼리를 작성해야 성능에 도움이 될지 살펴보자.SELECT 절에 사용된 서브쿼리SELECT 절에 사용된 서브쿼리는 내부적으로 임시 테이블을 만들지도 않고 비효율적으로 실행하지 않기 때문에서브쿼리가 인덱스만 적절히 사용한다면 크게 주의할 사항은 없다.(단, 상관 서브쿼리의 경우 다름) 일반적으로 SELECT 절에 서브쿼리를 사용하면 그 서브쿼리는 항상 컬럼과 레코드가 하나인 결과를 반환해야 한다.즉, 값이 NULL이든 아니든 관계 없이 레코드가 딱 1건..
많은 서비스들이 독립적인 기능을 수행하는 작은 단위의 서비스들로 구성된 MSA로 구축하면서서비스의 복잡도를 줄이고, 변경에 따른 영향을 최소화하고 작은 서비스별로 업무를 맡아 개발/배포를 하고 있다.하지만 이 작은 서비스들이 무수히 많아진다면 각 서비스들의 엔드포인트를 관리하기 쉽지 않을 것이다.또한 각 서비스마다 공통으로 들어가는 인증, 로깅같은 기능들을 중복으로 개발해야한다는 문제점도 있다.이러한 문제점을 해결하기 위해 등장한 것이 바로 API Gateway이다. API Gateway는 위 이미지와 같이 클라이언트와 각각의 서비스들 사이에 위치하게 된다. 클라이언트는 각 서비스의 엔드포인트 대신 API Gateway로 요청을 보내고요청을 받은 API Gateway는 라우팅 규칙에 따라 각 엔드포인트로..
세미 조인 (Semi Join)다른 테이블과 실제 조인을 수행하지는 않고, 단지 다른 테이블에서 조건이 일치하는 레코드가 있는지 없는지만체크하는 형태의 쿼리를 세미 조인이라고 한다.일반 조인과의 다른 점은 EXISTS나 IN 연산자를 서브쿼리와 함께 사용해서브쿼리의 조건을 만족하는 레코드는 가져오지 않고 만족하는지만 확인하는 것이다.-- IN을 사용한 세미 조인SELECT * FROM orders WHERE customer_id IN ( SELECT customer_id FROM customers WHERE country = 'KR');-- EXISTS를 사용한 세미 조인SELECT * FROM orders o WHERE EXISTS ( SELECT 1 FROM custo..