본문 바로가기

Spring

SELECT 문으로 데이터 랜덤으로 가져올 경우에 대한 성능 테스트

SELECT문으로 데이터를 가져올 때 랜덤으로 순서가 바뀌어야하는 요구사항이 존재하였습니다.

 

해당 기능을 구현하기 위해서 2가지 방안을 생각했었습니다.

 

1. DBMS에서 ORDER BY RANDOM()를 통해 랜덤하게 가져오도록 개발

2. SELECT 문으로 데이터를 가져온 후 웹 애플리케이션단에서 랜덤하게 순서변경 로직 개발

 

1번째 방안으로 개발을 진행한 후 성능테스트 이후 성능저하가 심할경우 2번째 방안으로 개발하도록 계획을 수립하였습니다.

 

쿼리문

	<select id="getByToken" parameterType="java.lang.String" resultMap="ReceiverInfo">
		select receiver_key, user_id, amount, is_received from tb_receiver
		where token = #{value}
	</select>

	<select id="getByTokenRandom" parameterType="java.lang.String" resultMap="ReceiverInfo">
		select receiver_key, user_id, amount, is_received from tb_receiver
		where token = #{value} order by RANDOM()
	</select>

 

테스트 코드 

	@Test
	public void 랜덤으로_정렬된_데이터_가져오기() {
		receiverDao.getByTokenRandom("Asq");		
	}
	
	@Test
	public void 정렬하지_않는_데이터_가져오기() {
		receiverDao.getByToken("Asq");
	}

 

테스트는 다음과 같이 진행하였습니다.

10회 이상 진행 후 수행되는 시간의 평균값을 구함

 

테스트 결과(테스트 데이터 건수 6,000건)

랜덤으로 정렬된 데이터를 가져올 때가 정렬되지 않은 데이터를 가져올때 보다 약 5배가량 빠른것을 확인할 수 있었습니다. 예상과 다르게 왜 이런결과가 나올걸까요??

혹시 데이터 건수가 많을 경우 다른 결과가 나올 수 있을 것 같아 더 많은 데이터 건수로 테스트를 진행해보았습니다.

 

테스트 결과(테스트 데이터 건수 30,000건)

테스트 데이터가 증가됨에 따라 랜덤으로 가져올 때 수행시간이 더 걸렸음을 확인할 수 있었습니다. 테스트 데이터 건수를 더 증가시켜 확인해보았습니다.

 

테스트 결과(테스트 데이터 건수 100,000건)

 

테스트 결론 : 테스트 데이터 건수가 증가될 수록 성능저하가 발생합니다. 

 

그렇다면 왜 랜덤하게 가져올 때 성능저하가 발생하는 것일까요??

 

h2 데이터베이스에서는 쿼리에 대한 실행계획 확인하기 어려워 maria db에서 실행계획을 확인하여 진행하였습니다.

 

실행계획 쿼리

EXPLAIN SELECT * FROM tb_receiver ORDER BY RAND()

 

실행계획을 살펴봤을 때 extra를 보면 Using temporary; Using filesort;로 임시테이블을 사용한다고 나타나있습니다.

그렇다면 임시테이블이 어디에 생성되었는지 확인해볼필요가 있습니다.

 

서버상태 변수 확인

SHOW SESSION STATUS LIKE 'Created_tmp%';

 

Created_tmp_disk_tables : 21 

 

디스크에 임시테이블이 생성된 것을 확인할 수 있었습니다.  디스크에 임시테이블 or 임시파일은 데이터베이스의 성능저하를 줄 수 있다고 합니다. 랜덤하게 데이터를 가져올 때 디스크에 임시테이블을 생성하기 때문에 데이터베이스의 성능이 저하됨을 알 수 있었습니다.

 

확정성과 성능을 고려한 결과, 1번째 방안보다는 2번째 방안으로 개발을 진행하는 것이 좋아보입니다.

 

 

참조