
조인은 한 데이터베이스 내 2개 이상의 테이블의 레코드를 조합하여 하나의 열로 표현한 것을 말합니다.
조인이 필요한 이유는 테이블 정규화와 깊은 연관이 있습니다.
데이터베이스 내 저장 공간을 효율적으로 관리하기 위해 정규화 과정을 거치면 테이블이 분리되는 경우가 많습니다.
이러한 경우 두 테이블 간에 관계라는 것이 형성 되고 이러한 데이터를 한번에 조회하는 경우에 효과적으로 검색하기 위해서 조인을 사용합니다.
조인의 종류로는 크게 내부/외부 조인이 있습니다.
내부 조인은 크게 다음과 같이 나뉩니다.
외부 조인은 조건문에 ㅁ나족하지 않는 행도 표시해주는 조인입니다. 즉, 이는 B테이블에 관련 데이터가 없더라도(null) 조인 결과에 포함시켜주는 조인입니다.
테이블 A와 테이블 B가 있을 경우, 테이블 A의 모든 데이터와 테이블 B에도 포함하고 있는 매칭되는 레코드를 포함하는 조인입니다.
테이블 B의 모든 데이터와 테이블 A에도 포함하고 있는 매칭되는 레코드를 포함하는 조인을 말합니다.
이는 조인으로는 구현이 불가하지만, UNION 예약어를 사용하여 구현이 가능합니다. 이는 합집합을 의미하며, 두테이블에 있는 모든 레코드를 결과로 나타냅니다.
❓ Join이 우선인가? 검색이 우선인가?
데이터베이스의 설계에서 데이터의 중복을 허용하지 않고, 저장 용량을 최소화해줌으로써 데이터베이스를 보다 효율적으로 설계하는 과정을 말합니다.
정규화의 주요 목적은 이상현상(anomalies)을 최소화하고 데이터베이스의 효율을 높이는 것입니다.
정규화는 테이블을 분해하는 방식에 따라 단계가 나뉘어져 있습니다.
데이터베이스는 볼륨이 커질수록 성능이 감소됩니다.
이를 해결하기 위한 대표적인 방법으로 파티셔닝과 샤딩이 있습니다.
파티셔닝은 하나의 테이블을 여러 하위 테이블로 분할하는 작업입니다. 파티셔닝의 특징은 물리적으로는 여러개의 테이블로 분리되어 있지만 사용자는 마치 하나의 테이블에 접근하는 것과 같이 사용할 수 있습니다.
파티셔닝의 종류
List Partitioning
데이터 값이 특정 목록에 포함되어 있는 경우 데이터를 분리해줍니다
Range Partitioning
데이터를 특정 범위 기준으로 분할 시 사용합니다.
Hash Partitioning
해시 함수를 사용하여 데이터 분할 시 사용합니다. 특정 컬럼의 값을 해싱하여 저장 시 파티션을 선택합니다. 이는 MySQL 공식 문서상에서 권장하지 않는 방식입니다.
Composite Partitioning
2개 이상의 파터셔닝을 조합하여 사용하는 방식입니다.
❓ 정규화와 파티셔닝의 차이점
정규화는 논리적인 설계 단계에서 이상현상을 해결하기 위한 기법으로, 그 과정 중에서 컬럼이 분리되는 것입니다. 파티셔닝은 물리적인 설계 단계에서 성능을 고려한 분할입니다.
샤딩은 동일한 스키마를 가지고 있는 여러 대의 데이터베이스 서버들에 데이터를 작은 단위로 나누어 분산 저장하는 기법을 말합니다.
이는 어떻게 보면 수평 파티셔닝의 일종입니다. 차이점은 파티셔닝은 모든 데이터를 동일한 컴퓨터에 저장하지만, 샤딩은 데이터를 서로 다른 컴퓨터에 분산한다는 점입니다.(서버 단위로 나눔) 물리적으로 서로 다른 컴퓨터에 데이터를 저장하기 때문에, 쿼리 성능 향상과 더불어 부하가 분산되는 효과까지 얻을 수 있습니다.
샤당은 일반적으로 데이터베이스 차원이 아닌 애플리케이션 레벨에서 구현하는 것이 일반적입니다.
샤딩은 물리적으로 독립된 데이터베이스 서버에 각각 분할하여 저장하기 때문에 조인이 어렵습니다. 또한, 하나의 데이터베이스에 집중적으로 데이터가 몰리게 되면 성능이 느려집니다.
객체와 관계형 데이터베이스 내 테이블 사이에서 자동 Mapping을 해주는 기술을 말합니다.
ORM 객체 지향 프로그래밍과 관계형 데이터베이스 간에 패러다임의 불일치로 인한 문제를 해결하기 위한 방안으로 나왔습니다.
개발자가 객체 지향적으로 프로그래밍을 하면, 이를 자동으로 ORM이 테이블로 매핑해주기 때문에 비지니스 로직에 집중할 수 있게 됐습니다. 또한, 객체지향적 프로그래밍을 사용함으로써 코드의 재사용성도 올라가게 됩니다. 하지만, 복잡한 쿼리를 구현하는 것에 한계가 있고, 잘못된 설계 및 구현 시 속도 저하의 원인이 될 수 있습니다.
제가 진행했던 프로젝트 내에서는 Hibernate를 사용하여 ORM을 구현하였습니다.
❓ MyBatis는 ORM이 아닐까?
아닙니다.
일반적으로 ORM은 객체와 관계형 데이터베이스 테이블 간의 매핑을 자동화하여, 개발자가 SQL을 직접 작성하지 않고도 데이터베이스 작업을 수행할 수 있게 해주는 기술을 의미합니다.
반면, MyBatis는 SQL 쿼리와 객체 간의 매핑을 지원하지만, SQL 쿼리를 개발자가 직접 작성해야 합니다. 즉, MyBatis는 데이터베이스 테이블과 자바 객체 간의 자동 매핑보다는, SQL 쿼리의 실행 결과를 객체에 매핑하는 데 초점을 둡니다.
RDBMS는 정해진 스키마 형태에 따라 명확한 데이터 구조를 보장하지만, 이로 인해 스키마 변경이 어려워 유연성이 떨어집니다. 하나의 테이블 내 중복된 튜플이 존재하지 않습니다. 하지만, 시스템이 커질 경우 JOIN문이 많아져 복잡한 쿼리가 발생합니다. 또한, 성능 향상을 위해서 Scale-up만 지원합니다.
NoSQL(Not Only SQL)은 테이블 간의 관계를 정의하지 않습니다.
NoSQL은 데이터의 추세가 단순한 형태의 대용량 데이터라는 특징을 띄고, 대용량 트래픽을 감당하기 위해 기존의 RDBMS에서 Scale-up을 통한 성능 개선은 비용이 기하급수적으로 증가될 것으로 예상되었기 때문에 데이터의 일관성을 포기화되 데이터를 여러대에 분산하여 저장하는 Scale-Out을 목표로 NoSQL이 등장했습니다.
NoSQL에서는 스키마가 없기 때문에 유연하며, 자유로운 데이터 구조를 가질 수 있습니다. 또한, 언제든지 저장된 데이터를 조정하고 새로운 필드 추가가 가능합니다.
데이터 분산이 용이하여 성능향상을 위한 Scale-up과 Scale-out이 모두 가능합니다.
하지만, 데이터 중복 문제가 발생하며, 이로인해 데이터 변경 시 해당 데이터를 갖는 모든 곳에 데이터를 수정해줘야 합니다. 데이터 구조가 명확하지 않아 구조를 정하는 것이 어려울 수 있습니다.
===
RDBMS는 명확한 데이터 구조를 보장합니다. 하지만 한번 생성된 스키마의 변경이 어려워 유연성이 떨어집니다.
NoSQL은 스키마가 없어 자유로운 데이터 구조를 가집니다. 하지만 정해진 구조가 없어 데이터 구조 결정이 어렵습니다.
RDBMS는 스케일업만 지원합니다.(트레픽이 많아지면, 비용이 기하급수적으로 증가)
NoSQL은 스케일업과 스케일아웃 모두 지원합니다.
테이블 간의 관계성
RDBMS는 중복없이 한번만 저장이 가능합니다. 하지만, 시스템 규모가 커짐에 따라 JOIN이 많아지는 복잡한 쿼리가 만들어 질 수 있습니다.
NoSQL은 중복이 다량 발생하며, 중복 데이터 변경 시 모든 컬렉션에서 수정해줘야 합니다.
데이터 수정이 RDBMS가 더 빠릅니다.
RDBMS는 데이터 구조의 변경 여지가 없는 경우 사용하는 것이 좋고, 복잡한 형태의 트랜잭션 처리와 쿼리가 필요한 경우 사용하는 것이 좋습니다. 또한, 데이터의 일관성이나 정확성이 중요한 곳에 사용됩니다.(은행, 일관성)
NoSQL은 규모 분산 데이터, 빠른 읽기/쓰기 처리 속도, 유연한 데이터 구조가 필요한 경우 사용하는 것이 좋습니다.(소셜 네트워크, 확장성)