* 무단횡단

   - 목표 : 다중 값 속성 저장

   - 문제 : 교차 테이블 생성을 피하기 위해 쉼표로 구분된 목록에 저장

   - 허용 : 반정규화를 적용해 성능을 향상시키기 위한 방법으로는 사용할 수 있다

   - 해법 : 교차 테이블 생성

 

 

* 단순한 트리

   - 목표 : 계층구조 저장 및 조회하기

   - 문제 : Adjacency List 로 구현 시, 깊은 트리 구조의 데이터를 처리하기 어렵다

   - 허용 : 부모-자식 관계 이상으로 깊이가 깊어지지 않는 경우

   - 해법 :

     1) Path Enumeration

          - 일련의 조상을 각 노드의 속성으로 저장 (e.g. 파일 시스템의 디렉토리 경로)

          - 단점 : 경로에 대한 검증이 필요, 문자열 길이에 따라 깊이가 제한된다

     2) Nested Sets

          - 부모가 자손 집합에 대한 정보를 저장

          - 단점 : 트리 수정이 복잡하고 어렵다 (빠른 조회에 적합)

     3) Closure Table

          - 트리의 모든 경로, 즉, 조상/자손 관계를 가진 노드의 쌍을 한 행으로 저장

          - 단점 : 별도의 테이블이 필요하고, 저장 공간을 많이 사용한다

 

모델 테이블 자식 조회 트리 조회 삽입 삭제 참조 정합성
Adjuacency List 1 쉽다 어렵다 쉽다 쉽다 가능
Recursive Query 1 쉽다 쉽다 쉽다 쉽다 가능
Path Enumeration 1 쉽다 쉽다 쉽다 쉽다 불가능
Nested Sets 1 어렵다 쉽다 어렵다 어렵다 불가능
Closure Table 2 쉽다 쉽다 쉽다 쉽다 가능

 

 

* 아이디가 필요해

   - 목표 : PK 관례 확립

   - 문제 : 가상키인 id 를 만능키로 모든 테이블에 사용, 중복키 생성 (id + XXX_id), 중복 행 허용 등

   - 허용 : 자연키를 만들기 위해 컬럼이 과도하게 많은 경우

   - 해법 : 상황에 맞춰 적절한 PK 구성

 

* 키가 없는 엔트리

   - 목표 : 데이터베이스 아키텍처 단순화

   - 문제 : FK 제약조건을 생략하면, 의도치 않은 데이터가 생성될 수 있음

   - 허용 : FK 를 지원하지 않는 DB 를 사용하는 경우

   - 해법 : FK 제약조건 선언하여 정합성 보장 및 실수 방지

 

* 엔터티-속성-값

   - 목표 : 가변 속성 지원

   - 문제 : 범용 속성 테이블 사용 (컬럼들로 정의되어야 할 속성이, 특정 컬럼의 값들로 삽입되는 경우)

   - 허용 : X

   - 해법 : 서브타입 모델링

      1) 단일 테이블 상속 (Fruit, Apple, Banana 타입에 속하는 모든 컬럼을 하나의 테이블에 구성)

           - 서브 타입의 각각의 속성들을 컬럼으로 생성

           - 단점 : 특정 컬럼이 어떤 서브 타입에 속하는지 알 수 없음.

                        (서브 타입의 개수가 적고 특정 서브타입에만 속하는 속성이 적을 때 효율적)

      2) 구체 테이블 상속 (Apple, Banana 타입에 따른 테이블 생성)

           - 서브 타입별로 별도의 테이블 생성

           - 단점 : 어떤 속성이 공통 속성인지 알기 어려움. 하나의 공통 속성이 추가되면 2개의 테이블에 모두 추가 필요

                        (모든 서브 타입을 한번에 조회할 필요가 거의 없는 경우에 적합)

      3) 클래스 테이블 상속 (Fruit, Apple, Banana 타입에 따른 테이블 별도 생성)

           - 객체 지향 클래스인 것처럼 공통 속성을 가지는 테이블과 서브 타입별 테이블을 별도로 생성

      4) 반 구조적 데이터

           - 서브타입의 수가 많거나 새로운 속성이 빈번한 경우에 XML 혹은 JSON 형식으로 부호화해  TEXT 컬럼으로 저장

           - 장점 : 확장이 쉽다

           - 단점 : SQL 이 특정 속성에 접근하는 것을 지원하지 않는다

 

* 다형성 연관

   - 목표 : 여러 부모 참조

   - 문제 : 이중 목적의 FK 사용 (특정 컬럼이 여러 테이블의 FK 로 사용됨)

   - 허용 : X

   - 해법 : 관계 단순화

     1) 교차 테이블 생성

          - 자식 테이블의 FK 는 여러 부모 테이블을 참조할 수 없으므로, 자식 테이블과 각 부모 테이블간 교차 테이블 생성

     2) 공통 수퍼테이블 생성

          - 부모 테이블이 상속할 베이스 테이블 생성

 

* 다중 칼럼 속성

   - 목표 : 다중 값 속성 저장

   - 문제 : 여러 개의 칼럼 생성

   - 허용 : 여러 개 칼럼의 용도가 각기 다른 경우 (tag1, tag2, tag3 vs developer, tester, reporter)

   - 해법 : 종속 테이블 생성

 

