개발놀이터

데이터베이스 조인 연산은 성능에 영향을 줄까? 안줄까? 본문

CS 지식/데이터베이스

데이터베이스 조인 연산은 성능에 영향을 줄까? 안줄까?

마늘냄새폴폴 2024. 7. 22. 20:44

포스팅을 작성하게 된 계기는 해당 포스팅을 보고 나서입니다. 

 

https://blog.naver.com/shino1025/223124936920

 

Table Join은 정말 느리지 않은가?

RDBMS의 쿼리에서 빼놓을 수 없는 핵심 기능 중 하나가 바로 "JOIN"이다. 조인은 각기 ...

blog.naver.com

 

사실 6개월전에 봤던 게시글인데 오랜만에 북마크 정리하다가 보게 됐습니다. 

 

6개월전에 볼 때와 크게 다르지 않을 것이라고 예상했던 것과 다르게 꽤 많이 다르게 보였습니다. 

 

이전에 봤을 땐 그저 읽고 이해하기만 했는데 이젠 다른 생각이 들기 시작했습니다. 

 

조인 연산, 성능에 영향을 줄까? 안줄까?

일단 직관상 영향을 줄 것처럼 생겼습니다. 테이블을 하나만 조회하는 것과 두개, 세개를 조합해서 조회하는 것은 단순히 하나의 테이블에서 조회하는 것 이외에 테이블을 엮는 과정이 추가적으로 필요하기 때문이죠. 

 

하지만 이에 대해 찾아보면 많은 사람들이 "조인 연산은 성능에 영향을 주지 않는다" 라고 말합니다. 이 답에 대해 느려지는가? 느려지지 않는가?에 대한 고찰을 한 것이 위의 포스팅입니다. 

 

위의 포스팅은 제 생각과 반대되는 글이지만 정말 잘 쓰여진 글입니다. 한번 읽어보시는 것을 추천드립니다. 

 

간단하게 정리하자면 "수많은 사례에서 조인 연산을 없애는 비정규화 (Denormalization) 로 성능을 최적화 해왔다." 라는 논리를 사용하고 있습니다. 

 

하지만 해당 포스팅에서 가져온 사례는 속된말로 미친듯한 데이터가 존재하는 트위터, 배달의민족 같은 서비스라는 것입니다. 이에 대한 상수가 있고 이 부분은 감안하고 보셔야될 것 같습니다. 또한, 이는 뒤에서 설명하겠지만 두 서비스 모두 NoSQL을 사용한다는 것을 염두해둬야합니다.

 

왜 제가 "조인 연산은 느려지지 않는다" 입장인지 제 논리를 펼쳐보도록 하겠습니다. 그러면서 어떤 부분이 직관적으로 느려질 것 같은지에 대해서 짚으면서 진행하겠습니다. 

 

테이블 두개를 합치는 과정

테이블 두개를 합칠 때 어떤 과정이 내부적으로 일어나는지 알아야합니다. 

 

우선 RDBMS에는 Optimizer (이하 옵티마이저) 라는 놈이 있습니다. 이놈은 테이블을 합칠 때 어떤 연산이 가장 적합한지 계산해내는 놈입니다. 

 

일반적으로 테이블을 합치는 가장 합리적인 연산은 세가지로 추려낼 수 있고 이에 대해서는 아래의 링크에 자세하게 설명되어있습니다. 

 

https://coding-review.tistory.com/537

 

데이터베이스 조인 알고리즘과 쿼리 최적화

이번 포스팅은 데이터베이스의 조인 알고리즘과 쿼리를 최적화하는 방법에 대해서 공부해보고 정리해보겠습니다.  데이터베이스를 깊이있게 공부하면 공부할수록 왜 큰 기업들이 DBA라는 직

coding-review.tistory.com

 

옵티마이저가 테이블을 조인할 때 계산해야 하는 경우의 수는 팩토리얼연산입니다. 즉, 테이블이 3개 합치면 3! = 6 개의 경우의 수를 계산해야 한다는 것이죠. 

 

이게 많아지면 오버헤드가 생길 수 있겠죠. 하지만 팩토리얼 연산이 아무리 위협적이라고 하더라도 현대의 컴퓨터는 1초에 수십억개의 연산을 처리하는 기계입니다. 

 

또한, 옵티마이저는 모든 경우의 수를 계산하는 것이 아니라 허수는 제외하는 최적화 알고리즘을 가지고 있습니다. 

 

 

비정규화로 읽기 성능 최적화

상당히 오해하기 좋은 워딩입니다. 처음엔 데이터 셋이 크고 읽기 성능을 최적화하고 싶으면 비정규화를 고민해봄직하다는 인상을 줬습니다. 하지만 그건 맞지않습니다.

 

일단 정규화에 비해 INSERT, UPDATE, DELETE에 대한 연산이 기하급수적으로 늘어나 해당 연산이 필요한 테이블은 쓸 수조차 없습니다. 

 

특히, 비정규화를 고민할만큼 데이터 셋이 정말 큰 상황에서 앞선 세개의 연산이 필요하다면 절대 사용할 수 없을 것입니다. 

 

