데이터베이스 최적화: 쿼리와 인덱싱

개발팀
2분 읽기
데이터베이스SQL성능

데이터베이스 최적화: 쿼리와 인덱싱

데이터베이스 최적화는 애플리케이션 성능의 핵심 요소입니다.

인덱싱 전략

기본 인덱스 생성

-- 단일 열 인덱스
CREATE INDEX idx_users_email ON users(email);

-- 복합 인덱스
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);

-- 유니크 인덱스
CREATE UNIQUE INDEX idx_users_email_unique ON users(email);

인덱스 선택 기준

  1. 자주 검색되는 열: WHERE 절에 자주 사용
  2. 정렬 열: ORDER BY에 사용되는 열
  3. 조인 열: JOIN 조건에 사용되는 열
  4. 선택도 높은 열: 중복 값이 적은 열

쿼리 최적화

N+1 문제 해결

// 나쁜 예: N+1 쿼리
const users = await User.findAll();
for (const user of users) {
  user.posts = await Post.findByUserId(user.id); // N개의 쿼리
}

// 좋은 예: JOIN 사용
const users = await User.findAll({
  include: 'posts' // 1개의 쿼리로 해결
});

필요한 열만 선택

-- 나쁜 예
SELECT * FROM users WHERE id = 1;

-- 좋은 예
SELECT id, name, email FROM users WHERE id = 1;

쿼리 실행 계획 분석

-- MySQL
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';

-- PostgreSQL
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

캐싱 전략

// Redis를 사용한 캐싱
async function getUserWithCache(userId) {
  const cached = await redis.get(`user:${userId}`);
  if (cached) return JSON.parse(cached);

  const user = await User.findById(userId);
  await redis.set(`user:${userId}`, JSON.stringify(user), 'EX', 3600);
  return user;
}

파티셔닝

-- 날짜 기반 파티셔닝
CREATE TABLE logs (
  id INT,
  created_at DATE,
  message TEXT
) PARTITION BY RANGE (YEAR(created_at)) (
  PARTITION p2023 VALUES LESS THAN (2024),
  PARTITION p2024 VALUES LESS THAN (2025)
);

성능 모니터링

슬로우 쿼리 로그

-- MySQL에서 슬로우 쿼리 로깅 활성화
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;

최적화 체크리스트

  • 필요한 인덱스 생성 여부 확인
  • N+1 쿼리 문제 해결
  • 쿼리 실행 계획 검토
  • 캐싱 적용 가능성 검토
  • 테이블 파티셔닝 필요성 검토
  • 슬로우 쿼리 모니터링

데이터베이스 최적화는 지속적인 모니터링과 개선이 필요합니다.

데이터베이스 최적화: 쿼리와 인덱싱 | 블로그