티스토리 뷰
항해 99 과정서 콘서트 좌석 관련 테이블 형태는 다음과 같다.
제약조건:
좌석수: 1~50
콘서트수: 1~200
좌석상태: EMPTY, RESERVED
seat_number: 좌석 정보
show_id: 콘서트 아이디
occupied_status: EMPTY, RESERVED
이다.
1번 콘서트에서 잔여좌석 확인때 다음과 같이 수행한다.
select * from seat_info where occupied_status = "EMPTY" and show_id = 1;
Explain view로 보면 Full Table Scan을 수행한다.
여기서 풀테이블 스캔을 피해가려면 Index를 걸 수 있다.
Index는 Cardinality가 큰 녀석을 걸면된다. 직감적으로 show_id에 걸면 될 것이다.(1~50)이므로.
Index를 걸 때도 복합 인덱스 선택방향이 있는데, 다음과 같이 선택방향이 있을 것이다.
> (show_id)
> (show_id, occupied_status)
> (show_id, seat_number, occupied_status)
다만, occupied_status는 EMPTY, RESERVED 두 가지 상태만 존재하므로 카디날리티가 2밖에 되지 않는다. 이런경우 다음과 같은 단점이 있다.
1. 카디널리티가 낮으므로, 인덱스 탐색 범위가 넓어지고 최악의 경우 FULL TABLE SCAN보다 성능이 낮을 수 있다.
2. 좌석의 상태는 자주 변경된다. 인덱스는 삽입과 제거의 성능을 저하하지만 조회의 속도를 빠르게 하는 것이다. 상태가 EMPTY, RESERVED의 변경이 잦다면 인덱스를 선택하는데 더 좋지 않은 선택사항이 될 수 있다.
그래서 나의 최종적인 결정은 show_id 에만 걸게 하였다.
스프링에서 인덱스를 걸기 위해 다음과 같이 수행하였다.
package reservation.Domain;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
@Table(name="seat_info", indexes = {
@Index(name = "IDX_show_id", columnList = "show_id")
})
public class Seat {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name="seat_number")
private int seatNumber;
@Column(name="occupied_status")
private String occupiedStatus;
@Column
@Version
private int version;
@ManyToOne
@JoinColumn(name="show_id")
private Show concertShow;
public reservation.DTO.Seat toSeatDTO(){
return reservation.DTO.Seat.builder()
.id(this.id)
.seatNumber(this.seatNumber)
.occupiedStatus(this.occupiedStatus)
.build();
}
}
실행결과는 다음과같다.
query cost가 875.8 에서 17.5로 무려 50배, 98% 감소하게되었다.
다음은 내가 삽입 쿼리를 만드는 파이썬 테스트 코드이다.
from random import choice
for i in range(1, 200):
print(f"insert into concert_show (id, price, concert_id) values({i}, 1000, 1);")
print("")
for i in range(1, 200):
for j in range(1, 50):
val = choice(["EMPTY", "RESERVED"])
print(
"insert into seat_info (id, seat_number, occupied_status, version, show_id)" +
f"values ({i*50+j}, {j}, \"{val}\", 0, {i});"
)
문서끝
'개발이야기' 카테고리의 다른 글
항해99) 트랜잭션 관심 분리와 애플리케이션 이벤트 활용 - 문서 (0) | 2024.05.14 |
---|---|
항해 99) 대기열 이야기 (0) | 2024.05.10 |
python의 GC, 가비지 콜렉션 (0) | 2024.02.20 |
grafana cloud 에서 디스코드(discord) Alert 설정하기 (0) | 2024.02.19 |
프로메테우스 + grafana cloud 설정 후기 (2) | 2024.02.18 |
- Total
- Today
- Yesterday
- 항해99
- 로젠
- grafana cloud
- arena simulation
- Simulation
- 대규모 시스템 설계 기초
- Grafana
- 아레나시뮬레이션
- Arena
- 엄청난 인내심과 시뮬레이션을 위한 아레나 툴
- 명제논리
- beginning javascript
- 아레나
- rosen
- 그라파나
- 아레나 시뮬레이션
- 이산 수학
- 최단경로 알고리즘
- Discrete Mathematics
- 자바스크립트
- paul wilton
- 백준
- Propositional and Predicate Logic
- flutter
- 시뮬레이션
- javascript
- 데이터 중심 애플리케이션 설계
- 자바스크립트 예제
- 가상 면접 사례로 배우는 대규모 시스템 설계 기초
- 이산수학
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |