diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture25] db \354\235\270\353\215\261\354\212\244/README.md" "b/\352\271\200\354\227\260\354\232\261/[lecture25] db \354\235\270\353\215\261\354\212\244/README.md"
new file mode 100644
index 0000000..722a550
--- /dev/null
+++ "b/\352\271\200\354\227\260\354\232\261/[lecture25] db \354\235\270\353\215\261\354\212\244/README.md"
@@ -0,0 +1,132 @@
+> # [Lecture 25](https://www.youtube.com/watch?v=IMDH4iAQ6zM&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=25)
+
+## 주요 내용
+
+- index가 중요한 이유
+- index 거는 법
+- index 동작 방식
+- index 사용 시 참고 사항
+
+## index가 중요한 이유
+
+- index가 없다면 full scan(= table scan)으로 데이터를 찾아야 하므로 시간 복잡도는 O(N)
+- index가 있다면 O(logN) (B-tree based index)
+- index를 쓰는 이유
+ - 조건을 만족하는 튜플(들)을 빠르게 조회하기 위해!
+ - 빠르게 정렬(order by)하거나 그룹핑(group by) 하기 위해!
+
+## index 거는 법
+
+```sql
+create [unique] index 인덱스명 on 테이블명 (컬럼명);
+```
+
+- unique 옵션은 중복이 안되는 고유 인덱스를 생성하는 것
+ - 생략하면 중복이 허용
+- unique 옵션으로 인덱스를 생성하려면 인덱스를 설정하려는 컬럼 값에 중복이 있으면 안 됨
+
+```sql
+create table 테이블명 (
+ id int primary key,
+ name varchar(20) not null,
+ team_id int,
+ backnumber int,
+ index 인덱스명 (컬럼명),
+ unique index 인덱스명 (컬럼명들..),
+);
+```
+
+- primary key에는 index가 자동 생성됨
+
+## index 조회
+
+```sql
+show index from 테이블명;
+```
+
+## B-tree 기반 인덱스 동작 방식
+
+- members table
+
+
+ | a | b | c |
+ | --- | --- | --- |
+ | 3 | … | … |
+ | 7 | … | ... |
+ | 1 | … | … |
+ | 2 | … | … |
+ | … | … | … |
+ | 7 | … | … |
+ | 9 | … | … |
+- index(a) table (members의 a컬럼에 대한 index 테이블)
+
+
+ | a | ptr |
+ | --- | --- |
+ | 1 | … |
+ | 2 | … |
+ | 3 | … |
+ | 4 | … |
+ | … | … |
+ | 13 | … |
+- index테이블에서 ptr은 포인터 데이터로 members테이블의 어떤 튜플(행)과 연관있는지 가리키고 있음
+- a = 9 인 튜플을 찾는다고 해보면 index테이블에서 binary search를 통해 a = 9인 것을 찾음
+- a = 7 and b = 95 인 튜플을 찾는다고 하면 똑같이 binary search를 통해 a = 7인 것을 찾지만 그 이후 b를 찾아야 하기 때문에 a를 찾는 것은 이진 탐색이지만 b를 찾는 것은 full scan이 되어버림
+ - 그래서 index(a, b)를 생성하여 해결
+ - 만약 index(a, b) 테이블을 생성했다면 이것을 이용해서 b에 대한 탐색을 한다 해도 b에 대한 정렬이 제대로 되어 있지 않기 때문에 효율이 나오지 않거나 index가 아예 사용되지 않을 수 있음 (index(b)를 생성해서 탐색해야함)
+
+## 쿼리가 어떤 index를 쓰는지 확인하기
+
+```sql
+explain select * from player where backnumber = 7;
+```
+
+- 만약 index가 여러개 있다고 하자, 그럼 이때 어떤 index를 쓰는 기준은 무엇인가??
+ - DBMS에 존재하는 optimizer가 알아서 적절하게 index를 선택함
+- optimizer가 항상 최고의 index를 선택하지는 않음!
+- 특정 index를 사용하도록 명시하는 법
+ - MySQL
+
+ ```sql
+ select * from player force index (인덱스명)
+ where backnumber = 7;
+ ```
+
+ - use index도 존재하나 force index가 좀 더 강제적임 (use index는 써 주세용~)
+ - 만약 해당 인덱스로 데이터를 찾을 수 없다면 full scan을 실시함
+ - 특정 인덱스를 제외하고 싶다면 ignore index 사용
+
+## index 주의 사항
+
+- index가 많다고 좋은건 아님!
+- table에 write할 때마다 index도 변경 발생
+ - B-tree일 경우 정렬(트리의 구조 조정)을 해야하므로 많은 시간이 걸릴 수 있음
+- 추가적인 저장 공간 차지
+- 즉, 불필요한 index를 만들지 말자
+
+## Covering index
+
+- 조회하는 attribute(s)를 index가 모두 cover할 때를 의미
+- index(team_id, backnumber)가 존재할 때 team_id = 5;인 데이터를 가져온다고 하면 굳이 player 테이블에서 데이터를 가져올 필요가 없음 (index테이블에서 바로 가져오면 됨)
+- 조회 성능이 더 빠름!!
+
+## Hash index
+
+- hash table을 사용하여 index를 구현
+- 시간복잡도 O(1)
+- 하지만 단점 존재!!
+ - rehashing에 대한 부담 (rehashing : hash table을 더 큰 사이즈로 늘려주는 것)
+ - index의 equality 비교(==, ≠)만 가능! (range 비교 불가능)
+
+## full scan이 더 좋은 경우
+
+- table에 데이터가 조금 있을 때 (몇 십, 몇 백건 정도)
+- 조회하려는 데이터가 테이블의 상당 부분을 차지할 때
+ - 남자만 조회, 여자만 조회 ..
+- index를 쓸 지 full scan을 할 지는 optimizer가 판단함!!
+
+## 참고 사항
+
+- order by나 group by에도 index가 사용될 수 있음
+- FK에는 index가 자동으로 생성되지 않을 수 있음 (MySQL은 생성되나 다른 RDBMS에는 생성되지 않는 경우가 있음)
+- 이미 데이터가 몇 백만 건 이상 있는 테이블에 인덱스를 생성하는 경우 시간이 몇 분 이상 소요될 수 있고 DB 성능에 안 좋은 영향을 줄 수 있음
\ No newline at end of file
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/README.md" "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/README.md"
new file mode 100644
index 0000000..d4694b2
--- /dev/null
+++ "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/README.md"
@@ -0,0 +1,58 @@
+> # [Lecture 28](https://www.youtube.com/watch?v=liPSnc6Wzfk&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=28)
+
+## 주요 내용
+
+- B tree 시간 복잡도
+- B tree가 DB index로 쓰이는 이유
+
+## B tree 계열
+
+- B+ tree, B* tree
+- 시간 복잡도 : O(logN)
+
+## self-balancing BST
+
+- 스스로 균형을 잡는 이진 탐색 트리
+- AVL tree, Red-Black tree
+- 시간 복잡도 : O(logN)
+
+## 위 트리를 비교하기 전 DB 관점에서의 내용 정리
+
+- DB는 secondary storage에 저장됨 (secondary storage : SSD or HDD)
+- DB에서 데이터를 조회할 때 secondary storage에 최대한 적게 접근하는 것이 성능 면에서 좋음
+- secondary storage는 block 단위로 읽고 쓰기 때문에 연관된 데이터를 모아서 저장하면 더 효율적으로 읽고 쓸 수 있음
+
+## AVL tree index(b) vs B tree index(b)
+
+- tree의 각 노드는 서로 다른 block에 있다고 가정
+- 초기에는 root 노드를 제외한 모든 노드는 secondary storage에 있다고 가정
+- 초기에는 데이터 자체도 모두 secondary storage에 있다고 가정 (아직 메인메모리(RAM)에 올라오지 않은 상태)
+- AVL tree는 자녀 노드 수가 1~2개 가질 수 있음
+- 5차 B tree는 자녀 노드 수가 3~5개 가질 수 있음
+- 즉, B tree는 데이터를 찾을 때 탐색 범위를 빠르게 좁힐 수 있음
+ - 루트 노드에서 부터 리프 노드까지의 거리가 짧음
+ - secondary storage에 접근 횟수가 적음
+- AVL tree는 노드의 데이터로 1개 가질 수 있음
+- 5차 B tree는 노드의 데이터로 2~4개 가질 수 있음
+- 즉, B tree는 block 단위에 대한 저장 공관 활용도가 더 좋음
+
+## B tree의 강력함
+
+- with 101차 B tree
+ - 자녀 수 : 51~101
+ - key 수 : 50~100
+- best case의 데이터 총 수
+
+
+- worst case의 데이터 총 수
+
+
+- avg case의 데이터 총 수
+
+
+
+## B tree 계열을 DB index로 사용하는 이유
+
+- DB는 기본적으로 secondary storage에 저장됨
+- B tree index는 self-balancing BST에 비해 secondary storage 접근을 적게 함
+- B tree 노드는 block 단위의 저장 공간을 알차게 사용할 수 있음
\ No newline at end of file
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-1.png" "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-1.png"
new file mode 100644
index 0000000..95324c3
Binary files /dev/null and "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-1.png" differ
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-2.png" "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-2.png"
new file mode 100644
index 0000000..477f633
Binary files /dev/null and "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-2.png" differ
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-3.png" "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-3.png"
new file mode 100644
index 0000000..3c58b61
Binary files /dev/null and "b/\352\271\200\354\227\260\354\232\261/[lecture28] B tree/img/lecture28-3.png" differ
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture29] partitioning, sharding, replication/README.md" "b/\352\271\200\354\227\260\354\232\261/[lecture29] partitioning, sharding, replication/README.md"
new file mode 100644
index 0000000..8ad0ee7
--- /dev/null
+++ "b/\352\271\200\354\227\260\354\232\261/[lecture29] partitioning, sharding, replication/README.md"
@@ -0,0 +1,53 @@
+> # [Lecture 29](https://www.youtube.com/watch?v=P7LqaEO-nGU&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=29)
+
+## 주요 내용
+
+- partitioning
+- sharding
+- replication
+
+## partitioning
+
+- 파티셔닝
+- database table을 더 작은 table로 나누는 것
+- partitioning 종류
+ - vertical partitioning : column을 기준으로 table을 나누는 방식
+ - horizontal partitioning : row를 기준으로 table을 나누는 방식
+
+## vertical partitioning
+
+- board 테이블이 있다고 했을 때 게시글 목록을 보여주는데 content까지 가져올 필요가 없음!!
+- 이럴 경우 무거운 데이터인 content같은 것을 따로 분리해서 테이블로 나누는 것
+
+## horizontal partitioning
+
+- 테이블의 크기가 커질수록 인덱스의 크기도 커짐
+- 테이블에 read / write가 있을 때마다 인덱스에서 처리되는 시간도 조금씩 늘어남
+- 한 테이블에만 데이터를 쌓지 않고 테이블을 나누어서 데이터를 분산하여 쌓는 방법을 사용하여 문제를 해결함
+- 즉, hash function을 이용하여 horizontal partitioning을 하여 해결 가능(hash based horizontal partitioning)
+- hash function에서 기준이 되는 키(테이블에서 기준이 되는 키)를 partition key라고 함
+- 가장 많이 사용될 패턴에 따라 partition key를 정하는 것이 중요함!!!
+- 데이터가 균등하게 분배될 수 있도록 hash function을 잘 정의하는 것도 중요함!!!
+- hash-based horizontal partitioning은 한번 partition이 나뉘어져서 사용되면 이후에 partition을 추가하기 까다로움
+- partition들을 같은 DB 서버에 저장함 (HW 자원에 한정될 수 있음)
+
+## sharding
+
+- horizontal partitioning처럼 동작
+- horizontal partitioning과 차이는 각 partition이 독립된 DB 서버에 저장됨 (HW 자원에 한정되지 않음)
+- 그래서 부하(load)를 분산 시킬 수 있음
+- 즉, 데이터가 많이 쌓이는 테이블에는 샤딩을 사용하여 각 파티션마다 독립된 DB 서버를 할당하고 트래픽을 분산 시켜 DB 서버의 부하를 낮추는 방식을 사용함
+
+## replication
+
+- DB 서버의 데이터를 copy하여 sync를 맞춰 나가 하나의 DB 서버에 문제가 생기더라도 다른 DB 서버(보조 서버)를 통해 문제를 해결하는 방법
+- 기존 DB 서버 : master / primary / leader
+- 복사 DB 서버 : slave / secondary / replica
+- 즉, 한 서버에 장애가 발생하여도 서비스에 타격이 없도록 하는 고가용성(High availability)을 보장하는 것
+- 또는 계속 되는 트래픽에 대한 부하를 분산시킬 수도 있음!!
+
+## 정리
+
+- partitioning : table을 목적에 따라 작은 table들로 나누는 방식
+- sharding : horizontal partitioning으로 나누어진 table들을 각각의(독립된) DB 서버에 저장하는 방식
+- replication : DB를 복제해서 여러 대의 DB 서버에 저장하는 방식
\ No newline at end of file
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture30] dbcp/README.md" "b/\352\271\200\354\227\260\354\232\261/[lecture30] dbcp/README.md"
new file mode 100644
index 0000000..ae99e37
--- /dev/null
+++ "b/\352\271\200\354\227\260\354\232\261/[lecture30] dbcp/README.md"
@@ -0,0 +1,27 @@
+> # [Lecture 30](https://www.youtube.com/watch?v=zowzVqx3MQ4&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=30)
+
+## 주요 내용
+
+- DBCP란?
+- 성능에 도움되는 이유
+- DBCP 튜닝 팁
+
+## DBCP
+
+- DataBase Connection Pool
+- connection을 재사용하여 열고 닫는 시간을 절약할 수 있음
+
+## DBCP 설정 방법 (Spring hikariCP - MySQL 기준)
+
+- max_connections (MySQL) : client와 맺을 수 있는 최대 connection 수
+- wait_timeout (MySQL) : connection이 inactive 할 때 다시 요청이 오기까지 얼마의 시간을 기다린 뒤에 close할 것인지를 결정
+- minimumIdle (hikariCP) : pool에서 유지하는 최소한의 idle connection 수
+- maximumPoolSize (hikariCP) : pool이 가질 수 있는 최대 connection 수 (idle과 active(in-use) connection 합쳐서 최대 수)
+- idle connection 수가 minimumIdle보다 작고, 전체 connection 수도 maximumPoolSize보다 작다면 신속하게 추가로 connection을 만듦
+- 즉, maximumPoolSize는 Pool에 존재할 수 있는 connection의 최대 수이며 minimumIdle은 Pool에 사용하지 않는 connection이 최소한 몇개는 있어야 된다는 것으로 connection이 maximumPoolSize 미만이고 idle connection이 minimumIdle 미만이라면 connection을 만든다!!
+- 기본 값은 maximumPoolSize와 minimumIdle이 동일함 (= pool size 고정)
+- maxLifetime (hikariCP) : pool에서 connection의 최대 수명
+ - idle connection은 maxLifetime을 넘기면 바로 제거
+ - active인 경우라면 maxLifetime을 넘기면 pool로 반환된 후 제거
+ - 이 값은 DB의 connection time limit(MySQL에서는 wait_timeout)보다 몇 초 짧게 설정해야 함
+- connectionTimeout (hikariCP) : pool에서 connection을 받기 위한 대기 시간
\ No newline at end of file
diff --git "a/\352\271\200\354\227\260\354\232\261/[lecture31] NoSQL/README.md" "b/\352\271\200\354\227\260\354\232\261/[lecture31] NoSQL/README.md"
new file mode 100644
index 0000000..845bbaa
--- /dev/null
+++ "b/\352\271\200\354\227\260\354\232\261/[lecture31] NoSQL/README.md"
@@ -0,0 +1,41 @@
+> # [Lecture 31](https://www.youtube.com/watch?v=sqVByJ5tbNA&list=PLcXyemr8ZeoREWGhhZi5FZs6cvymjIBVe&index=31)
+
+## 주요 내용
+
+- NoSQL이란?
+- RDB vs NoSQL
+- MongoDB
+- Redis
+
+## RDB 단점
+
+- 경직된 스키마 / 유연한 확장성의 부족 (새로운 기능이 추가될 때마다 컬럼을 추가해야하는 상황이 발생하기도 함)
+- 정규화로 인한 과도한 조인과 성능 하락
+- scale-out이 쉽지 않음 (여기서의 scale-out은 DB 서버를 추가하는 것)
+- ACID를 보장하려다 보니 DB 서버의 performance에 영향을 줌
+
+## NoSQL
+
+- Not only SQL
+- mongoDB, redis, DynamoDB …
+
+## NoSQL 특징
+
+- 유연한 스키마 / 스키마 관리를 application 레벨에서 함 (개발자가 부담)
+- 데이터 중복 허용 (join 회피)
+- scale-out이 쉽고 편함 (서버 여러 대로 하나의 클러스터를 구성하여 사용)
+- ACID의 일부를 포기하고 high-throughput, low-latency 추구 (금융 시스템처럼 consistency가 중요한 환경에서는 사용하기가 조심스러움)
+
+## Redis
+
+- in-memory key-value database, cache …
+- 메모리로도 사용하기도 하고 캐시로도 사용하기도 하고 …
+- data type : string, list, set, hash, sorted set …
+- hash-based sharded cluster
+- High Availability (replication, automatic failover)
+- in-memory로 SSD와 HDD보다 빠르기 때문에 주로 cache처럼 사용함
+- 기본 동작 과정
+ 1. 백앤드에서 redis에 데이터가 있는지 확인 (redis에 데이터 존재하지 않음)
+ 2. 백앤드에서 DB에 데이터가 있는지 확인 (DB에 데이터 존재)
+ 3. 백앤드에서 가공하여서 프론트로 보여줌과 동시에 redis에 데이터를 key-value 형태로 저장
+ 4. 1~3번 반복
\ No newline at end of file