또한, 비정규화는 조인에 대한 결과가 단순하거나 예측 가능한 테이블만 사용할 수 있습니다. 왜냐하면 비정규화는 그 특성상 데이터의 개수가 N x M이 되기 때문에 테이블을 비대하게 만들기 때문입니다.

 

그리고 위의 포스팅에서 언급한 배달의민족에서 비정규화로 읽기 성능 최적화의 부분은 MongoDB를 사용한 것으로 나옵니다. 관계라는 것이 정해져 있지 않은 NoSQL에서 JOIN을 쓰는 것은 당연히 RDBMS에 비해 비싼 것이 당연합니다. 

 

배달의민족뿐만 아니라 트위터도 제가 알기로는 NoSQL을 사용한다고 알고 있습니다. 트위터같은 SNS는 데이터의 일관성이 크게 중요하지 않기 때문에 ACID대신 BASE속성을 따르는 것이 압도적으로 유리하기 때문입니다. 

 

때문에, 위의 포스팅에서도 언급했듯이 MongoDB 진영에선 조인을 지양하라고 나오지만 RDBMS 진영에선 그런 얘기가 일절 없는 것을 알 수 있죠. 

 

NoSQL의 조인과 RDBMS의 조인을 동일선상에 놓고 조인에 아무런 오버헤드도 없는건 이상하다! 라고 주장하기엔 조금 설득력이 부족합니다.

 

결국, "많은 기업이 조인연산을 이유로 비정규화를 이용해 읽기 성능을 최적화했다." 라는 것은 조금 성급한 일반화가 아닌가 생각이 드네요.

 

 

그럼 조인은 성능에 영향이 없냐?

마냥 그렇다고 답변하기도 좀 그럴 것 같습니다. 왜냐하면 LEFT JOIN은 확실히 성능에 영향을 줍니다. 아마 LEFT JOIN을 많이 사용하기 때문에 조인이 성능에 영향을 준다고 잘못 알려진 것이 아닐까 싶습니다. 

 

때문에 RDBMS 진영에선 LEFT JOIN을 최적화하는 방법에 대해서 소개하고도 있죠. 

 

https://dev.mysql.com/doc/refman/8.4/en/outer-join-optimization.html

 

MySQL :: MySQL 8.4 Reference Manual :: 10.2.1.9 Outer Join Optimization

10.2.1.9 Outer Join Optimization Outer joins include LEFT JOIN and RIGHT JOIN. MySQL implements an A LEFT JOIN B join_specification as follows: Table B is set to depend on table A and all tables on which A depends. Table A is set to depend on all tables (

dev.mysql.com

 

왼쪽 테이블의 값을 기준으로 계속해서 값이 늘어나면 (가져오는 데이터 셋이 커지면) 성능에 악영향을 주는 것은 많이 알려진 사실입니다. 

 

제가 기존에 알고있던 비정규화는 굉장히 제한적으로 사용할 수 있다는 것과 옵티마이저가 최적화된 조인 연산을 수행해준다는 것과 별개로 조인 성능에 대한 구체적인 수치가 있을까 싶어서 논문을 뒤져봤습니다. 

 

SQL Performance Explained.pdf
1.19MB

 

해당 논문(책)에 잘 나와있습니다. 혹시나 읽으실 분들을 위해 쪽수를 알려드리자면 Chapter 3 Performance and Scalability 부분입니다. 

 

때문에 LEFT JOIN에 대해서는 확실히 조인을 수행하면 속도가 느려지는 것은 사실이지만 이것이 조인 때문이 아니고 LEFT JOIN의 특성상 데이터가 계속 배수로 늘어나는 특징 때문에 데이터 셋이 커져 벌어지는 현상이라는 것을 알아주시면 좋을 것 같습니다. 

 

 

그래서 조인이 성능에 영향을 준다는거냐 안준다는거냐

조인 자체는 성능에 영향을 주지 않습니다. 하지만 LEFT JOIN같은 특정 연산이 데이터 셋을 많이 가져오는 특징 때문에 성능이 안좋아질 수는 있다는 것입니다. 

 

이 결론은 JWT자체는 stateless하지만 결국 구현하려면 stateful하게 구현해야한다는 것과 결론이 일맥상통합니다.

 

 

마치며

맨 처음 소개했던 포스팅에서도 언급했듯이 "조인은 오버헤드가 존재하니까 비정규화를 쓰라는 얘기가 아니다" 라는 것을 미루어 봤을 때 작성자분이 한 발 물러난 것 처럼 보이긴 합니다. 

 

하지만 글을 읽는 내내 본인의 확신에 가득찬 워딩때문에 의구심을 가지게 되는 것은 사실이었습니다. 의도치않게 주장을 반박하게 되었지만 그 점을 제외하고서도 짜임새가 좋은 글이어서 한번쯤 보시는 것을 추천드립니다. 

 

이렇게 조인이 성능에 영향을 주는지 안주는지에 대해서 정리해봤습니다. RDBMS를 쓴다면 조인에 대한 오버헤드에 대해서 맘놓고 쓰세요 ㅎㅎ.. 대신 인덱싱같은 작업이 필요하긴 하지만요. 

 

긴 글 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요!