* 메타 데이터 트리블

   - 목표 : 확장 적응성 지원

   - 문제 : 테이블 또는 칼럼 복제 (연도별로 테이블을 생성하는 등)

   - 허용 : 오래된 데이터를 분리하여 보관하는 경우

   - 해법 : 파티션과 정규화

     1) 수평 분할 (행으로 분리)

          - 물리적으로는 테이블이 분리되어 있지만, SQL 에서는 마치 하나의 테이블인 것처럼 사용

     2) 수직 분할 (열로 분리)

          - BLOB 이나 TEXT 컬럼은 가변적이고 크기가 매우 커질수 있기에 다른 칼럼과 분리해 저장

 

* 반올림 오류

   - 목표 : 정수 대신 소수 사용

   - 문제 : FLOAT 데이터 타입 사용 (이진수 사용으로 정확한 소수값을 표현 불가능)

   - 허용 : INTEGER 나 NUMERIC 타입보다 큰 실수 값을 표현하는 경우

   - 해법 : NUMERIC 데이터 타입 사용

 

* 31가지 맛

   - 목표 : 칼럼을 특정 값으로 제한하기

   - 문제 : 칼럼 정의에 값 지정

   - 허용 : 값의 집합이 절대 변하지 않는 경우 ENUM 사용해도 문제가 없다

   - 해법 : 특정값을 행으로 하는 별도의 색인 테이블을 만들고 FK 제약조건을 선언

 

* 유령파일

   - 목표 : 이미지 또는 벌크 미디어 저장

   - 문제 : 파일을 사용해야 한다고 가정한다

   - 허용 : 이미지 등의 파일을 별도로 접근이 필요할 때, 백업을 빠르게 할 때, 가벼운 데이터베이스가 필요할 때

   - 해법 : 필요한 경우에는 BLOB 데이터 타입을 사용하라

 

* 인덱스 샷건

   - 목표 : 성능 최적화

   - 문제 : 무계획하게 인덱스 사용하기

   - 허용 : X

   - 해법 : 인덱스를 MENTOR (Measure, Explain, Nominate, Test, Optimize, Rebuild) 하라

     1) Measure

          - 어떤 쿼리가 수행시간이 오래 소요되는지, 혹은 빈번하게 수행되는지 측정

     2) Explain

          - 쿼리 실행 계획을 확인한다

     3) Nominate

          - 커버링 인덱스 : 쿼리가 인덱스에 포함된 칼럼만 참조한다면, DB는 인덱스만 읽어서 결과를 생성할 수 있다

     4) Test

          - 인덱스를 새성한 후, 쿼리를 다시 프로파일링 한다

     5) Optimize

          - 인덱스는 빈번하게 사용되는 데이터 구조로, 캐시 메모리에 보관할 좋은 후보다.

          - 인덱스를 메모리에서 읽으면 디스크 I/O 를 통해 읽는 것보다 성능을 수십배 향상시킨다

     6) Rebuild

          - 인덱스도 데이터가 변경됨에 따라 재구성이 필요하다

 

* 모르는 것에 대한 두려움

   - 목표 : 누락된 값을 구분하기

   - 문제 : NULL 을 일반 값처럼 사용 (논리 연산자로 비교 불가)

   - 허용 : NULL 을 일반 값처럼 사용하지 않는 경우

   - 해법 : 유일한 값으로 NULL 을 사용 (IS NULL 혹은 IS NOT NULL 은 사용 가능)

 

* 애매한 그룹

   - 목표 : 그룹당 최댓값을 가진 행 얻기

   - 문제 : 그룹되지 않은 칼럼 참조

   - 허용 : 그룹되지 않은 컬럼이지만, Single Value Rule 을 만족하는 경우

   - 해법 : 칼럼을 모호하게 사용하지 않기

      1) 함수 종속인 칼럼만 쿼리하기

           - 그룹되지 않은 모호한 칼럼을 쿼리에서 제거

      2) 상호 연관된 서브쿼리 사용하기

      3) 유도 테이블 (인라인 뷰) 사용하기

      4) 조인 사용하기

      5) 다른 칼럼에 집계 함수 사용하기

      6) 각 그룹에 대해 모든 값을 연결하기

   

* 임의의 선택

   - 목표 : 샘플 행 가져오기

   - 문제 : 데이터를 임의로 정렬하기

   - 허용 : 데이터 집합이 적을 때는 임의의 컬럼으로 정렬하여 난수를 생성할 수 있다

   - 해법 : 테이블 전체 정렬 피하기

      1) 1 ~ Max 키값 중 임의의 키 값 고르기

      2) 다음으로 큰 키 값 고르기

           - 1 ~ Max 값 사이에 빈틈이 있는 경우에도 사용 가능

      3) 모든 키 값의 목록을 구한 다음, 임의로 하나 고르기

           - 단점 : 리스트 크기가 클 수 있다, 쿼리를 두 번 해야 한다.

      4) 오프셋을 이용해 임의로 고르기

      5) 벤더 종속적인 방법

 

* 가난한 자의 검색 에진

   - 목표 : 전체 텍스트 검색

   - 문제 : 패턴 매칭 사용 (LIKE, REGEXP 등)

   - 허용 : 거의 사용되지 않는 쿼리에서는 유지할 수 있다

   - 해법 : 작업에 맞는 올바른 도구 사용하기

     1) 벤더 확장기능

     2) 직접 만들기

          - 전치 인덱스 (검색할 모든 단어의 목록)를 만든다

 

 

 

+ Recent posts