일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 외부키
- 컨테이너실행
- 테스트메소드
- 추후정리
- 예약
- 참조키
- appspec
- 테스트
- docker명령어
- MySQL
- 서브쿼리
- 커밋메세지수정
- querydsl
- Query
- 적용우선순위
- foreignkey
- 메세지수정
- 메소드명
- 포트
- 네이티브쿼리
- ㅔㄴ션
- 검색
- subquery
- WeNews
- appspec.yml
- application.yml
- 2 > /dev/null
- AuthenticationEntryPoint
- ubuntu
- EC2
- Today
- Total
제뉴어리의 모든것
[Section2] [관계형 데이터베이스] 본문
데이터베이스의 필요성
프로그램이 작동중이든 종료된 상태든 반 영구적으로 데이터를 저장하고 있어야하며, 필요한 데이터만을 효율적으로 가져져오기에 적합하기 때문.
다른 저장방식과 비교하여 보자.
- In-Memory
코드상 특정 변수에 저장하는 방식으로, 프로그램이 종료되면 소멸된다. - File/IO
엑셀시트나 csv같은 파일을 읽어오는 방식으로, 적합해보이지만 필요한 데이터만이 아니라 항상 파일전체를 불러와야 하므로 비효율적이며, 필요한 데이터가 여러 파일에 존재하고 있을 경우 여러 파일 전체를 불어와야하는 불편함이 있다.
쿼리란
직역하자면 "질의문"이란 말로, 뭔가 질문하는 형태의 언어를 말한다. 검색엔진의 검색어 또한 쿼리이다.
그리고 데이터베이스에서 쓰이는 sql이란 데이터베이스용 프로그래밍 언어가 이러한 "질의문" 형태로 되어있다.
sql 기본 문법
다음은 SQL을 사용에 필요한 기본 문법
- Select
- Where
- And, Or, Not
- Order By
- Insert Into
- Null Values
- Update
- Delete
- Count
- Like
- Wildcards
- Aliases
- Joins
- Inner Join
- Left Join
- Right Join
- Group By
데이터베이스 관련 용어
- SQL Create DB
- SQL Drop DB
- SQL Create Table
- SQL Drop Table
- SQL Alter Table
- SQL Not Null
- SQL Unique
- SQL Primary Key
- SQL Foreign Key
- SQL Default
- SQL Auto Increment
- SQL Dates
데이터 베이스의 중요 개념
- 트랜잭션
서로 연관된 여러개의 작업을 하나로 묶은 실행 유닛.
이러한 트랜잭션은 처리의 최소단위라고도 말할 수 있는데, 트랜잭션에 속하는 여러 작업중 하나라도 처리를 실패한다면 트랜잭션내의 모든 작업은 취소되어 처리전의 상태가 된다.
즉, 트랜잭션 내의 작업들은 성공하려면 모두 성공하고, 실패하면 모두 실패해야하는 데이터 처리의 최소 묶은 단위이다.
EX : 은행의 송금 절차
- ACID
하나의 트랜잭션의 안정성을 보장하기 위해 필요한 성질.
- Atomicity (원자성)
한 트랙잭션이 과학에서 쓰이는 원자처럼 더이상 쪼갤 수없는 단위여야 한다는것이다.
즉, 한 트랜잭션에 속해있는 여러 작업이 개별적으로 성공, 실패해선 안된다는 것이다.
성공하면 다 성공!. 하나라도 실패하면 다 실패! 해야한다는것이다.
- Consistency (일관성)
한 트랜잭션의 실행 이전과 이후의 상태가 일관되어야 한다는것이다.
쉽게 말해, 정해진 규칙을 깨선 안된다는것이다.
특정 속성(컬럼)의 값이 절대 비어있어서는 안되는 값이다.
그런데 어떤 트랜잭션으로 인해 데이터가 삽입되어있는데 절대 비어선 안되는 컬럼이 비어져 들어와선 안된다는것이다.
- Isolation (고립성, 격리성)
모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야 한다는 뜻이다.
음, 쉽게 말해서 트랜잭션이 여러개일때, 각각의 트랜잭션은 트랜잭션끼리 서로 영향을 미쳐선 안된다는것이다.
만약 영향을 미칠때 발생할 수 있는 문제들은 다음과 같다.
--> Dirty Read:
A트랜잭션이 1번 레코드의 2번 필드의 값을 'abc' 에서 'def'로 수정했다.
그러나 아직 커밋은 하지 않은 상태이다.(수정은 했지만 아직 완전히 적용은 하지 않은 상태라고 생각하면됨)
그런 상태에서 B트랜잭션이 1번 레코드의 2번 필드를 읽는다면 수정된 'def'로 읽혀질거다.
그러나 A트랜잭션이 롤백(원상복구)을 해버린다면, 2번 필드의 값은 'abc'이지만, 이미 B트랜잭션에서 읽어 온 값은 'def'가 될것이다.
이런 상황이 더럽게 읽혀진 Dirty Read이다.
--> Non-Repeatable Read
A라는 트랜잭션 내에서는 특정 필드의 값을 두번 select 해오는 경우가 있다.
첫번째 select 후에 B라는 트랜잭션이 중간에 끼어들어 그 특정 값을 변경하고 커밋을 해버릴때,
A 트랜잭션은 두번째 select 해올때 해당 값이 첫번째 select와는 다른 값을 가져오는 상황을 말한다.
--> Phantom Read (가상 읽기)
REPEATABLE_READ 격리 수준에서는 공유 잠금인 상태의 데이터에 대해 변경 불가가 보장되었다. 하지만, 그 데이터를 변경시키지 못할 뿐 새로운 데이터를 추가/삭제하는 것은 가능하다. 이것을 팬텀 읽기(Phantom read, 가상 읽기)라고 부르는 것이다. 정리하면, 트랜잭션 중에 없던 행이 추가되어 새로 입력된 데이터를 읽는 것 또는 트랜잭션 중에 데이터가 삭제되어 다음 읽기시 이전에 존재하던 행이 사라지는 것을 팬텀 읽기라고 한다.
위에 3가지 문제사항을 방지하기 위한 격리 단계
- Read Uncommitted
한 트랜잭션에서 커밋하지 않은 데이터에 다른 트랜잭션이 접근 가능하다. 즉, 커밋하지 않은 데이터를 읽을 수 있다.
- Read Committed
커밋이 완료된 데이터만 읽을 수 있다.
- Repeatable Read
트랜잭션 내에서 한번 조회한 데이터를 반복해서 조회해도 같은 데이터가 조회 된다
- Serializable
가장 엄격한 격리 수준
즉, 격리성을 완벽히 보장하기 위해 모든 트랜잭션을 순차적으로 실행한다면 동시성 처리 이슈가 발생한다.
반대로 동시성을 높이기 위해 여러 트랜잭션을 병렬처리하게 되면 데이터의 무결성이 깨질 수 있다.
- ACID
참고 자료 : https://incheol-jung.gitbook.io/docs/q-and-a/db/isolation-level
https://armful-log.tistory.com/57
https://blog.yevgnenll.me/posts/what-is-acid-about-transaction
https://mysqldba.tistory.com/334
- Durability(지속성)
Durability(지속성)는 하나의 트랜잭션이 성공적으로 수행되었다면, 해당 트랜잭션에 대한 로그가 남아야 합니다. 만약 런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 한다는 뜻이다.
예를 들어 은행에서 게좌이체를 성공적으로 실행한 뒤에, 해당 은행 데이터베이스에 오류가 발생해 종료되더라도 계좌이체 내역은 기록으로 남아야 합니다. (오류 전 실행 계좌이체 내역은 그대로 유지되어야한다.)
마찬가지로 계좌이체를 로그로 기록하기 전에 시스템 오류 등에 의해 종료가 된다면, 해당 이체 내역은 실패로 돌아가고 각 계좌들은 계좌이체 이전 상태들로 돌아가게 됩니다.
SQL(구조적 언어) 과 NoSQL (비 구조적 언어)
관계형 데이터 베이스는 sql을 사용하여 데이터를 관리하고,
비 관계형 데이터 베이스는 NoSql을 사용하여 데이터를 관리한다.
왜냐면,
관계형 데이터베이스는 데이터들을 사전에 정해진 구조에 맞춰 입력, 출력을 한다.
예를 들면, mysql로 데이터를 저장하기 위해선 일단 테이블을 형식에 맞춰 생성하여야 하고, 데이터를 넣을때도 그 형식에 맞는 타입과 값들을 저장한다.
그러나 비 관계형 데이터베이스는 사전에 정해진 스키마(형식)가 없을 뿐이다.
즉 원하는 형식을 만들어서 데이터를 넣는것이다.
NoSql의 데이터 저장 방식
- Key-Value 타입
속성을 Key-Value의 쌍으로 나타내는 데이터를 배열의 형태로 저장.
Redis, Dynamo 등이 있다. - 문서형(Document) 데이터베이스
데이터를 테이블이 아닌 문서처럼 저장하는 데이터베이스를 의미한다.
MongoDB 등이 있다. - Wide-Column 데이터베이스
데이터베이스의 열(column)에 대한 데이터를 집중적으로 관리하는 데이터베이스. 각 열에는 key-value 형식으로 데이터가 저장되고, 컬럼 패밀리(column families)라고 하는 열의 집합체 단위로 데이터를 처리할 수 있다 - 그래프(Graph) 데이터베이스
료구조의 그래프와 비슷한 형식으로 데이터 간의 관계를 구성하는 데이터베이스입니다. 노드(nodes)에 속성별(entities)로 데이터를 저장.
Neo4J, InfiniteGraph 등이 있다.
SQL 기반의 데이터베이스와 NoSQL 데이터베이스의 차이점
- 데이터 저장(Storage)
- NoSQL은 key-value, document, wide-column, graph 등의 방식으로 데이터를 저장합니다.
- sql은 이미 형식이 정해진 데이터베이스에 해당 형식에 맞게 데이터를 입력하여 저장한다. - 스키마(Schema)
- NoSQL은 내가 저장하려는 데이터의 데이터형식이 그대로 저장이 된다. 즉, 스키마가 정해져 있지 않다.
- SQL을 사용하려면 정해진 테이블 형식이 필요하며, 해당 테이블의 각 필드에 맞는 데이터 타입으로 저장을 해주어야 한다. 물론 테이블 형식을 수정할 수는 있지만, 수정하게 된다면 데이터 베이스에 저장된 데이터들 또한 조정이 필요하다. - 쿼리(Querying)
- sql은 테이블간의 관계를 고려하여 정해진 형식으로 데이터를 읽어오고 저장하여야 한다.
- nosql은 테이블이란 개념이 존재하지 않고, 그냥 데이터 그룹 자체를 읽어온다. - 확장성(Scalability)
- 일반적으로 SQL 기반의 관계형 데이터베이스는 수직적으로 확장한다.
수직적 확장이란, 데이터베이스의 구조는 그대로 두고 단순히 데이터베이스 서버의 부품을 교환한다던가 하는 성능을 향상 시키는것이다.
많은 데이터를 더 빨리 가져오도록 하드웨어적인 기능 확장(향상)이다.
- NoSQL로 구성된 데이터베이스는 수평적으로 확장한다.
쉽게 말해 데이터베이스를 분산적으로 여러 서버에 두는것이다.
참조 : https://velog.io/@rlcjf0014/Database-SQL-vs-NoSQL
SQL 혹은 NoSQL을 사용해야할 때
관계형 데이터베이스를 사용할때
- 데이터 구조가 명확하며 변경될 여지가 없으며 명확한 스키마가 필요한 경우
- 중복된 데이터가 없어서 변경이 용이하므로 관계를 맺고 있는 데이터가 자주 변경될 경우
비 관계형 데이터베이스를 사용할때
- 정확한 데이터 구조를 알 수 없고 데이터가 변경/확장이 될 수 있는 경우
- 막대한 데이터를 저장해야 해서 데이터베이스를 Scale-Out를 해야하는 경우
- 조인을 잘 사용하지 않고 자주 변경되지 않는 데이터
- 읽기를 자주 하지만 데이터 변경은 자주 없는 경우
이론적으론 이런데, 여러 글을 보고 본인이 생각을 해보았을때는
일단 관계형데이터베이스는 여러 데이터들을 체계적으로 저장하여 그 데이터들간에 관계를 이용하여 조인(합쳐진) 데이터들을 뽑아야 할때이고, 비 관계형 데이터베이스는 딱히 다른 데이터들간의 조합이 필요치 않고 단순히 무수히 많은 데이터를 저장하고 읽기만 할때 유용한것 같다.
참조 : https://steady-coding.tistory.com/563
관계형 데이터베이스
- 데이터(data): 각 항목에 저장되는 값입니다.
- 테이블(table; 또는 relation) : 사전에 정의된 열의 데이터 타입대로 작성된 데이터가 행으로 축적됩니다.
- 칼럼(column; 또는 field) : 테이블의 한 열을 가리킵니다.
- 레코드(record; 또는 tuple) : 테이블의 한 행에 저장된 데이터입니다.
- 키(key) : 테이블의 각 레코드를 구분할 수 있는 값입니다. 각 레코드마다 고유한 값을 가집니다. 기본키(primary key)와 외래키(foreign key) 등이 있습니다.
관계 종류
- 1:1 관계
1 : 1 관계는 사실 불필요하므로 잘 쓰이지도 않으며, 의미적으로만 알아두자.
만약,
book이란 테이블이 있다.
그리고 한 레코드마다 당연히 book을 구별할 수 있는 pk가 있을것이다.
이런 상황에서 한 책에 대한 대략설명이 있다고 해보자. 그 데이터가 너무 길기때문에 book 테이블에 한 필드로만 넣기엔 테이블이 너무 비대해 지기 때문에
book detail이란 테이블 따로 만들어 book pk와 이어줄 필드 하나와 대략 설명을 담은 필드 하나로만 하여 테이블을 분리할때
book 테이블과 book detail 테이블은 1:1 관계이다.
- 1:N 관계
위에서처럼 book이란 테이블이 있고,
특정 책에 대한 여러 리뷰들이 달린다고 생각해보자.
그럼 한책에 수십, 수백의 리뷰가 달릴것이다.
이 경우 book review라는 테이블을 만들고
book 테이블과 book review 테이블은 1 : N 관계이다.
- N:N 관계
Customer는 고객 테이플이고.
Package는 여행패키지를 표현한 테이블이다.
이때, 한 고객은 여러 여행 패키지를 살 수가 있다.
그리고 패키지 또한, 여러 고객을 데리고 가는 패키지이기 때문에 Customer 테이블내의 여러 레코드를 참조할 수 있다.
이런 경우 N:N의 관계이다.
이런 N:N 관계를 의미있게 사용하기 위해선,
1 : N, N : 1 관계로 쪼개야 한다.
"패키지 구매내역" 이란 테이블을 하나 두는것이다.
아래가 바로 쪼개진 테이블 형태이다.
- self referencing 관계
만약 유저 테이블에 추천인 필드가 있을 경우,
해당 필드는 유저 테이블의 한 필드이면서 유저테이블을 참조할 것이다.