성능을 위한 모범 사례

이 정보를 사용하여 IBM Cloud 에서 실행 중인 Databases for MongoDB 배포에 모범 사례를 적용하세요.

성능 문제 해결 순서도

순서도를 사용하여 성능 문제를 해결하는 방법과 다음에 수행할 단계를 결정하세요.

┌─────────────────────────────────┐
│   Performance issue detected    │
└────────────┬────────────────────┘
             │
             ▼
┌─────────────────────────────────┐
│  Check IBM Cloud Monitoring     │
│  - CPU > 80%?                   │
│  - Memory > 80%?                │
│  - Disk latency high?           │
└────────────┬────────────────────┘
             │
        ┌────┴────┐
        │  YES    │
        ▼         │
┌──────────────┐  │
│ Scale        │  │
│ resources    │  │
└──────────────┘  │
                  │ NO
                  ▼
        ┌─────────────────────┐
        │ Check slow queries  │
        │ db.system.profile   │
        └─────────┬───────────┘
                  │
             ┌────┴────┐
             │  Found? │
             ▼         │
        ┌─────────┐    │
        │ Optimize│    │
        │ queries │    │
        │ & indexes│   │
        └─────────┘    │
                       │ NO
                       ▼
              ┌────────────────┐
              │ Check Locks    │
              │ currentOp()    │
              └────────┬───────┘
                       │
                  ┌────┴────┐
                  │ Locked? │
                  ▼         │
             ┌─────────┐    │
             │ Kill or │    │
             │ optimize│    │
             └─────────┘    │
                            │ NO
                            ▼
                   ┌────────────────┐
                   │ Check cache    │
                   │ hit ratio      │
                   └────────┬───────┘
                            │
                       ┌────┴────┐
                       │ < 95%?  │
                       ▼         │
                  ┌─────────┐    │
                  │ Scale   │    │
                  │ memory  │    │
                  └─────────┘    │
                                 │ NO
                                 ▼
                        ┌────────────────┐
                        │ Check          │
                        │ replication    │
                        └────────┬───────┘
                                 │
                            ┌────┴────┐
                            │ Lagging?│
                            ▼         │
                       ┌─────────┐    │
                       │ Scale   │    │
                       │ or fix  │    │
                       └─────────┘    │
                                      │ NO
                                      ▼
                             ┌────────────────┐
                             │ Contact IBM    │
                             │ Support        │
                             └────────────────┘

일반적인 안티 패턴

성능 문제를 유발하는 이러한 일반적인 실수를 피하세요.

쿼리 안티 패턴

1. 누락된 인덱스

문제점:

// No index on 'email' field
db.users.find({ email: "user@example.com" })

해결 방법:

// Create index
db.users.createIndex({ email: 1 })

2. 비효율적인 정규식 쿼리

문제점:

// Case-insensitive regex without index
db.users.find({ name: /john/i })

해결 방법:

// Use text index or exact match
db.users.createIndex({ name: "text" })
db.users.find({ $text: { $search: "john" } })

3. 대규모 스킵() 연산

문제점:

// Skipping thousands of documents
db.collection.find().skip(10000).limit(10)

해결 방법:

// Use range queries with indexed field
db.collection.find({ _id: { $gt: lastSeenId } }).limit(10)

4. 불필요한 필드 선택

문제점:

// Fetching entire documents
db.users.find({ status: "active" })

해결 방법:

// Use projection
db.users.find({ status: "active" }, { name: 1, email: 1 })

5. 비효율적인 집계 파이프라인

문제점:

// $match after $lookup
db.orders.aggregate([
  { $lookup: { ... } },
  { $match: { status: "completed" } }
])

해결 방법:

// $match first to reduce documents
db.orders.aggregate([
  { $match: { status: "completed" } },
  { $lookup: { ... } }
])

스키마 설계 문제

1. 무제한 배열

문제점:

// Array grows indefinitely
{
  userId: 123,
  activities: [/* thousands of items */]
}

해결 방법:

// Use separate collection or bucketing
{
  userId: 123,
  month: "2024-01",
  activities: [/* limited items */]
}

2. 과도한 임베딩

문제점:

// Deeply nested documents
{
  user: {
    profile: {
      settings: {
        preferences: {
          // many levels deep
        }
      }
    }
  }
}

해결 방법:

// Flatten or use references
{
  userId: 123,
  profileId: 456
}

3. 대용량 문서

문제점:

// Documents approaching 16MB limit
{
  data: "very large string...",
  attachments: [/* large binary data */]
}

해결 방법:

// Store large data separately (GridFS or object storage)
{
  dataRef: "s3://bucket/key",
  attachments: [{ ref: "gridfs://id" }]
}

연결 관리 실수

1. 연결 풀링을 사용하지 않음

문제점:

// Creating new connection per request
app.get('/api/users', async (req, res) => {
  const client = await MongoClient.connect(uri);
  // ...
  await client.close();
});

해결 방법:

// Reuse connection pool
const client = new MongoClient(uri, { maxPoolSize: 50 });
await client.connect();

app.get('/api/users', async (req, res) => {
  const db = client.db();
  // ...
});

