💁🏻♂️ 면접을 위한 컴퓨터공학 개념 정리 - [데이터베이스] 편
🧑🏻💻 공부 자료
1. 데이터베이스 개론 (김연희)
2. 깃허브 + 구글링
Database = 데이터의 집합.
모든 데이터들의 집합, 데이터의 모음을 데이터베이스라고 할 수 있다. 카카오톡 메시지 모음, 인스타그램에 등록한 사진들, 카페에서 구매할 수 있는 음료의 종류와 가격 등.
DataBase Management System = 데이터베이스를 관리하는 프로그램.
예금 계좌 주인, 은행 담당 직원, 인터넷 뱅킹, ATM 기기에서 모두 은행 데이터베이스에 접근해서 원하는 데이터를 읽고 쓸 수 있다. DBMS 가 이를 돕기 때문.
사용자가 쿼리문을 작성하면, DBMS가 쿼리에 맞는 데이터를 찾아준다.
현재 대표적인 DBMS 종류
[RDB]
Relational Database 관계형 데이터베이스.
엄격한 스키마와 테이블 형태로 데이터를 관리.
ex) MySQL, Oracle, PostgreSQL, SQLite
[NoSQL]
Not Only SQL 비관계형 데이터베이스.
테이블 형태가 아니고, 엄격하지 않은 Key-Value 형태로 데이터를 관리.
최근의 빅데이터 형태에서 많이 사용. Transaction과 SQL을 지원하지 않음.
ex) MongoDB, DynamoDB, Cassandra, Bigtable
DBMS는 시간이 지남에 따라 계속해서 새로운 모델들이 제시되어 왔다.
-> DBMS 모델 등장 과정.
이 중에서 가장 많이 언급 되는 것이 RDB, NoSQL 이다.
관계형 데이터베이스에서 테이블 관계는 1:N 과 N:M 의 관계를 가질 수 있다.
1:N 관계
하나의 entity(table)가 관계를 맺은 entity의 여러 객체를 가질 수 있는 구조.
보통 Primary Key - Foreign Key 를 사용해서 관계를 맺는다.
실무에서 대표적으로 고객 - 주문 내역 테이블이 있다.
이 경우, 고객의 배송지가 바뀌었다고 했을 때 수정하기 매우 편리하다.
N:M 관계
양쪽 entity 모두가 서로에게 1:N 구조를 갖는 구조.
N:M 관계에서는 새로운 Mapping Table을 통해서 관계를 맺는다.
학생 - 수강과목 테이블을 예로 들 수 있다.
김상우 - 데이터베이스, 네트워크 수강 (1:N)
데이터베이스 - 김상우, 이상우, 박상우 수강 (1:N)
SQL (Structed Query Language) = 구조적 질의 언어. RDBMS에서 데이터를 처리하기 위해 설계된 언어.
데이터 언어 : 데이터를 다루는 언어. 일반적으로 SQL을 생각하면 된다.
데이터 언어는 기능에 따라 DDL, DML, DCL로 나눠진다.
DDL (Data Definition Language)
데이터 정의어. 스키마를 정의하기 위해 사용되는 언어. 데이터 정의어로 생성된 스키마는 데이터 사전에 저장된다.
ex) CREATE TABLE, ALTER TABLE, DROP TABLE
DML (Data Manipulation Language)
데이터 조작어. 데이터의 CRUD 처리를 위해 사용하는 언어. Select, Insert, Delete, Update 등이 있다.
ex) SELECT, INSERT, UPDATE, DELETE
DCL (Data Control Language)
데이터 제어언어. 내부적으로 필요한 규칙이나 기법을 정의하는 언어. Commit, Rollback, Grant, Revoke 등이 있다.
https://noahlogs.tistory.com/39
다양한 컴파일러가 있고, 이 컴파일러와 저장 데이터 관리자를 거친 정보들을 데이터 사전(카탈로그)과 데이터베이스에 필요에 맞게 나눠 저장한다.
데이터 사전(카탈로그) : 데이터베이스 전반적인 데이터 항목들에 대한 정보를 저장한다.
사용자 정보, 데이터베이스 스키마 정보, 무결성 제약조건에 관한 정보 등이 저장된다.
https://jwprogramming.tistory.com/47
https://code-lab1.tistory.com/114
스키마 : 데이터베이스에 저장되는 데이터 구조와 제약 조건을 정하는 것. 메타 데이터 라고도 한다.
예를들어 데이터베이스는 데이터에 INT, CHAR 등의 데이터 타입을 지정한다거나, 중복된 값을 허용하지 않는 등의 제약조건을 지정할 수 있다.
스키마는 DBMS에서 카탈로그에 저장되며 시간에 따라 불변적이다.
스키마 3계층 구조
옵티마이저 = DBMS에서 SQL을 처리하는 가장 효과적인 방법(실행 계획)을 찾아내는 핵심 엔진.
실행 계획 = SQL을 정확히 어떤 방식으로 처리할 것인지의 실행 방법
같은 SQL을 실행하더라도 어떻게 실행하느냐에 따라 성능은 달라진다. 옵티마이저는 여러가지 SQL 처리방법들을 계산하고, 가장 낮은 비용을 가진 실행 계획을 선택한다.
SQL 처리 흐름
규칙 기반 옵티마이저 : 미리 정해진 규칙대로 실행 계획을 세운다. 유동적이지 못함.
비용 기반 옵티마이저 : 처리하는데 예상되는 소요시간, 자원 사용량 등을 고려해서 실행 계획을 세운다.
WAS에서 DB 접근이 필요할 경우 DB Connection 객체를 생성해서 접근한다.
하지만 이 DB Connection을 매 접근마다 생성하는 것은 매우 비효율적.
DB Connection Pool = 미리 일정량의 DB Connection 객체를 생성해두고 모아서 저장.
DBCP 활용 흐름
1. WAS가 실행되면서 DB Connection 을 일정량 미리 만들어 DBCP에 저장한다.
2. HTTP 요청에 따라 필요한 Connection 을 꺼내어 사용하고 반환한다.
3. 이와 같은 방법으로 DB Connectino 을 생성하는 과정을 단축한다.
https://www.holaxprogramming.com/2013/01/10/devops-how-to-manage-dbcp/
Super Key (슈퍼키)
유일성만을 만족하는 키.
예를 들어 {학번 + 이름}, {주민등록번호 + 학번}
Candidate Key (후보키)
유일성 + 최소성을 만족하는 키.
Table의 column 중에서 어떠한 튜플을 유일하게 식별하기 위한 column 들.
즉 기본키가 될 수 있는 후보들.
예를 들어 {학번 + 이름}은 유일성은 만족하지만 최소성을 만족하지 않는다.
{학번}, {주민등록번호} 등이 Candidate Key가 될 수 있다.
Primary Key (기본키)
후보 키 중에서 선택받은 메인 키.
Null 값을 가질 수 없고, 중복 값을 가질 수 없다.
Alternative Key (대체키 / 보조키)
후보 키 중에서 선택받지 않은 키들.
Foreign Key (외래키)
테이블 A가 있을 때, 테이블 A와 새로운 테이블 B를 연결시켜주는 키.
테이블 A에서 기본키여야 외래키로 설정할 수 있다.
테이블 B의 column X가 테이블 A의 기본키(X)를 참조한다면 X가 외래키이다.
Composite Key (복합키)
한 개의 column 만으로 후보키를 만들 수 없을 때, 2개의 column을 조합해서 후보키를 만드느 것.
두 개이상의 테이블이나 데이터베이스를 연결해서 데이터를 검색하는 방법.
Inner Join
Outer Join
SQL Injection = SQL 문에 악의적인 SQL 문을 주입해서 DB에 악영향을 끼치도록 하는 것
무결성 = 데이터에 결함이 없는 상태. 즉 데이터를 정확하고 유효하게 유지하는 것. 데이터의 유지 보수를 쉽게 하기 위함.
무결성 제약 조건
트랜잭션 = 데이터베이스에서 송금과 입금 처럼 뗄래야 뗄 수 없는 작업의 흐름 단위.
데이터베이스 무결성을 유지하고, 데이터를 복구하는 단위가 된다.
데이터베이스의 회복과 병행제어를 가능하게 한다.
데이터베이스 관리 시스템은 데이터베이스가 항상 정확하고 일관된 상태를 유지할 수 있도록 다양한 기능을 제공하는데, 그 중심에 트랜잭션이 있다.
트랜잭션은 ACID 조건을 만족해야한다.
Atomic (원자성)
트랜잭션은 원자처럼 쪼개지지 않아야한다. 전부 실행되거나, 전부 실행되지 않거나.
Consistency (일관성)
트랜잭션은 항상 일관된 결과를 낳아야한다.
Isoliation (고립성)
트랜잭션끼리는 서로 독립적으로 수행되어야 한다. 영향을 줘서는 안된다.
Durability (지속성)
트랜잭션으로 낳은 결과는 건드리지 않는 이상 계속 그 결과를 유지해야한다.
DBMS에서는 트랜잭션 동시성제어를 제공한다.
수많은 트랜잭션들이 동시적으로 수행될 때 어떤 트랜잭션 작업이 무효화 되지 않도록 한다.
수정중에 있는 transaction 에 lock 을 걸어두고 다른 transaction 이 접근하지 못하게 한다.
→ 트랜잭션의 5가지 상태
트랜잭션은 commit, rollback을 이용해서 데이터베이스 무결성을 보장한다.
Commit = 트랜잭션이 올바로 수행되어 일을 완료했음을 의미.
Rollback = 트랜잭션 수행 중 무언가 문제가 발생해서 트랜잭션 수행 전 상황으로 돌리는 것
트랜잭션에서 동시성과 일관성은 반비례 관계에 있다.
동시에 실행할 수 있는 트랜잭션이 많아질수록, 트랜잭션 결과의 일관성은 떨어진다.
트랜잭션 격리수준 = 동시에 여러 트랜잭션이 처리될 때, 트랜잭션이 얼마나 서로 고립되어있는지의 정도를 나타내는 수준
각 트랜잭션은 Lock을 통해 다른 트랜잭션의 접근을 막는다. 하지만 무조건 Lock하면 동시성 측면에서 효율적이지 못하기 때문에 적절한 격리 수준으로 성능을 향상시킬 수 있다.
4개의 레벨로 나눌 수 있다.
1. Read Uncommited
2. Read commited
3. Repeatable Read
4. Serializable
일반적으로 데이터베이스는 비휘발성 저장 장치인 디스크에 상주한다.
트랜잭션이 데이터베이스의 데이터를 처리하려면, 디스크에서 메인 메모리로 가져와 이를 처리한 후 다시 디스크로 보내야 한다. 데이터 이동은 블록(block) 단위로 수행된다.
디스크 블록 : 디스크에 있는 블록
버퍼 블록 : 메인 메모리에 있는 블록 → DBMS의 버퍼 매니저가 관리.
input(x) : 디스크 블록 → 버퍼 블록 이동 연산
output(x) : 버퍼 블록 → 디스크 블록 이동 연산
read(x) : 메인 메모리 버퍼 → 프로그램의 변수로 읽어오는 연산
write(x) : 프로그램 변수 → 메인 메모리 버퍼 기록 연산
회복(Recovery) = 장애가 발생했을 때, 데이터베이스를 장애가 발생하기 전의 일관된 상태로 복구시키는 것.
DBMS의 회복 관리자(recovery magager)가 담당한다.
트랜잭션의 ACID 특성을 보장하고, 데이터베이스를 모순이 없는 일관된 상태로 유지하기 위해 DBMS는 회복 기능을 제공한다.
장애 유형
데이터베이스 회복의 핵심 원리는 데이터 복사 - 별도의 장소에 미리 복사해두고, 장애가 발생했을 때 복사본을 이용해 복원한다.
회복을 위한 복사본 만들기
불필요한 데이터 중복으로 인해 삽입, 갱신, 삭제 연산을 할때 발생할 수 있는 부작용
1. 삽입 이상
데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 문제.
2. 갱신 이상
중복 튜플 중 일부만 변경해서 데이터 불일치가 생기는 문제.
3. 삭제 이상
튜플을 삭제하면 꼭 필요한 데이터까지 함께 삭제되는 데이터 손실 문제.
https://mjn5027.tistory.com/46
이상 현상을 제거하기 위해 데이터베이스의 데이터를 분해하는 과정.
중복된 데이터가 저장되는 것을 방지하고, INSERT, UPDATE, DELETE 할 때 이상한 현상이 생기는 것을 방지하기 위해서 정규화를 한다.
제 1 정규화
한 필드에 여러 개의 정보가 들어가지 않도록 해야한다.
-> 제 1 정규화를 만족하지 않는 테이블.
-> 제 1 정규화를 거친 테이블.
제 2 정규화
기본키가 복합키이고, 그 중에 특정 컬럼에 종속된 컬럼이 있을 경우 제 2 정규화 위배된다.
위에서 제 1 정규화를 거쳤던 테이블을 보면, {학생이름 + 수강과목} 을 기본키로 설정해야 유일성, 최소성을 만족한다.
하지만 나이 컬럼은 학생이름에게 종속된 컬럼이다. 따라서 테이블을 [학생이름 + 나이], [학생이름 + 수강과목] 2 개의 테이블로 쪼개야 제 2 정규화가 진행된다.
위의 테이블들은 제 2 정규화를 거친 테이블들이다.
제 3 정규화
제 2 정규형을 만족하는 상태에서, 이행 함수 종속을 제거하는 과정.
위의 테이블은 한 통신사의 고객 정보 테이블이다. 고객번호가 기본키이다.
자세히 보면, 등급은 고객번호에 의해 결정되고 할인율은 등급에 의해 결정된다.
논리적으로보면 할인율이 고객번호에 의해 결정되는 이상한 상황이 발생한다.
이렇게 X->Y, Y->Z 일때 X->Z를 만족하는 상황을 이행 함수 종속이 발생한다고 말한다.
따라서 제 3 정규화를 거치면 다음과 같은 결과를 낳는다.
[등급 테이블] 과 [고객 정보] 테이블로 찢어놓았다.
뷰 = 어떠한 테이블을 기반으로 만들어진 가상 테이블. 물리적인 공간을 차지하지 않는다.
CREATE VIEW 명령어로 생성한다.
테이블을 어떠한 조건을 입혀서 제한적으로 보여주기 위해 많이 사용한다.
결국은 테이블에 의존적이라서 테이블이 삭제되면 뷰도 삭제된다.
SELECT, INSERT, UPDATE, DELETE 문 모두 기본 테이블을 기반으로 일어난다.
뷰를 사용하는 이유
SQL문을 더 쉽게 작성할 수 있다.
복잡한 조건을 만족하는 뷰를 만들어두면, 매번 SQL문을 어렵게 작성할 필요없이 뷰에 접근하면 된다.
데이터 보안 유지에 도움이 된다.
여러가지 사용자의 요구에 맞는 다양한 뷰를 미리 만들어두고, 사용자가 자신에게 제공된 뷰를 통해서만 데이터에 접근하도록 권한 설정을 하면, 뷰에 포함되지 않은 데이터를 사용자로부터 보호할 수 있다.
데이터의 일부만 열람할 수 있도록 허용하는 것.
인덱스 = 데이터베이스에서 table의 검색 성능을 향상 시켜주는 자료구조. 대부분 B+ Tree로 되어있다.
특정 column 을 search-key 값으로 설정하고, search-key 를 기준으로 정렬하여 (search-key, pointer)를 별도의 파일에 저장한다.
search-key = 인덱스에 저장되는 column 속성
pointer = 데이터가 실제로 저장되는 물리적인 위치
Full Table Scan 보다 Index Scan 이 훨씬 빠르기 때문에 그 column 에 대한 검색 속도를 향상 시킬 수 있다.
책에서 banana 라는 단어를 찾을 때 처음부터 끝까지 완전탐색 하는것보다 색인을 이용하는 것이 더 빠른 원리.
CREATE INDEX 문으로 생성
클러스터형 인덱스 = 테이블 자체가 하나의 인덱스처럼 정렬되는 것. 예를들어 학번으로 정렬된 테이블.
보조형 인덱스 = 테이블과 별개로 search-key, pointer 자료구조 인덱스를 만드는 것
인덱스의 장단점
B Tree 는 Balanced Tree. 모든 리프들이 같은 레벨을 가질 수 있도록 한다.
하나의 노드에 여러 개의 key와 Pointer 를 가질 수 있다. (파란색은 key / 빨간색은 Pointer)
정렬된 순서를 보장한다.
멀티레벨 인덱싱을 통한 빠른 검색을 할 수 있다.
실제 DB에서는 B Tree에서 발전된 B+ Tree를 많이 사용한다.
B+ Tree 는 발전한 B Tree.
B Tree 와의 공통점
하나의 노드에 여러 개의 Key와 Pointer 를 가질 수 있다.
정렬된 순서를 보장한다.
멀티레벨 인덱싱을 통한 빠른 검색을 할 수 있다.
B Tree 와의 차이점
모든 key, data가 리프에 모여있다. (리프까지 가야만 데이터 탐색 가능)
모든 리프노드가 연결리스트 형태를 가진다.
B+ Tree가 DB Index로 적합한 자료구조인 이유
Patitioning = 데이터베이스 테이블을 더 작은 테이블로 나누는 것.
vertical (column 기준) / horizontal (row 기준) 파티셔닝이 있다.
정규화는 vertical 파티셔닝에 포함된다.
출처 : https://www.youtube.com/watch?v=P7LqaEO-nGU&ab_channel=%EC%89%AC%EC%9A%B4%EC%BD%94%EB%93%9C
Vertical Partitioning
예를 들어 다음과 같은 게시판 사이트가 있었을 때, ARTICLE 처럼 테이블이 생겼다고 해보자.
실제로 FE 상에서 content 는 보여주고 있지 않지만, 나머지 정보를 획득하기 위해 content 가 합쳐진 튜플들을 가져올 것이다.
DB 에서 데이터를 획득하는 과정은 대략 다음과 같다. (HDD/SSD) → (메인 메모리) → (애플리케이션)
content 는 실제 게시글 내용이기 때문에, 사이즈가 클 것이고, 이로 인해서 데이터 획득 과정에 시간적으로 손해를 보게 된다.
따라서 이렇게 ARTICLE / ARTICLE_CONTENT 로 찢어서 vertical partitioning 을 수행하면 시간적인 이득을 취할 수 있게 된다.
Vertical Partitioning 수행 이유
그리고 전체가 한꺼번에 필요하게 된다면 다시 Join 으로 합쳐서 가져온다.
Horizontal Partitioning
위 그림은 유튜브의 구독/알림설정/멤버쉽 현황 데이터베이스 예시
테이블의 크기가 커질 수록 인덱스의 크기도 커진다. 테이블에 읽기/쓰기가 있을 때 인덱스에서 처리되는 시간도 조금씩 늘어난다. 이 경우 Horizontal Partitioning 을 수행한다.
Hash Function 을 이용해서 row 파티셔닝을 진행한다. 예를 들어, user_id 를 기반으로 해쉬 펑션에 넣었을 때 0이 나오냐 1이 나오냐에 따라서 2개의 테이블에 나눠 저장한다.
지금 이 user_id 를 파티션 키라고 부른다.
테이블의 스키마는 변화하지 않는다.
검색 속도가 향상된다.
가장 많이 사용될 패턴에 따라 파티션 키를 정하는 것이 중요하다. → 현재 user_id 가 파티션 키이기 때문에 user_id 가 SELECT WHERE 절에 들어가면 효율적이겠지만, channel_id 를 조건으로 조회하고 싶다면 파티셔닝이 의미가 없어지기 때문
데이터가 균등하게 분배될 수 있도록 hash function을 잘 정의하는 것도 중요
한번 수평 파티셔닝을 했으면 그 이후에 파티셔닝을 추가하기 어렵다. 설계할때 매우 신중하게 설계해야 한다.
Horizontal Partitioning 으로 나눠진 파티션을 독립된 서버에 저장하는 방식
같은 서버에서 테이블이 나눠진 Horizontal Partitioning 에서는, 서버에 트래픽이 몰려올 때 부담을 갖게된다.
서버를 나눠서 저장한 샤딩 방법에서는 트래픽을 분산시키는 효과를 볼 수 있다.
샤딩에서는 파티션 키를 샤드 키라고 부르고, 파티션을 샤드라고 부른다.
Horizontal Partitioning 기반이기 때문에 검색 속도를 향상시키는 방법이다.
샤딩같은 경우는 복잡성이 있기 때문에 먼저 캐시 같은 방법을 생각해보고, 나중에 최후의 방안으로 선택하는 식이 좋다.
서비스에 장애가 생겨도 계속해서 서비스가 유지될 수 있도록 (High Availability, HA = 고가용성) 복사 서버를 두는 방법.
Master(=Leader) 서버가 있고 그를 보조하는 Slave(=Replica) 서버가 있다.
레플리카 서버는 마스터 서버의 복사본이고, 마스터 서버에 문제가 생겼을 때 레플리카 서버가 사용된다. 레플리카 서버는 여러 대 복사 될 수 있다.
대부분의 서비스는 READ 가 WRITE 보다 많다. 그래서 몰려오는 READ 쿼리 중 일부를 레플리카 서버에 돌릴 수 있다. READ 쿼리 분산. 서버 부하를 낮출 수 있다.
1. 장애가 생겨도 서비스를 유지시킨다.
2. 서버 부하를 낮춘다. (트래픽 분산)
파티셔닝 / 샤딩 / 레플리케이션 개념 정리
clustering = 군집화
서버가 죽으면 어떡하지 ? → 서버를 여러 대로 나누자.
그런데 데이터 스토리지가 손실되면 어떡하지 ? → 레플리케이션 활용
레플리케이션은 데이터 스토리지까지 함께 복제.
출처 : 우아한 테코톡
ERD = Entity Relationship Diagram.
테이블 간의 관계를 설명해주는 다이어그램. 이를 통해 프로젝트에 사용되는 DB 구조를 한 눈에 파악할 수 있다.
REmote DIctionary Server = 외부에 있고, 딕셔너리 (key-value)를 사용하는 서버.
NoSQL. (Key-Value)
In-memory 데이터베이스 → 보통 DB는 HDD나 SSD에 저장하지만, Redis는 메모리(SRAM)에 저장해서 디스크 스캐닝 없이 매우 빠르게 접근해서 사용한다.
주로 DB를 따로 두고, 캐시역할로 Redis를 추가 사용하는 경우가 많다.
프로시저 = 여러줄의 쿼리를 마치 하나의 함수처럼 실행하기 위한 쿼리의 집합
보통 프로시저를 저장 프로시저라고 부르기도한다.
프로시저 장점
편의성
반복적인 여러줄의 SQL 작업에 대해 프로시저를 만들어두면 처리하기 편리하다.
캐시
프로시저를 한번 실행해두면 같은 작업에 대해서 캐시해놓기 때문에 속도가 빠르다.
트래픽 감소
클라에서 직접 SQL문을 작성하지 않고 프로시저명에 매개변수만 담아 보내기 때문에 트래픽이 감소한다.
프로시저 단점
인프런 강의
https://gyoogle.dev/blog/
https://github.com/jeonyeohun/Getting-Ready-For-Interview
https://noahlogs.tistory.com/36
https://jwprogramming.tistory.com/47
안녕하세요 상우님. 면접 준비를 하고 있는 취준생입니다.
혹시 상우님 자료를 기반으로 정리해서 제 블로그에 포스팅 해도 괜찮을까요? 자료가 너무 잘 정리되어 있어서 질문드립니다.
출처는 밝히겠습니다!