![[CS] 데이터베이스 QnA](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255BCS%255D%2520%25EB%258D%25B0%25EC%259D%25B4%25ED%2584%25B0%25EB%25B2%25A0%25EC%259D%25B4%25EC%258A%25A4%2520QnA%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3Dlushlife99&w=2048&q=75)
SQL이란 무엇일까요?
SQL이란 Structed Query Language의 약자로 DBMS의 데이터를 관리하기 위해 설계된 특수 목적의 프로그래밍 언어이다.
트랜잭션이란?
트랜잭션이란 데이터베이스에서 논리적인 작업 단위를 구성하는 연산들의 집합이다
트랜잭션의 특징인 ACID 설명
- 원자성 : 트랜잭션의 연산은 DB에 모두 반영되거나 아예 반영되지 않아야 한다.
- 일관성 : 트랜잭션이 성공적으로 작업을 수행한 후에도 데이터베이스는 일관성있는 상태를 유지해야 한다.
- 독립성 : 둘 이상의 트랜잭션이 실행되고 있을 경우 어떤 트랜잭션이라도 다른 트랜잭션의 연산에 끼어들 수 없다.
- 지속성, 영속성 : 성공적으로 수행을 마친 트랜잭션의 결과는 시스템이 고장나도 영구적으로 반영되어야 한다.
다수의 트랜잭션이 하나의 자원을 접근할 때 발생하는 문제
- Dirty Read : 한 트랜잭션이 아직 커밋되지 않은 다른 트랜잭션의 변경된 데이터를 읽는 문제로 롤백 시 일관성이 깨질 수 있다.
- Non-Repeatable Read : 같은 트랜잭션 내에서 동일한 데이터를 조회했을 때, 다른 트랜잭션의 변경으로 인해 결과가 달라지는 문제이다.
- Phantom Read : 한 트랜잭션이 특정 조건을 만족하는 데이터를 여러 번 조회할 때, 다른 트랜잭션의 삽입 또는 삭제로 인해 조회 결과가 달라지는 문제
- 문제 해결 방법 : 트랜잭션의 격리 수준 조정, Lock을 사용
트랜잭션 격리 수준
여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지를 결정하는 것이다.
4가지 격리 수준
- Read Uncommited(Level 0) : 트랜잭션의 변경 내용을 commit 여부와 상관없이 다른 트랜잭션이 조회할 수 있다. (Dirty Read, Non-Repeatable Read, Phantom Read가 발생할 수 있다)
- Read Commited(Level 1) : Commit이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다. (Non-Repeatable Read, Phantom Read가 발생할 수 있다)
- Repeatable Read(Level 2) : 하나의 트랜잭션에서 데이터를 조회할 때 모두 같은 결과를 가져오도록 보장한다. (Phantom Read가 발생할 수 있다)
- Serialize(Level 3) : 한 트랜잭션에서 읽거나 쓰는 모든 데이터들을 다른 트랜잭션에서 접근할 수 없게 한다.
DDL, DML, DCL이란?
DDL(Data Definition Language)
- 데이터베이스 스키마를 정의하거나 조작하기 위한 언어
- 대상은 SCHEMA, DOMAIN, TABLE, VIEW, INDEX 등이 있다.
- 명령어를 입력하는 순간 작업이 즉시 완료(Auto Commit)된다.
- CREATE, ALTER, DROP. RENAME, COMMENT, TRUNCATE
DML(Data Manipulation Language)
- 데이터베이스 내부 레코드를 관리하기 위한 언어로 데이터 추가, 변경, 삭제 등의 작업을 수행한다.
- AUTO COMMIT이 되지 않아, 작업 완료시 트랜잭션 내에서 COMMIT 명령어를 통해 반영을 해야하며 ROLLBACK이 가능하다.
- SELECT, INSERT, UPDATE, DELETE 등
DCL(Data Control Language)
- 데이터베이스에 접근하거나 객체에 권한을 주는 등의 역할을 하는 언어이다.
- GRANT, REVOKE(권한 회수), COMMIT, ROLLBACK
DB Key
후보키
- 릴레이션을 구성하는 속성들 중 튜플을 유일하게 식별할 수 있는 속성들의 부분 집합
- 모든 릴레이션은 반드시 하나 이상의 후보키를 가져야 한다
- 릴레이션에 있는 모든 튜플에 대해 유일성과 최소성을 만족시켜야 한다.
- 유일성: Key로 하나의 Tuple을 유일하게 식별할 수 있다.
- 최소성: 꼭 필요한 속성으로만 구성된다.
기본키
- 한 릴레이션에서 특정 튜플을 유일하게 구별할 수 있는 속성으로 후보키중에서 선택된 Main Key이다
- 무결성 특징을 갖는다
- 무결성이란 데이터의 정확성과 일관성을 유지하고, 데이터의 결손과 부정합이 없음을 보증하는 것을 의미한다
- Null 값을 가질 수 없다
- 중복된 값이 저장될 수 없다
- 기본키를 수정하기 위해서는 삭제를 한 후 추가를 하는 식으로 동작해야 한다.
대체키
- 후보키가 둘 이상일 때 기본키를 제외한 나머지 후보키를 의미한다
- 보조키라고 부른다
슈퍼키
- 한 개의 릴레이션 내에 있는 속성들의 집합으로 구성된 키
View란?
데이터베이스에서 뷰는 사용자에게 접근이 허용된 자료만을 보여주기 위해 한개 이상의 테이블을 조인하여 만든 가상 테이블이다. 뷰는 저장 장치에 물리적으로 존재하지 않지만 사용자에게는 실제로 존재하는 것처럼 간주된다.
장점
- 논리적인 데이터의 독립성을 제공한다. (물리적인 공간이 필요없다)
- 복잡한 쿼리를 단순화하고 데이터 조회가 용이하다
- 접근 제어를 통한 보안이 제공된다
단점
- 뷰에 인덱스를 구성할 수 없다
- 뷰의 정의를 변경할 수 없다
- 뷰로 구성된 내용에 대한 삽입, 삭제, 갱신, 연산에 제약이 따른다
뷰에 데이터의 CUD 연산의 제약이 걸리는 경우
- 뷰 정의에 포함되지 않은 컬럼 중에서 기본 테이블의 컬럼이 Not null 제약조건이 지정되어 있는경우 Insert 불가
- Data * 2와 같이 산술 표현식으로 정의된 가상 컬럼이 뷰에 정의되면 insert, update 불가
- Distinct를 포함하는 경우에 DML 명령 사용 불가
- 그룹 함수나 Group By 절을 포함한 경우 DML 명령 사용 불가
Join
조인이란 두 개 이상의 테이블이나 데이터베이스를 연결하여 데이터를 검색하는 방법이다. 테이블을 연결하려면 1개 이상의 속성을 공유하고 있어야하며 이를 통해 데이터 검색을 한다.
Join의 종류
- Inner Join
- 기준 테이블과 조인 테이블의 중복된 교집합을 추출하게 된다
- Left Outer Join
- 기준(왼쪽) 테이블과 조인 테이블의 교집합과 차집함의 연산 결과를 합친 것과 같다
- Right Outer Join
- Left Outer Join과 같으나 기준 테이블이 오른쪽으로 바뀐 것
- Full Outer Join
- 두 테이블의 합집합을 조회
- Cross Join
- 모든 경우의 수를 표현해주는 방식이다
- Self Join
- 자기 자신과 조인하는 것으로 자신이 갖고 있는 컬럼을 다양하게 변형시켜 사용할 때 자주 사용한다
데이터베이스 이상 현상이란?
이상 현상은 테이블을 설계할 때 잘못 설계하여 데이터를 삽입, 삭제, 수정할 때 논리적으로 생기는 오류를 말한다
- 삽입 이상
- 자료를 삽입할 때 의도하지 않은 자료까지 삽입해야만 자료를 테이블에 추가할 수 있는 현상이다
- 갱신 이상
- 중복된 데이터 중 일부만 수정되어 데이터의 모순이 일어나는 현상이다
- 삭제 이상
- 어떤 정보를 삭제하면, 의도하지 않은 다른 정보까지 삭제되어버리는 현상이다
정규화란?
정규화란 이상현상이 있는 릴레이션을 분해하여 이상현상을 없애는 과정이다. 데이터의 중복성을 최소화하고 일관성 등을 보장하여 데이터베이스의 품질을 보장하고 성능의 향상을 위해 수행한다. 정규화 수준이 높을 수록 유연한 데이터 구축이 가능하고 데이터의 정확성이 높아지는 반면 물리적 접근이 복잡하고 너무 많은 조인으로 인해 조회 성능이 저하된다.
정규화의 장점
- 데이터 구조의 안정성 및 무결성을 유지한다
- 데이터 중복을 배제하여 이상현상의 발생을 방지하고 자료 저장 공간의 최소화가 가능하다
- 정규화된 데이터베이스 구조에서는 새로운 데이터 형의 추가로 인한 확장시, 그 구조를 변경하지 않거나 일부만 변경해도 된다
- 테이블의 구성을 논리적이고 직관적으로 할 수 있다
- 개체와 속성의 누락 여부 확인이 가능하다
정규화의 단점
- 릴레이션의 분해로 Join연산이 많아진다
- 쿼리를 통한 데이터 처리 속도가 빨라질 수도 있고 느려질 수도 있다
정규화 과정
1NF
- 릴레이션에 속한 모든 도메인이 원자값으로만 되어 있는 정규형이다. 즉 릴레이션의 모든 속성 값이 원자 값으로만 되어 있는 정규형이다.
- 아래 조건을 만족해야 한다
- 각 컬럼은 하나의 속성만을 가져야 한다
- 하나의 컬럼은 같은 종류나 타입을 가져야 한다
- 각 컬럼은 유일한 값을 가져야 한다
2NF
- 제1정규화를 진행한 테이블에 대해 기본키가 아닌 모든 속성이 기본키에 대하여 완전 함수적 종속을 만족하도록 테이블을 분해하는 것이다 → 부분적 종속이 없어야 한다
완전 함수적 종속이란? 기본키의 부분집합이 결정자가 되어서는 안된다는 것을 의미한다
- 즉 테이블에서 기본키가 복합키(키1, 키2)로 묶여있을 때, 두 키 중 하나의 키만으로 다른 컬럼을 결정지을 수 있으면 안된다
3NF
- 제2정규화를 진행한 테이블에 대해 기본키가 아닌 모든 속성이 기본키에 대해 이행적 종속을 만족하지 않도록 테이블을 분해하는 것이다
4NF
- 다치 종속이 없는 정규형이다
- 다치종속은 아래의 조건을 만족한다.
- A→B일때, 하나의 A에 여러 개의 B값이 존재한다. (1:N의 관계로 대응)
- 최소 3개의 컬럼이 존재한다.
- R(A, B, C)가 있을 때 A와 B 사이에 다치 종속성이 있을 때 B와 C가 독립적이다.
5NF
- 모든 조인 종속이 없는 정규형이다
RDBMS와 NoSQL의 차이점
RDBMS
- RDBMS는 R의 의미인 관계의 의미대로 관계형 데이터 모델을 기초로 두고 모든 데이터를 테이블 형태로 표현하는 데이터베이스이다
- RDBMS는 핵심적인 2가지 특징이 있다
- 데이터는 정해진 데이터 스키마에 따라 테이블에 저장된다
- 데이터는 관계를 통해 여러 테이블에 분산된다
- 테이블은 명확하게 정의된 구조가 있어서 스키마 구조에 맞는 데이터만 추가할 수 있다
- 관계형 데이터베이스에서 관계는 외래키를 통해 관계를 표현한다
장점
- 스키마가 명확하게 정의되어 있고 데이터의 무결성을 보장한다
- 테이블간의 관계를 통해 데이터를 중복없이 한번만 저장 가능하다
단점
- 데이터 스키마를 사전에 계획하고 알려야 하며 수정하기 힘들다(유연하지 못하다)
- 관계를 맺고 있어서 조인문이 많이 있는 복잡한 쿼리가 만들어질 수 있다
- 대체로 수직적 확장만 가능하다
NoSQL
- NoSQL (Not Only SQL)
- RDBMS와 다르게 스키마도 없고 관계도 없는 DB이다
- RDBMS와 다르게 정해진 스키마를 따르지 않고 다른 구조의 데이터를 같은 컬렉션에 추가 가능하다
- Join이라는 개념이 존재하지 않는다
- Join을 하고 싶다면 컬렉션을 통해 데이터를 복제 후, 각 컬렉션 일부에 속하는 데이터를 정확하게 산출하도록 한다
- 데이터의 중복이 있어 서로 영향을 줄 위험이 존재한다. 그래서 데이터 변경이 거의 없는 경우 NoSQL을 사용하면 효율적이다
- 다양한 저장 형태가 존재한다
- Key-Value
- Document
- Wide Column
- Graph
장점
- 스키마가 없어서 유연하다
- 데이터는 애플리케이션이 필요로하는 형식으로 저장된다
- 데이터를 읽어오는 속도가 빠르다
- 수직적 확장 뿐만 아니라 수평적 확장을 쉽게 할 수 있다는 장점이 있다
단점
- 유연성으로 인해 데이터 구조 결정을 미루게 될 수 있다
- 데이터가 여러 컬렉션에 중복되어 있기 때문에 수정시 모든 컬렉션에서 수행하여야 한다
- 스키마가 존재하지 않아 명확한 데이터 구조를 보장하지 않으며 데이터 구조 결정이 어려울 수 있다
결론
정확한 데이터 구조를 알 수 없거나 변경/확장이 될 수 있는 경우, 읽기는 자주하지만 데이터 변경은 자주 없는 경우, DB를 수평적으로 확장해야 하는 경우에는 NoSQL 사용을 고려하면 좋다
Full Table Scan이란?
데이터를 탐색하기 위해 모든 테이블의 데이터를 순차적으로 탐색하는 방법이다
- 데이터베이스는 아래의 상황에서 Full Table Scan으로 탐색하게 된다
- 적용 가능한 인덱스가 없는 경우
- 인덱스 처리 범위가 넓은 경우
- 크기가 작은 테이블에 엑세스하는 경우
- Full Table Scan의 경우 모든 데이터를 순차적으로 탐색하기 때문에 데이터가 많을 경우 조회할 때 많은 비용이 든다. 이를 보완하기 위해 Index를 설정하여 조회 성능을 향상시킬 수 있다
카디널리티(Cardinality)
모든 인덱스 키 값 중 유니크한 값의 수를 의미한다
인덱스란?
인덱스란 책의 목차와 같은 개념으로 추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조이다
- 인덱스는 항상 정렬된 상태로 보관을 하기에 저장(Insert, Update, Delete) 요청이 오면 Index의 정렬이 다시 한번 진행되기에 성능적으로 손해를 볼 수 있다. 하지만 조회의 경우 성능 향상을 느낄 수 있다
- 인덱스는 프라이머리 키와 보조 키로 구분할 수 있다
- 프라이머리 키
- 레코드를 대표하는 컬럼의 값으로 만들어진 인덱스를 의미한다
- 테이블에서의 식별자를 가르키며 Null값과 중복을 허용하지 않는다
- 세컨더리 인덱스
- 프라이머리 키를 제외한 나머지 인덱스를 의미한다
- 유니크 인덱스는 프라이머리 키와 성격이 비슷하고 대체해서 사용할 수 있기에 대체 키라고 부른다
- 별도로 분리하기도 하고 세컨더리 인덱스로 분리하기도 한다
기본적으로 설정되는 인덱스
- PK → 클러스터링 인덱스로 생성
- Unique Column → 논 클러스터링 인덱스로 생성
인덱스의 장단점
장점
- 테이블을 조회하는 속도와 그에 따른 성능을 향상시킬 수 있다
- 전반적인 시스템의 부하를 줄일 수 있다
단점
- Index 생성시 인덱스를 저장할 추가적인 저장 공간이 필요하다.
- 인덱스를 관리하기 위해 DB의 약 10%에 해당하는 저장공간이 필요하다.
- 인덱스를 관리하기 위해 추가 작업이 필요하다
- 인덱스 된 Field에서 Data를 업데이트하거나, Record를 추가 또는 삭제시 성능이 떨어진다.
- 데이터 변경 작업이 자주 일어나는 경우, Index를 재작성해야 하므로, 성능에 영향을 미침.
- 인덱스를 잘못 선택할 경우 오히려 성능이 저하되는 역효과가 발생할 수 있다.
- 한 페이지를 동시에 수정할 수 있는 병행성이 줄어든다.
인덱스를 지정하면 좋은 경우
- 데이터의 중복도가 낮은(카디널리티가 높은) Column
- 규모가 작지 않은 테이블
- INSERT, UPDATE, DELETE가 자주 발생하지 않는 Column
- JOIN이나 WHERE 또는 ORDER BY에 자주 사용되는 Column
- 외래키가 사용되는 Column
B-Tree란?
- B-Tree는 가장 일반적으로 먼저 도입된 알고리즘이다.
- B-Tree에서 B는 Binary가 아닌 Balanced를 의미한다.
- 컬럼의 원래 값을 변경하지 않고 앞 부분만 잘라서 관리를 하는데 인덱스 구조체 내에서 항상 정렬된 상태로 관리된다.
- 전문 검색과 같은 특수한 요건이 아닌 경우, 인덱스는 거의 B-Tree를 사용할 정도로 일반적인 용도에 적합하다.

