트리거(Trigger)는 특정 테이블에 INSERT, DELETE, UPDATE 같은 DML 문이 수행되었을 때, 데이터베이스에서 자동으로 동작하도록 작성된 프로그램 ▶︎ 사용자가 직접 호출하는 것이 아니라, 데이터베이스에서 자동적으로 호출하는 것이 가장 큰 특징
🎈요즘은 Trigger를 DB에서 직접 적용하기보다는 가급적이면 Javascript단에서 적용하는 편
인덱스(= 책갈피)는 테이블을 빨리 조회하기 위해 테이블 데이터에 포인터를 주는 검색 방법
- 옵티마이저: 검색을 효율적으로 해주는 DB 내장기능
- 실행계획: 효율적인 검색 계획
- Explain 명령어: 옵티마이저가 결정한 실행결과를 볼 수 있는 명령어
주의!‼️ 빠른 검색을 위해 모든 컬럼에 인덱스를 적용하게 되면
데이터를 등록, 수정할 때 마다 정렬을 시도하기 때문에 속도가 느려지게됨
따라서, 검색에 자주 사용되는 컬럼에 인덱스를 적용하는 것이 좋음
//dbeaver - Script
# 데이터 개수 조회
select COUNT(*) from board
;
# 쿼리 검색 속도 비교
select *
from board
where title = '0.719410951919305'
;
select *
from board
where number = 36
;
# 옵티마이저로 실행계획 확인
explain
select *
from board
where title = '0.719410951919305'
;
explain
select *
from board
where number = 36
;
# 인덱스 확인
show index from board
;
#인덱스 생성
create index idx_title on board(title)
;
# 옵티마이저로 실행계획 다시 확인
explain
select *
from board
where title = '0.719410951919305'
;
#인뎅싱된 컬럼으로 재쿼리 후, 성능 비교
select *
from board
where title = '0.719410951919305'
;
Feature of Redis
- NoSQL로서 Key-Value 타입의 저장소인
레디스(Redis, Remote Dictionary Server)
영속성을 지원하는 인메모리 데이터 저장소
읽기 성능 증대를 위한 서버 측 복제를 지원
쓰기 성능 증대를 위한 클라이언트 측 샤딩(Sharding) 지원
다양한 서비스에서 사용되며 검증된 기술
문자열, 리스트, 해시, 셋, 정렬된 셋과 같은 다양한 데이터형을 지원. 메모리 저장소임에도 불구하고 많은 데이터형을 지원하므로 다양한 기능을 구현
1ms 이하의 응답대기시간
1ms 이하의 응답시간을 제공 → 데이터를 메모리에 저장하기 때문에, 디스크 기반의 데이터 베이스보다 빠르게 데이터를 읽을 수 있음
개발의 용이성
문법적으로 사용하기 쉽고, 개발코드 양 또한 적음
데이터 파티셔닝
데이터를 여러 노드에 분산하여 저장 → 수요가 증가할 때 더 많은 데이터를 효과적으로 처리하기 위하여 스케일아웃이 가능
다양한 프로그래밍 언어 지원
자바, 파이썬, C, C++, C#, JavaScript, Node.Js, Ruby, Go 등
멀티스레드
를 지원하기 때문에, 멀티프로세스코어
를 사용 가능 → 스케일업을 통하여 더욱 많은 작업처리를 할 수 있음
1. 더욱 다양한 데이터 구조
문자열 뿐만 아니라 List
, Set
, 정렬된 Set
, Hash
, Bit 배열
, hyperloglogs
(매우 적은 메모리로 집합의 개수를 추정할 수 있는 방법)을 지원 i.e)Sorted Set
을 활용하여 게임유저의 상위랭크 정보 제공 가능
2. Snapshots
레디스는 특정시점에 데이터를 디스크에 저장하여 파일 보관이 가능
또한, 장애 상황시 복구에 사용할 수 있음
3. 복제
Master — Salves
구조로, 여러개의 복제본을 만들 수 있음 → 데이터베이스 읽기를 확장할 수 있기 때문에 높은 가용성(오랜 시간동안 고장나지 않음) 클러스터를 제공
4. 트랜젝션
트렌젝션이란 데이터베이스 상태를 변경시키는 작업 단위를 의미하고, 원자성, 일관성, 독립성, 지속성의 특징을 가지고 있음 → Redis 지원
5. Pub / Sub messaging
Publish(발행)과 Sub(구독)방식의 메시지를 패턴 검색이 가능 →높은 성능을 요구하는 채팅, 실시간 스트리밍, SNS 피드 그리고 서버상호통신에 사용 가능
6. 루아 스크립트 지원
매우 경량화된 절차스크립트 언어인 루아를 지원 → eval 명령어를 사용하여 루아스크립트를 실행시킬 수 있음, 프로그램을 명료하게하고 성능을 높일 수 있음
7. 위치기반 데이터 타입 지원
Redis는 실시간 위치기반데이터를 지원 → 두 위치의 거리를 찾거나, 사이에 있는 요소 찾기등의 작업을 수행할 수 있음 i.e) 맛집, 길찾기 그리고 지도기반의 고성능 서비스를 제공
검색 시 Redis에서 먼저 찾아보고 Redis에 저장된 내용이 있다면 저장된 정보를 바로 보여주고
없다면 MySQL에서 정보를 보여준 다음 검색된 내용을 redis에 저장하는 방식
Cache-Aside패턴를 사용한다면 같은 내용의 2번째 검색부터는 redis에 저장된 정보를 보여주기 때문에 속도가 빨라짐
// app.module.ts
@Module({
imports: [
//
//
//
CacheModule.register<RedisClientOptions>({ // CacheModule.register<CacheModule의 타입 명시>
store: redisStore, //저장 위치
url: 'redis://my-redis:6379', // redis 주소
isGlobal: true,// 모든 API에서 사용가능하게 하는 역할
}),
],
})
// boards.resolver.ts
import { Cache } from 'cache-manager';
import { CACHE_MANAGER, Inject } from '@nestjs/common';
@Resolver()
export class BoardResolver {
constructor(
private readonly boardService: BoardService,
@Inject(CACHE_MANAGER)
private readonly cacheManager: Cache,
) {}
@Mutation(() => String)
async createBoard(
@Args({ name: 'writer', nullable: true }) writer: string,
@Args('title') title: string,
@Args('contents') contents: string,
@Args('createBoardInput') createBoardInput: CreateBoardInput,
) {
// 1. 캐시에 등록하는 연습
await this.cacheManager.set('aaa', createBoardInput, {
ttl: 0,
}); //key-value 형태 저장, ttl : 0 무제한 저장
// 2. 캐시에서 조회하는 연습
const mycache = await this.cacheManager.get('aaa');// get을 통해 저장된 정보 가져옴 (key값)
console.log(mycache);
return '지금은 캐시 테스트 중!!!';
////////////////////////////////////////////////////////
// 레디스 연습을 위해서 잠시 주석걸기!!
// console.log(args);
// console.log(writer);
// console.log(title);
// console.log(contents);
// console.log(createBoardInput);
// return this.boardService.create();
}
set
를 통해 redis에 저장get
을 통해 redis에 저장된 정보를 가져올 수 있음ttl
을 통해 저장 기간을 지정 가능ttl
을 생략한다면 default값은 5초ttl: 0
무제한 저장