데이터베이스 애플리케이션 구현 단계

데이터 모델링

성공적인 애플리케이션 설계를 위한 핵심은 데이터 모델링입니다. 비즈니스 요구사항을 정확하게 반영하는 데이터 모델을 구축하는 것이 중요합니다. 정확한 데이터 모델링은 효율적인 쿼리 작성과 성능 개선에 직접적인 영향을 미칩니다.

  • 정확한 요구사항 분석: 데이터 모델링 전에 비즈니스 요구사항을 철저히 분석해야 합니다.
  • 정규화: 중복을 최소화하고 데이터 일관성을 유지하기 위해 데이터베이스 정규화를 수행합니다. 하지만 지나친 정규화는 조인 연산을 증가시켜 성능 저하를 초래할 수 있으므로 적절한 수준에서 조절해야 합니다.
  • 역정규화: 특정 상황에서는 성능 향상을 위해 의도적으로 역정규화를 고려할 수 있습니다.

다음은 간단한 예시입니다.


    -- 부서 테이블 생성
    CREATE TABLE departments (
     dept_id NUMBER PRIMARY KEY,
     dept_name VARCHAR2(50) NOT NULL,
     location_id NUMBER
    );

    -- 직원 테이블 생성
    CREATE TABLE employees (
     emp_id NUMBER PRIMARY KEY,
     emp_name VARCHAR2(50) NOT NULL,
     dept_id NUMBER REFERENCES departments(dept_id),
     salary NUMBER
    );
   

SQL 쿼리 효율성

SQL 쿼리 효율성은 애플리케이션 성능에 큰 영향을 미칩니다. 개발자는 쿼리가 어떻게 실행되는지 이해하고, 실행 계획을 분석하여 쿼리를 최적화해야 합니다.

  • 인덱스 활용: WHERE 절에 자주 사용되는 컬럼에는 인덱스를 생성하여 쿼리 성능을 향상시킵니다.
  • 조인 최적화: 조인 연산은 성능에 큰 영향을 미치므로, 적절한 조인 순서와 조인 방법을 선택해야 합니다.
  • 불필요한 연산 제거: 쿼리에서 불필요한 연산(예: DISTINCT, ORDER BY)을 제거하여 성능을 개선합니다.
  • 바인드 변수 사용: 리터럴 대신 바인드 변수를 사용하여 파싱 overhead를 줄입니다.

다음은 SQL 쿼리 최적화 예시입니다.


    -- 비효율적인 쿼리 (인덱스 미사용)
    SELECT emp_id, emp_name
    FROM employees
    WHERE salary > 50000;

    -- 효율적인 쿼리 (인덱스 사용)
    CREATE INDEX idx_employees_salary ON employees(salary);

    SELECT emp_id, emp_name
    FROM employees
    WHERE salary > 50000;
   

효과적인 커서 관리

데이터베이스 연결 및 커서 관리는 애플리케이션 성능에 매우 중요합니다. 불필요한 연결/커서 생성을 최소화하고, 재사용을 극대화해야 합니다.

  • 커넥션 풀 사용: 데이터베이스 연결을 재사용하여 연결 생성 overhead를 줄입니다.
  • 커서 재사용: 동일한 SQL 쿼리를 반복적으로 실행할 때 커서를 재사용하여 파싱 overhead를 줄입니다.
  • 명시적인 커서 닫기: 사용이 완료된 커서는 즉시 닫아 데이터베이스 자원을 확보합니다.

다음은 커넥션 풀을 사용한 예시입니다.


    // JDBC 커넥션 풀 설정 (예시: HikariCP)
    HikariConfig config = new HikariConfig();
    config.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
    config.setUsername("hr");
    config.setPassword("password");
    config.setDriverClassName("oracle.jdbc.driver.OracleDriver");
    config.setMaximumPoolSize(10); // 최대 커넥션 수

    HikariDataSource ds = new HikariDataSource(config);

    // 커넥션 풀에서 커넥션 획득 및 사용
    try (Connection conn = ds.getConnection();
         PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM employees WHERE dept_id = ?")) {
        pstmt.setInt(1, 10); // 부서 ID
        ResultSet rs = pstmt.executeQuery();

        while (rs.next()) {
            System.out.println(rs.getString("emp_name"));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
   

최적화 도구 통계 관리

쿼리 실행 계획은 옵티마이저 통계를 기반으로 생성됩니다. 따라서 최적의 실행 계획을 얻기 위해서는 통계를 최신 상태로 유지하는 것이 중요합니다.

  • 정기적인 통계 수집: DBMS_STATS 패키지를 사용하여 테이블, 인덱스 통계를 정기적으로 수집합니다.
  • 증분 통계 수집: 파티션 테이블의 경우, 변경된 파티션에 대해서만 통계를 수집하여 overhead를 줄입니다.
  • 동적 통계: 통계가 없는 컬럼이나 복잡한 조건이 있는 쿼리에 대해서는 동적 통계를 사용하여 실행 계획을 개선합니다.

다음은 통계 수집 예시입니다.


    -- 테이블 통계 수집
    EXEC DBMS_STATS.GATHER_TABLE_STATS(
     OWNNAME => 'HR',
     TABNAME => 'EMPLOYEES',
     ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE,
     METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO'
    );
   

자동 SQL 튜닝

오라클 데이터베이스는 자동 SQL 튜닝 기능을 제공하여 성능 문제를 자동으로 진단하고 개선합니다. 자동 데이터베이스 진단 모니터(ADDM)는 시스템 성능을 분석하고, SQL 튜닝 Advisor는 비효율적인 SQL 쿼리를 찾아 튜닝 권고안을 제시합니다. SQL 계획 관리 (SPM) 는 검증된 실행 계획을 사용하여 데이터베이스가 알려진 최적의 계획만 사용하도록 보장합니다.


    -- 자동 SQL 튜닝 작업 실행
    EXEC DBMS_AUTO_TASK_ADMIN.ENABLE(task_name => 'auto sql tuning advisor', client_name => null, window_name => null);

    -- SQL 튜닝 Advisor 권고안 확인
    SELECT TASK_NAME, STATUS, ADVICE FROM DBA_ADVISOR_FINDINGS;
   

Real-World 성능 가이드라인

  • 애플리케이션 설계 단계부터 성능을 고려합니다. 비효율적인 설계는 튜닝만으로 해결하기 어렵습니다.
  • SQL 문에서 리터럴 값 대신 바인드 변수를 사용합니다.
  • SQL 계획 안정성을 위해 SQL 계획 기준선을 사용합니다.
  • 쿼리 성능 모니터링을 위해 SQL Developer와 같은 툴을 활용합니다.
위로 스크롤