2. 커서를 닫지 않음

문제점:

// Cursor left open
const cursor = db.collection.find();
// Never closed

해결 방법:

// Always close cursors
const cursor = db.collection.find();
try {
  await cursor.forEach(doc => { /* process */ });
} finally {
  await cursor.close();
}

3. 너무 많은 연결

문제점:

// One connection per user session
const connections = new Map();
users.forEach(user => {
  connections.set(user.id, new MongoClient(uri));
});

해결 방법:

// Share connection pool across application
const client = new MongoClient(uri);
// All users share the same pool

인덱싱의 함정

1. 인덱스가 너무 많습니다

문제점:

// Index on every field
db.collection.createIndex({ field1: 1 })
db.collection.createIndex({ field2: 1 })
db.collection.createIndex({ field3: 1 })
// ... 20+ indexes

Impact: 쓰기 속도가 느려지고 저장 공간이 증가합니다.

해결책: 필요한 인덱스만 유지하고 복합 인덱스를 사용하세요.

2. 복합 인덱스의 잘못된 인덱스 순서

문제점:

// Query: { status: "active", createdAt: { $gt: date } }
// Index: { createdAt: 1, status: 1 }  // Wrong order

해결 방법:

// Correct order: equality first, range second
db.collection.createIndex({ status: 1, createdAt: 1 })

3. 적용 대상 쿼리를 사용하지 않음

문제점:

// Index exists but query not covered
db.users.createIndex({ email: 1 })
db.users.find({ email: "user@example.com" }, { name: 1, email: 1 })
// Still fetches documents

해결 방법:

// Include all projected fields in index
db.users.createIndex({ email: 1, name: 1 })
db.users.find({ email: "user@example.com" }, { name: 1, email: 1, _id: 0 })

부록: 메트릭 임계값

주요 성과 지표에 대한 권장 임계값입니다.

지표 임계값
메트릭 경고 임계값 위험 임계값 권장 조치
CPU 이용률 75% 90% CPU 코어 확장
메모리 사용률 80% 95% 메모리 할당 규모 조정
디스크 활용도 80% 90% 디스크 공간 확장
디스크 IOPS 한도의 80% 한도의 95% 디스크 크기를 늘려 IOPS 향상
활성 연결 수 한도의 80% 한도의 95% 계획 확장 또는 연결 풀링 최적화
복제 지연 5초 30초 필요한 경우 조사 및 확장
캐시 적중률 < 95% < 90% 메모리 확장 또는 쿼리 최적화
쿼리 실행 시간 100ms (평균) 1000ms (평균) 쿼리 및 인덱스 최적화
잠금 대기 시간

100ms

1000ms

운영 최적화 및 장기 실행 쿼리 종료
페이지 결함

100/sec

1000/sec

메모리 확장
네트워크 대기 시간

10ms

50ms

네트워크 구성 확인
백업 지속 기간 1시간 4시간 확장 또는 최적화 고려

모니터링 빈도 권장 사항

모니터링 빈도
지표 범주 확인 빈도 보존 기간
자원 활용도 1분마다 30일
쿼리 성능 5분마다 14일
복제 상태 1분마다 30일
연결 통계 5분마다 14일
백업 상태 1시간마다 90일
디스크 증가 1시간마다 90일

알림 구성 예시

CPU 경고

Condition: CPU > 80% for 10 consecutive minutes
Action: Send notification to ops team
Escalation: Page on-call if > 90% for 15 minutes

메모리 경고

Condition: Memory > 85% for 15 consecutive minutes
Action: Send notification to ops team
Escalation: Auto-scale if > 95% for 10 minutes

복제 지연 경고

Condition: Lag > 10 seconds
Action: Send notification immediately
Escalation: Page on-call if > 60 seconds

디스크 공간 경고

Condition: Disk > 80%
Action: Send notification to ops team
Escalation: Create incident if > 90%

모범 사례 요약

우수 사례
영역 권장사항
색인화 사용하지 않는 인덱스를 정기적으로 검토하고 제거
모니터링 CPU, 메모리, 디스크 및 복제 지연에 대한 알림을 구성하세요
용량 계획 디스크 사용량을 80% 미만으로 유지하고 선제적으로 확장하기
쿼리 디자인 개발 중 계획 설명 사용
스케일링 포화 전에 선제적으로 확장
연결 풀링 연결 풀을 사용하고 요청별 연결을 피하세요
읽기 환경설정 읽기량이 많은 워크로드에 보조 스토리지 사용
우려 사항 작성 내구성과 성능 요구 사항의 균형
스키마 디자인 무제한 배열 및 과도한 임베딩 방지
백업 계획 트래픽이 적은 기간의 일정
네트워크 IBM Cloud 워크로드에 비공개 엔드포인트 사용
보안 자격 증명을 정기적으로 교체하고 IP 허용 목록 사용
문서 기준 지표 및 일반 패턴 문서화
테스트 비프로덕션 환경에서 먼저 성능 변경 사항 테스트
지원 지원팀에 문의하기 전에 진단 정보 수집

추가 자원

IBM Cloud 문서

MongoDB 문서

커뮤니티 자료