IT/SQL

[mariaDB] 7~8초 걸리던 select 쿼리 빠르게 하기

월공 2023. 6. 23. 09:02
728x90
300x250

실 서비스중인 모바일 페이지가 있는데, 특정 페이지를 진입하면 로딩이 너무 느려진다고 클레임이 들어와서 
확인하게 된 쿼리이다.
(정말 더럽게 짜여져있는 레거시 페이지라 하나 하나 지우면서 분석했다. 물론 내가 만든건 아니다.)

아래와 같은 쿼리였는데 JOIN 도 없고 단순히 테이블 한곳에서 Select 해서 가져온다.
쿼리에서 대충 짐작 할 수 있다시피 ,  그냥 단순히 특정 회원에게 알림이 쌓이는 테이블이고, read_date 에 읽은 날짜가 기입되고, 읽기전에는 0000-00-00 식으로 기본으로 박혀있다.

SELECT COUNT(*) 
FROM TABLE 
WHERE del_yn = 0 	 	#사용여부
AND user_id = "111111"  #회원 고유 ID
AND read_date = "0000-00-00 00:00:00"; #읽은 날짜

테이블 용량은 대충 13GiB 가량 되며,  컬럼은 20개, 총 데이터 Row 수는 대략 2000만개 정도 되는 테이블이다.

정말 단순한 select 쿼리 라고 생각했는데 해당 부분이 실행이 되는데에 7~8 초 걸린다 해서 콧방귀를 뀌면서 직접 해봤다.

이왜진??

쿼리가 느리다하면 보통 JOIN 이 여러개 걸려있을때만 그런줄 알았는데 신기한 경험을 하게 될줄이야

찾는 컬럼들에 인덱스 키는 당연히 걸려있었다.

그래서 우선 줄일수 있는 WHERE 절 조건 부터 확인했다.

생각해보니 del_yn 은 사용여부 컬럼인데 , 사용자한테 알림 (새 소식) 을 보여주는데 굳이 해당 데이터를 사용 여부를 체크할 필요가 있을까 싶었고 사이드 이펙트 체크를 하기위해 다른곳에서 해당 테이블의 사용여부 컬럼 조건으로 값을 가져가는 부분이 있는지 체크했는데 없었어서,
그냥 의미없이 들어가있는거라 판단하고 바로 del_yn 은 조건에서 제외시키기로 한다.
del_yn 은 1과 0 만 들어가는 TINYINT 데이터 형식임에도 불구하고 해당 부분만 빠져도 2.5초 가량 실행시간이 나왔는데 이것만해도 상당히 성능개선이 많이되었다.

그리고 '0000-00-00 00:00:00' 으로 들어가 있는 부분은 NULL 로 찾는게 훨씬 빠를텐데 이미 다른 페이지에서 애초에 해당 테이블에 insert 를 할때 PHP 단에서 기본값으로 죄다 read_date 컬럼에 '0000-00-00 00:00:00' 라고 박아놔버렸기도하고 이미 쌓여있는 2천만개의 데이터를 이제와서 죄다 고치긴 일이 너무 커질것 같아서 저 부분을 좀 더 보완 할 수 있을까 고민을 해봤는데 mariaDB 에서의 CAST 가 답이었다.

SELECT COUNT(*)
FROM TABLE
WHERE user_id = "111111"  AND CAST(read_date AS INT) = 0

INT 형이 아무래도 검색속도가 빠르기도하고
어차피 read_date 에 값이 들어가있으면 CAST 로 뽑았을경우 무조건 0 이 아니게 되어버리니
위처럼 뽑아오니까 성능 개선이 대폭 되었다.

 

위에도 썻다시피, join 걸려있는것도 없는데 단순 select 문이 이렇게 느릴수도 있구나,
단순히 키값 걸었다고 무조건 빠르지 않다는것도 , TINYINT 데이터 형식의 1,0 만 들어가있는 컬럼을 찾는 WHERE 절 조건을 빼고 안빼고 차이가 이렇게 크다는것도 느끼게되었다.

728x90
300x250