데이터베이스
데이터베이스는 여러 응용 시스템들의 통합된 정보들을 저장하여 운영할 수 있는 공용 데이터를 구조화 해놓은 집합체이다.
같은 데이터가 서로 다른 목적을 가진 여러 응용 서비스에 중복되어 사용될 수 있다는 것이다.
데이터 베이스를 ‘데이터의 집합’이라고 정의한다면 DBMS(DataBase Management System)는 이 데이터 베이스를 관리, 운영하는 역할을 한다. 또한 데이터 베이스는 여러 명의 사용자나 응용 프로그램이 공유하고 동시에 접근 할 수 있어야 한다.
사용 목적
데이터베이스가 존재하기 이전에는 파일 시스템을 이용하여 데이터를 관리하였고 현재도 부분적으로 사용되고 있지만
기술이 발전함에 따라 서비스의 규모가 비대해지면서 상이한 시스템간 데이터를 공용으로 사용하기 시작했고 이에 따라 다양한 데이터를 효과적으로 관리할 수 있는 방법이 요구되었는데 이를 해소하기 위해 필연적으로 체계화된 데이터베이스가 등장하게되었다.
데이터베이스의 특징
데이터베이스의 의미는 효율에 있다.
- 통합 데이터 - Integrated Data
여러가지 데이터를 통합하여 저장하는데 중복된 정보가 있다면 용량 낭비가 발생하기 때문에 데이터베이스는 중복된 정보에 대해 데이터를 통합하여 자료의 중복을 최소화한 데이터의 모임으로 구성한다. - 저장된 데이터 - Stored Data
사진 혹은 영상 파일을 하드디스크나 SSD에 저장하는 것 처럼, 데이터베이스도 컴퓨터가 접근할 수 있는 매체에 데이터를 저장한다. - 운영 데이터 - Operational Data
데이터베이스는 주로 조직의 목적을 위해 존재하고 활용되는 운영 데이터를 다루는데 주로 이용된다.
만약 휘발성으로 사용되는 정보라면 굳이 데이터베이스에 저장하는 것이 아닌 메모리 같은 임시 저장소에 저장하면 되는 것이다. - 공유 데이터 - Shared Data
데이터베이스를 사용하는 근본적인 이유 중 하나로 하나의 컴퓨터에서 사용되는 저장소가 아닌 여러 시스템들이 접근하여 사용할 목적으로 통합 관리되는 데이터를 말한다.
기능 특징
데이터베이스는 위에서 알아본 특징을 가진 데이터를 효율적으로 관리하기 위해 다음과 같은 기능을 제공한다.
실시간 접근성(Real-Time Accessibility)
- 데이터베이스는 사용자의 요구에 신속하고 정확한 응답이 가능해야 한다.
계속적 변화(Continue Evolution)
- 현실 세계의 변화를 반영하기 위해 새로운 데이터의 삽입, 삭제, 갱신이 이루어저 항상 최신의 데이터를 유지하는 것을 말한다.
동시 공용(Concurrent Sharing)
- 다수의 사용자가 동시에 같은 내용의 데이터를 이용할 수 있어야 한다.
내용 참조(Content Reference)
- 데이터베이스에 있는 데이터를 참조할 때 사용자의 요구에 따른 데이터 내용으로 데이터의 위치나 주소로 데이터를 찾는것을 말한다.
구조
언어
사용 목적이 다른 엑셀과 데이터베이스를 비교하는건 어불성설이지만 굳이 비교를 하자면 엑셀은 함수를 사용하지만 주로 공식 기반이며 스프레드시트 구조 범위 내에서 작동하고 개인 사용자 중심으로 구성되어있다. 하지만 데이터베이스는 SQL이라는 고유 언어를 통해 삽입, 삭제, 수정, 조회 등 동적인 결과를 만들어 낼 수 있다.
Category | Commands |
---|---|
DDL (Data Definition Language) | CREATE, ALTER, DROP, TRUNCATE |
DML (Data Manipulation Language) | SELECT, INSERT, UPDATE, DELETE |
DCL (Data Control Language) | GRANT, REVOKE |
TCL (Transaction Control Language) | COMMIT, ROLLBACK, SAVEPOINT |
DBMS(Database Managerment System)
관계형 모델
DBMS는 단어 그대로 데이터베이스를 관리하는 소프트웨어이다. 데이터베이스는 특정 조직의 업무를 수행하는 데 필요한 상호 관련된 데이터들의 복잡한 모임인데, DBMS는 이러한 데이터베이스의 데이터들을 효율적으로 저장하고 검색하고 수정하고 삭제하고 보호할 수 있도록 도와준다.
DBMS는 1세대부터 5세대까지 다양한 종류와 모델이 있지만 현재 주요하게 사용되는 모델은 4세대 관계형 모델로 RDBMS라고 불리운다.
이 모델은 데이터를 컬럼(column)과 로우(row)를 이루는 하나 이상의 테이블(또는 관계)로 정리하며, 고유 키(Primary key)가 각 로우를 식별한다. 로우는 레코드나 튜플로 부른다.일반적으로 각 테이블/관계는 하나의 엔티티 타입(고객이나 제품과 같은)을 대표한다.
로우는 그 엔티티 종류의 인스턴스(예: “Lee” 등)를 대표하며 컬럼은 그 인스턴스의 속성이 되는 값들(예: 주소나 가격)을 대표한다.
Key
테이블의 각 로우에는 저만의 고유 키(key)가 있다. 한 테이블 안의 로우는 다른 테이블들의 로우로 연결이 가능한데, 이는 연결된 로우의 고유 키를 위한 컬럼을 추가함으로써 이루어진다. (이러한 컬럼들은 외래 키로 부른다)
관계
관계는 테이블 간에 둘 다 존재한다. 이 관계들은 일대일, 일대다, 다대다, 이렇게 세 가지 형태로 이루어진다. 대부분의 관계형 데이터베이스들은 각 로우의 각 컬럼이 하나의 값만을 보유할 수 있도록 설계되어 있다. (값은 원자적이다)
관계란 같은 속성을 지닌 튜플의 모임으로 정의된다. 튜플은 일반적으로 오브젝트와 그 오브젝트의 정보를 대표한다. 오브젝트는 일반적으로 물리적인 오브젝트나 개념을 가리킨다. 관계를 일반적으로 여러 열이나 컬럼으로 조직된 테이블로 기술하기도 한다. 속성에 의해 참조된 모든 데이터는 동일한 도메인에 있으며 동일한 제약을 따른다.
제약
제약(constraint)들을 이용하면 속성의 범위에 추가적으로 제한을 둘 수 있다. 이를테면 제약은 주어진 값의 속성을 1부터 10 사이의 정수로 제한할 수 있다. 각 속성이 관련 도메인을 소유하고 있으며, 여기에 도메인 제약이 존재한다. 관계형 모형의 두 가지 주된 원칙은 개체 무결성과 참조 무결성이다.
트랜잭션
데이터베이스 관리 시스템(DBMS)이 효율적이고 정확하게 운용되기 위해서는 ACID 트랜잭션을 갖추고 있어야 한다.
저장 프로시저
RDBMS 내의 대부분의 프로그래밍은 저장 프로시저(SP)를 이용하여 이루어진다. 때때로 프로시저는 시스템 안팎으로 전송되는 정보의 양을 줄이는데 큰 기여를 한다. 보안을 위해 시스템 매니저는 저장 프로시저에만 접근 권한을 주고 테이블에 직접 주지 않을 수도 있다.
정규화
정규화는 관계형 모델의 필수적인 부분으로 단순하지 않은 도메인(비원자성 값)과 데이터 중복을 제거하기 위해 설계된 프로시저들의 모임을 말하며, 데이터 조작의 변칙과 데이터 무결성의 손실을 예방한다.
관계형 데이터베이스는 사용자에게 데이터를 관계로서 표현한다.
즉, 행과 열이 있는 구조화된 테이블로 구성되어 데이터 무결성을 강화하고 효율적인 쿼리를 가능하게 한다. 테이블 간에 정의된 관계를 사용하여 데이터 일관성을 보장하고 SQL을 통한 쉬운 검색을 보장하는데, 이는 업무 변화에 대한 적응력이 높아 변화하는 업무에 쉽게 활용하며 유지보수가 용이하다는 특징 덕에 생산성 역시 향상되지만 다른 DBMS 보다 더 많은 자원이 활용되어 시스템의 부하가 높고, 테이블 관계가 복잡해짐에 따라 쿼리 또한 복잡해지기 때문에 적절한 질의를 삽입하는것이 역시 성능에 지대한 영향을 끼친다.
성능
Disk I/O
데이터베이스는 하나의 파일 시스템이고 데이터베이스의 성능 이슈는 디스크 I/O
를 어떻게 줄이느냐에서 시작된다.
여기서 말하는 디스크는 컴퓨터의 하드 디스크를 말하고 정확히 디스크 I/O
란 Disk I/O(%)
라고 하며,
5초동안의 디스크 사용률을 보여주는데 디스크 드라이브의 플래터(원판)을 돌려서 읽어야 할 데이터가 저장된 위치로 디스크 헤더를 이동시킨 다음 데이터를 읽는 것을 의미한다. 이렇게 데이터를 처리하게 될 경우 디스크에서 물리적으로 액세스 암(Arm)이 움직이면서 헤드를 통해 데이터를 읽고 쓰기 때문에 용량은 크지만 매우 느리다는 단점이 존재한다.
SQL을 이용해 데이터 파일에 데이터를 저장하고 출력 시에 DB 버퍼 캐쉬
에 데이터가 없을 경우 디스크를 통하여 데이터를 버퍼 캐쉬에 저장한 후 결과를 주게 되는데 실제로 버퍼 캐쉬가 없다면 물리적 디스크 I/O
가 필요한 경우, 서버 프로세스가 디스크에서 원하는 블록을 가져오고 난 후 같은 데이터를 원할 경우 경합이 발생하여 대기 시간이 길어진다.
결국 데이터를 읽는데 걸리는 시간, 다른 말로 디스크의 성능은 디스크 헤더를 움직여서 읽고, 사용할 위치로 옮기는 단계에서 결정되고 디스크 헤드를 한 번 이동하여 DB 버퍼 캐쉬에 얼마나 많은 데이터를 한 번에 기록할 수 있는지가 성능 평가의 지표가 된다.
순차 I/O와 임의I/O
- 순차I/O : 연속적인 순서로 데이터에 액세스하여 헤드 움직임이 최소화 되기 때문에 디스크 성능을 최적화 할 수 있다.
- 임의I/O : 비순차적 디스크 위치에서 데이터를 검색하므로 헤드 이동 역시 증가하여 성능에 악영향을 미친다.
데이터베이스 쿼리 튜닝은 데이터 액세스 패턴을 최적화하여 임의 I/O를 줄이는 것을 목표로 한다.
이는 인덱스 최적화, 쿼리 재구성, 적절한 데이터 구성과 같은 기술을 통해 순차 액세스를 향상 시키고 임의 I/O를 최소화 하는걸로 해소할 수 있다.
인덱스를 사용하면 데이터를 논리적으로 구성하여 더 빠르게 검색할 수 있으므로 임의 디스크 읽기의 필요성이 줄어들게 되고 쿼리 재구성에는 가능할 때마다 순차적으로 데이터에 액세스 하도록 쿼리를 최적화하는 작업이 포함된다.
또한 클러스터형 인덱스 또는 적절한 분할 전략과 같은 효율적인 데이터 저장 구조는 무작위 액세스 패턴을 순차적 패턴으로 변환하는데 도움이 될 수 있다. 하지만 현실에서는 대부분의 I/O 작업이 임의 I/O 이다. 임의 I/O 를 순차 I/O 로 바꿔서 실행할 수는 없을까? 이러한 생각에서부터 시작되는 데이터베이스 쿼리 튜닝은 임의 I/O 자체를 줄여주는 것이 목적이라고 할 수 있다.
데이터베이스 풀
Connection Pool
클라이언트의 요청에 따라 어플리케이션에서 데이터베이스에 접근하기 위해서는 연결이 필요하고 요청에 따라 데이터베이스에 대한 연결을 생성하는 것은 비용적인 측면에서 리스크가 크기 때문에 사용량에 따라 적정량의 커넥션을 미리 생성해 놓고 유지 관리 및 삭제함으로써 리소스를 최적화 하고 관련된 오버헤드 비용을 줄일 필요가 있다.
Connection pool
은 이를 해결하기 위한 방법으로 연결을 여러 개 생성하고 공간(주로 캐시)에 저장해 이 공간의 Connection을 필요할 때 꺼내 쓰고 반환하는 기법을 말한다. 이는 풀의 기존 연결을 재사용함으로써 모든 요청에 대해 새 연결을 설정하는데 관련된 리소스 집약적인 프로세스를 최소화 하는데 효과적이다.(새로운 연결을 설정하는데 드는 비용에는 네트워크 대기 시간, 인증 및 리소스 할당 등이 포함된다.)
DB 접근 단계
1. 애플리케이션 로직은 DB 드라이버를 통해 커넥션을 조회한다.
2. DB 드라이버는 DB와 TCP/IP 커넥션을 연결한다.
물론 이 과정에서 3 way handshake 같은 TCP/IP 연결을 위한 네트워크 동작이 발생한다.
3. DB 드라이버는 TCP/IP 커넥션이 연결되면 ID, PW와 기타 부가정보를 DB에 전달한다.
4. DB는 ID, PW를 통해 내부 인증을 완료하고, 내부에 DB 세션을 생성한다.
5. DB는 커넥션 생성이 완료되었다는 응답을 보낸다.
6. DB 드라이버는 커넥션 객체를 생성해서 클라이언트에 반환한다.
이렇게 요청에 따라 그때 그때 커넥션을 만들게 된다면 DB는 물론, 애플리케이션 서버도 TCP/IP 커넥션을 새로 생성하기 때문에 불필요한 리소스 낭비를 유발하게 되고 자연스레 고객이 애플리케이션을 사용할 때 SQL을 실행하는 시간 뿐만 아니라 커넥션을 만드는 시간까지 추가되어 결과적으로 응답 속도 마저 저하되기 때문에 사용자 경험에 악영향을 줄 수 있다.
DB 접근 단계 feat. connection pool
- 초기화
- 애플리케이션 시작 시 최소 및 최대 연결, 시간 초과 등과 같은 매개변수를 구성하여 커넥션 풀을 구성하고 초기화한다.
- 연결 요청
- HTTP 요청에 따라 데이터베이스와 상호 작용해야 할 때 풀에 연결을 요청한다.
- 연결 검색
- 풀은 사용 가능한 연결을 제공하거나 사용 가능한 연결이 없는 경우 새 연결을 생성 혹은 대기하여 이를 애플리케이션에 반환한다.
- 데이터베이스 상호 작용
- 애플리케이션은 해당 연결을 사용하여 쿼리 또는 기타 데이터베이스 작업을 실행한다.
- 연결 반환
- APP과 DB간 상호 작용이 종료되면 재사용을 위해 연결을 풀에 반환한다.
초기화 단계에서 진행되는 설정은 주로 APP에서의 요청으로 DB는 이에 맞게 연결을 준비하지만, 이는 상황에 따라 다르게 작용할 수 있다.
특히 검색 단계에서 사용 가능한 연결이 없을 시 새로운 풀을 생성하도록 요구할 수 있지만 반대로 해당 클라이언트는 대기 상태로 전환 시키고 순차적으로 제공할 수도 있다. 한 마디로 쓰기 나름이다.
스프링부트의 커넥션 획득 방법
자바에서는 커넥션 풀을 위해 javax.sql.DataSource
라는 인터페이스를 제공하고 이 DataSource
는 커넥션을 획득하는 방법을 추상화 하는
인터페이스로써 커넥션 조회를 위한 핵심 기능을 제공한다.
docs에서 제공하는 내용을 간단하게 요약하면 다음과 같다.
데이터 소스에 대한 연결을 위한 팩토리로 기존 DriverManager 기능의 대안으로 DataSource 객체는 연결을 얻는데 사용됩니다.
DataSource 인터페이스를 구현하는 객체는 일반적으로 JNDI(Java Naming and Directiory)
API를 기반으로 하는 이름 지정 서비스에 등록됩니다.
구현은 총 세 가지 유형으로 기본 구현, 연결 풀링 구현, 분산 트랜잭션 구현이 있습니다.
기본 구현 표준 연결 객체를 생성합니다.
연결 풀링 구현
연결 풀링에 자동으로 참여할 연결 개체를 생성합니다.
(이 구현은 middle-tier connection pooling manager 와 함께 작동해야합니다.)
분산 트랜잭션 구현
분산 트랜잭션에 사용될 수 있고 대부분의(높은 확률로 항상) 연결 풀링에 참여하는 연결 개체를 생성합니다.
이 구현은 middle-tier transaction manager, connection pooling manager 와 함께 작동합니다.
(아닐 경우도 있지만 대부분의 경우 해당)외에도 기본 생성자 필수, 수정할 수 있는 속성 등에 대한 추가 설명 ...
물론 개발자를 위해 Apache의 Commons DBCP, Tomcat-JDBC, HikariCP
등 다양한 DBCP
는 DataSource
인터페이스를 이미 구현해 두었기 때문에 세부 사항에 대해 신경쓰기 보단 DBCP
에 직접 의존하는 코드가 아닌 DataSource
인터페이스에 의존하는 애플리케이션 로직 작성에 더욱 신경쓰는게 바람직하다. (참고로 스프링부트 2.0부터 기본적으로 HikariCP를 사용하고있다.)
WAS의 Thread와 Connection Pool 관리
WAS에서 설정해야 하는 값 중 성능에 가장 큰 영향을 주는 부분은 Thread와 Connection Pool의 개수이다.
이 값은 직접적으로 메모리와 관련이 되어 있기 때문에 많이 사용할 수록 메모리를 많이 점유하게 되지만 이를 방지하기 위해 연결의 개수를 적게 지정한다면 많은 요청이 들어올 경우 처리하지 못 하고 대기할 수 밖에 없게 된다.
대표적으로 다음과 같은 경우 적절한 조치가 필요하다 판단할 수 있다.
- DB Connection Pool의 개수가 지나치게 많을 경우
- WAS Thread 수가 DB Connection Pool의 개수보다 적게 설정 되어 있는 경우
커넥션 풀의 개수가 적을 경우 발생하는 문제에 대해선 이제까지 언급한 바와 같은데 WAS의 Thread 수가 커넥션 풀보다 많아야 하는 이유는 무엇일까?
일반적인 시나리오에서 이 개념은 동시 요청의 효율적인 처리를 보장하는데 의미가 있다.
- 동시성 처리 : WAS의 스레드 수가 많을수록 클라이언트에서 동시에 들어오는 요청을 더 많이 처리할 수 있다.
(클라이언트의 요청 수가 사용 가능한 스레드를 초과하는 경우 일부 요청은 대기열에 머물러야 하므로 잠재적인 지연이나 시간 초과가 발생할 수 있다.) - 리소스 균형 조정 : WAS에서 DB의 커넥션 풀 수보다 더 많은 스레드를 가짐으로써 클라이언트 요청 관리와 데이터베이스 용량 간의 균형을 유지하여 데이터베이스의 리소스 고갈이나 경합을 방지할 수 있다.
이렇게 스레드 수를 적절히 설정하는 것으로 과도한 연결로 인한 데이터베이스의 부하를 방지할 수 있고 WAS가 더 많은 클라이언트 요청을 처리할 수 있도록 하여 병목 현상을 방지하고 보다 원활한 작업 흐름을 보장한다.
물론 애플리케이션에 대한 모든 요청이 DB에 접근하는 것은 아니라는 가정하에 이루어지는 조건이기 때문에 여전히 적절한 스레드와 커넥션 풀의 개수를 찾는것이 포인트인데, 이를 해결하기 위한 가장 효과적인 방법은 애플리케이션을 실제 운영할 시스템 환경에서 성능 테스트를 진행하는 것으로 시스템 환경에 최적화된 값을 찾아 내는 것이 주요하다.
예를 들어 커넥션 풀을 보통 40-50개로 지정한다면 스레드는 이보다 10개 정도 더 지정하는 것으로 균형을 유지할 수 있다.
Thread Pool
Connection pool과 비슷한 맥락으로 Thread pool이라는 개념도 존재한다.
이 역시 매 요청마다 요청을 처리할 Thread를 만드는것이 아닌, 미리 생성한 pool 내의 Thread를 소멸시키지 않고 재사용하여 효율적으로 자원을 활용하는 기법이다.
참고 자료
[DB] 📚 데이터 모델 🕵️ 정리
데이터모델이란? 현실 세계의 정보들을 컴퓨터에 표현하기 위해서 단순화, 추상화 하여 체계적으로 표현한 개념적 모형이다. 데이터, 데이터의 관계, 데이터의 의미 및 일관성, 제약조건 등을
inpa.tistory.com
관계형 데이터베이스 - 위키백과, 우리 모두의 백과사전
위키백과, 우리 모두의 백과사전. 관계형 데이터베이스(關係形 Database, Relational Database, 문화어: 관계자료기지, 관계형자료기지, RDB)는 키(key)와 값(value)들의 간단한 관계를 테이블화 시킨 매우 간
ko.wikipedia.org
https://hazel-developer.tistory.com/244
Disk I/O 기반 VS 인메모리 기반
Disk I/O 란? 웹서비스 성능에 많은 영향을 미치는 중요 모니터링 지표이다. 정확히 Disk I/O(%)라고 하며, 5초동안의 디스크 사용률을 보여준다. 이 디스크는 바로 컴퓨터의 하드 디스크이다. 컴퓨터
hazel-developer.tistory.com
https://docs.oracle.com/en/java/javase/18/docs/api/java.sql/javax/sql/DataSource.html
DataSource (Java SE 18 & JDK 18)
All Superinterfaces: CommonDataSource, Wrapper A factory for connections to the physical data source that this DataSource object represents. An alternative to the DriverManager facility, a DataSource object is the preferred means of getting a connection. A
docs.oracle.com
DB 커넥션 풀(DBCP)은 왜 쓰는가?
웹 컨테이너(WAS)가 실행되면서 DB와 미리 connection(연결)을 해놓은 객체들을 pool에 저장해두었다가,클라이언트 요청이 오면 connection을 빌려주고, 처리가 끝나면 다시 connection을 반납받아 pool에 저
velog.io