일단 SQL 쿼리가 들어오면
sqlCopySELECT * FROM users WHERE email = 'kim@mail.com';
DB가 "ㅇㅋ 이메일로 찾는 거구나? email 인덱스 있으니까 그거 쓰면 되겠다!" 이러면서 실행 계획 세워요.
메모리 체크
먼저 메모리(버퍼 풀)에 필요한 데이터가 있나 확인함!
진짜 카톡에서 최근에 봤던 메시지 바로 뜨는 것처럼요.
없으면 어쩔 수 없이 디스크에서 읽어와야 됨 ㅠㅠ (개느림)
B+ Tree 타고 내려가기
Copy여기서부터 진짜 찾기 시작!
[f@mail.com]
⬇️
[p@mail.com] (여기 있나?)
⬇️
[k@..] (드디어 찾았다!)
위에서부터 쭉 내려가면서 찾는데, 마치 네이버 사전에서 단어 찾는 것처럼 ㄱㄴㄷ 순으로 찾아감!
ID 찾기
email 인덱스에서 찾으면 "아 이 데이터는 id=1이구나!" 이러면서 이제 진짜 데이터 있는 곳 찾으러 감.
Copy요런 식으로 또 찾아감
[5]
/ \
[2][7]
/
[1] <- 여기야!
실제 데이터 가져오기
드디어 진짜 데이터가 있는 페이지 찾음!
페이지에서 우리가 원하는 데이터 쏙 빼옴
이게 다 0.1초도 안 걸림 ㄷㄷ
메모리 관리
찾은 데이터는 메모리에 저장해둠 (나중에 또 찾으면 빨리 찾으려고)
메모리 꽉 차면 오래된 거부터 지움 (최근 카톡은 바로 뜨고 옛날 카톡은 좀 걸리는 것처럼요!)
동시성 처리
다른 사람이 동시에 같은 데이터 보려고 할 수 있으니까
"잠깐만요~ 제가 보는 중이에요!" 이런 식으로 표시해둠 (락이라고 함)
인스타 스토리 올릴 때 여러 명이 동시에 봐도 괜찮은 것처럼!
이래서 은행 앱이나 카톡에서 데이터 찾을 때 엄청 빠른 거예요!
B+ Tree가 있어서 마치 책에서 목차로 페이지 찾는 것처럼 바로바로 찾을 수 있는 거죠 ㅎㅎ
궁금한 거 있으면 또 물어보세요~! 😊
ㅋㅋㅋ 이메일 저장하는 거 재밌게 설명해드릴게요!
이메일 정렬하는 방식
Copy이메일 예시:
abc@mail.com
ABC@mail.com
민수@mail.com
DB한테 "야 너 대소문자 구분해서 정렬해줘!" 아니면 "대소문자 구분하지 말고 정렬해줘!" 이렇게 설정할 수 있음!
마치 카톡 프사에서 한글이름/영어이름 정렬하는 것처럼요 ㅎㅎ
저장할 때 꿀팁
Copythese.people@gmail.com
those.users@gmail.com
thy.friends@gmail.com
똑똑한 DB는 '@gmail.com' 이런 애들 매번 저장 안 하고 한 번만 저장해놓음!
ㄹㅇ 수납박스에 자주 쓰는 거 따로 빼두는 것처럼요 👍
공간 관리 (진짜 수납의 신)
Copy수납박스가 꽉 찼을 때:
[민수 | 영희 | 철수 | 영민]
공간 나눠서 정리:
[민수 | 영희] ---> [철수 | 영민]
DB가 알아서 공간 딱 나눠서 깔끔하게 정리함!
찾을 때 꿀팁!
sqlCopy-- 이건 개꿀임
WHERE email LIKE 'kim%' / kim으로 시작하는 애들 찾기 /
-- 이건 좀 별로...
WHERE email LIKE '%kim%' / kim이 중간에 있는 애들 찾기 /
첫 번째처럼 하면 인스타 검색할 때처럼 후다닥 찾아주는데,
두 번째는 네이버 카페 글 찾을 때처럼 겁나 오래 걸림 ㅠㅠ
실제로 저장된 모습
Copy [kim@mail.com]
/ \
[jake@mail.com][lee@mail.com]
/ / \
[hong@...][kim.a@...] [park@...]
이렇게 트리 구조로 저장하는데, 마치 폴더 정리하듯이 깔끔하게 정리됨!
진짜 DB가 수납의 신이랑 비슷한데, 이메일 주소도 사전순으로 쫙쫙 정리해두고 필요할 때마다 후다닥 찾아주는거죠 😎
근데 각 DB마다 정리하는 방식이 좀 달라요! MySQL이랑 PostgreSQL이랑 다 자기만의 방식이 있음 ㅋㅋ
마치 MBTI처럼 각자 다 자기만의 정리 방식이 있는 거죠 ㅎㅎ
인메모리 DB (Redis)의 구조
Copy[메모리 구조]
RAM (휘발성 메모리)
├── Key-Value Store
│ ├── "user:1" -> {"name": "김철수", "points": 100}
│ ├── "ranking" -> [user1, user2, user3]
│ └── "session:123" -> {"user_id": 1, "login_time": ...}
└── 메모리 관리자
├── maxmemory 설정
└── eviction 정책 (메모리 부족할 때 어떤 데이터 삭제할지)
진짜 카톡으로 비유하면:
카톡 켜놓으면 채팅 내용이 폰 메모리에 있어서 엄청 빠름
근데 폰 끄면 최신 메시지들 날아가고 다시 서버에서 받아와야 함
Redis도 이런 식! 빠른 대신에 휘발성이라는 단점이 있음
Redis의 자료구조들
redisCopy# 1. Strings (그냥 값 저장)
SET name "김철수"
GET name
LPUSH chatroom "안녕하세요"
LPUSH chatroom "뭐하세요?"
LRANGE chatroom 0 -1 # 채팅 내역 다 보기
SADD friends "영희" # 친구 추가
SADD friends "민수"
SMEMBERS friends # 친구 목록 보기
ZADD ranking 100 "user1" # 유저1: 100점
ZADD ranking 200 "user2" # 유저2: 200점
ZREVRANGE ranking 0 -1 # 랭킹 전체 보기
HSET user:1 name "철수" age "20"
HGET user:1 name # "철수" 출력
Pub/Sub 시스템 더 자세히
Copy실제 동작 과정:
1) 구독자들 채널 구독
SUBSCRIBE korea_chat
SUBSCRIBE game_chat
2) 발행자가 메시지 발행
PUBLISH korea_chat "안녕하세요!"
3) Redis가 하는 일
4) 구독자가 받는 메시지 형태
{
"type": "message",
"channel": "korea_chat",
"data": "안녕하세요!"
}
Redis 트랜잭션의 한계
redisCopy# Redis 트랜잭션
MULTI
SET points:user1 90
DECR points:user1 # 89됨
SET points:user2 110
INCR points:user2 # 111됨
EXEC
MULTI
GET points:user1
IF points:user1 < 100
INCR points:user1
ELSE
DECR points:user1
END
EXEC
왜 이런 구조를 가졌냐면:
Redis는 싱글스레드라서 atomic 연산이 보장됨
근데 그만큼 복잡한 연산은 못하게 만듦
대신 빠름! (멀티스레드면 락 걸고 풀고 하느라 느려짐)
실제 사용 예시:
Copy[Redis 쓰는 경우]
[MySQL 쓰는 경우]