구조와 특징
- B-Tree는 루트 노드 아래에 하위 노드(브랜치, 리프 노드)들이 붙어있는 형태이다.
- 데이터베이스에서는 클러스터링 인덱스인지 논-클러스터링 인덱스인지에 따라 리프 노드에 실제 데이터 또는 주소를 저장하고 있다.
클러스터링 인덱스와 논-클러스터링 인덱스란?
클러스터링 인덱스
클러스터링 인덱스는 리프 노드에 같은 무리의 인덱스 데이터를 물리적으로도 묶어서 저장한다.
특징
- 실제 데이터 자체가 정렬되어 저장된다.
- 테이블당 1개만 존재 가능하다.
- 리프 페이지가 데이터페이지이다.
- 아래의 제약조건 시 자동 생성
- Primary Key (우선 순위)
- Unique + Not Null
논 클러스터링 인덱스
논-클러스터링 인덱스는 리프노드에 실제 물리적 데이터의 주소를 담아 저장한다.
## Unique 제약조건을 통한 논-클러스터링 인덱스 설정
ALETER TABLE member
ADD CONSTRAINT unq_name UNIQUE(name);
## Unique Index 설정을 통한 인덱스 설정 (중복 허용 X)
CREATE UNIQUE INDEX unq_inx_name
ON member(name);
## Default Index 설정을 통한 인덱스 설정 (중복 허용)
CREATE INDEX idx_name
ON member(name);
특징
- 실제 데이터 페이지는 그대로 존재한다.
- 별도의 인덱스 페이지 생성하여 데이터를 저장한다. → 추가 공간 필요
- 테이블당 여러 개의 논-클러스터링 인덱스를 설정할 수 있다.
- 리프 페이지에 클러스터링 인덱스가 적용된 컬럼의 실제 값를 담고 있다. (MySQL InnoDB기준)
- MyISAM은 리프 페이지에 실제 데이터 주소 값을 담고 있다.
- Unique 제약조건 적용시 자동 생성된다.
- 직접 Index 생성시 논-클러스터링 인덱스로 생성된다.
Share article