1. 인덱스란?
책의 목차처럼, 테이블의 특정 컬럼 값과 그 값이 저장된 물리적 위치(레코드의 주소)를 매핑한 자료구조이다.
인덱스를 통해 테이블 전체를 순차 검색(Full Table Scan)하는 대신, 필요한 레코드의 위치를 빠르게 찾을 수 있어 조회 성능이 크게 향상된다.
2. 인덱스 하기 전
5만건의 데이터를 넣은 후(authorId가 3), 약 20건의 post만 authorId가 2인 사용자로 지정했다면,
Postman으로 요청 시 약 170ms 가 걸리는 것을 볼 수 있다.
DB에서 좀 더 자세히 분석을 해보면, Parallel Seq Scan on posts_model 이라고 뜨는데 이것은 posts_model을 병렬 스캔을 통해 authorId가 2인 사용자를 찾는다는 뜻이다. (요약하자면 오래걸린다는 뜻)
Execution Time이 121.665 ms 가 나온다.
3. 인덱싱
import { IsString } from 'class-validator';
import { BaseModel } from 'src/common/entity/base.entity';
import { ImageModel } from 'src/common/entity/image.entity';
import { stringValidationMessage } from 'src/common/validation-message/string-validation.message';
import { UsersModel } from 'src/users/entity/users.entity';
import { Column, Entity, Index, JoinColumn, ManyToOne, OneToMany, RelationId } from 'typeorm';
import { CommentsModel } from '../comments/entity/comments.entity';
@Entity()
export class PostsModel extends BaseModel {
@ManyToOne(() => UsersModel, (user) => user.posts, {
nullable: false,
})
@JoinColumn( {name: 'authorId'})
author: UsersModel;
@Column()
@Index('idx_post_author_id')
@RelationId((post: PostsModel) => post.author)
authorId: number;
@Column()
@IsString({
message: stringValidationMessage,
})
title: string;
@Column()
@IsString({
message: stringValidationMessage,
})
content: string;
@Column({
default: 0,
})
likeCount: number;
@Column({
default: 0,
})
commentCount: number;
@OneToMany(() => ImageModel, (image) => image.post)
images: ImageModel[];
@OneToMany(() => CommentsModel, (comment) => comment.post)
comments: CommentsModel[];
}
@Column()
@Index('idx_post_author_id')
@RelationId((post: PostsModel) => post.author)
authorId: number;
기존에 없던 authorId를 추가하였다.
데코레이터는 @Index(키), @RelationId((엔티티) => 엔티티의 컬럼)
이렇게하면 authorId는 PostsModel의 author와 연결되어 인덱싱이 생성된다.
// synchronize: true,
synchronize: configService.get<boolean>('db.synchronize', true),
app.module에서 DB와 synchronize가 true가 되어있어야 서버를 재시작한 경우 인덱싱이 진행된다.
npm run typeorm migration:generate -- -n UpdatePostsIndexes
npm run typeorm migration:run
혹은 위와 같은 명령어로 인덱싱을 진행할 수 있다.
SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'posts_model';
서버 재시작 후 위와 쿼리를 입력하면 인덱싱이 되었다는 결과를 볼 수 있다.
4. 인덱싱 결과
우선 Postman에서 요청 시 기존 170 ms 에서 92 ms 로 개선된 것을 볼 수 있다.
다시 authorId가 2인 Post들을 검색하면
Index Scan using idx_post_author_id on posts_model 이라는 메세지를 확인할 수 있는데, 인덱싱이 잘 적용된 것을 볼 수 있다.
Execution Time 도 기존 121.665 ms -> 0.045 ms 로 대폭 줄어든 것을 볼 수 있다.
5. 번외 (인덱스 삭제)
DROP INDEX IF EXISTS [인덱스키값];
기존 인덱스를 지우고 싶은 경우 위와 같은 쿼리로 지울 수 있다.
다만 서버를 재시작하면 인덱싱이 진행될테니 데코레이터 된 부분들을 적절히 수정해야할 것이다.
'NestJS' 카테고리의 다른 글
[NestJS] 각종 보안 적용하기 (0) | 2025.05.27 |
---|---|
[NestJS] GraphQL 적용하기 (0) | 2025.05.26 |
[NestJS] 데이터 시딩 - 50만건 더미 데이터 추가하기 (0) | 2025.05.08 |
[NestJS] Redis 적용하기 - Rate Limiting (0) | 2025.04.21 |
[NestJS] Redis 적용하기 (캐싱) (0) | 2025.04.17 |