복붙노트

[SQL] 역사적 데이터를 올바르게 EAV 데이터베이스 설계

SQL

역사적 데이터를 올바르게 EAV 데이터베이스 설계

나는 EAV 데이터베이스에 대한 책을 읽은되었으며, 짧은 오심의 대부분은 것 같다 정말 관련, 정말 나쁜 EAV 디자인이나 데이터에서 어려움이 발생보고합니다.

일반적으로 당신은 그들이 RDBMS에 기능적으로 분리 테이블 + 컬럼을 복제하려고 이하 세 개의 테이블을 사용하는 EAV에 대해 불평 사람들을 볼 때. 때때로 수단은 단일 TEXT 값 열의 문자열을 소수에서부터 기억있다. 당신이 조심하지 않으면 아주 나쁜 될 수있는 데이터의 무결성을 통해 안전 가드와 EAV도 망쳐 놨.

그러나, EAV은 기록 데이터를 추적 할 수있는 쉬운 방법을 제공한다 우리가 SQL 및 키 - 값 저장 시스템 사이 등 시스템 뒷면의 일부를 이동 할 수 있습니다.

우리가 자신의 유형에 따라 서로 다른 개체의 속성을 분리합니다. 이것은 여전히 ​​핸들에 우리를 허용 것 특정 속성과 실체에 묶여 제대로 인덱스 값에 추가 belongsTo를 가지고, hasMany의, 그리고 HasManyThrough는 관계.

다음과 같은 두 가지 기본 요소를 고려

products (price -> decimal, title -> string, desc -> text, etc...)
    attributes
        options
            [...]
        int
        datetime
        string
        text
        decimal
        relation
            [id,foreign_key]

users (gender -> options, age -> int, username -> string, etc...)
    attributes
        options
            [...]
        int
        datetime
        string
        text
        decimal
        relation
            [id,foreign_key]

우리 모두가 알다시피, 사용자 프로파일과 제품은 세계에서 가장 다양한 항목의 일부입니다. 각 회사 핸들 그들을 다르게 다른 '열'또는 요구에 "속성"을 가지고있다.

다음은 핸들 배수 (중첩 및 / 또는 관계) 방법 실체의 도면이다.

아이디어는 각 개체에 대해 다음 지정 어떻게 찾아 그 값을 해석하는 것을이 마스터 속성 테이블을 가지고 있다는 것입니다. 이것은 우리가 "옵션"또는 10 진수 번호와 같은 다른 기관과 사물에 대한 외래 키와 같은 특별한 경우를 처리 할 수 ​​있습니다.

ENTITY_TYPE {     신분증,     유형, // 즉, "블로그", "사용자", "제품", 등     created_at }

entity {
    id,
    entity_type_id, 
    created_at
}

    attr {
        id,
        entity_id,
        type,
        name,
        created_at
    }

        option {
            id,
            attr_id,
            entity_id,
            multiple, // multiple values allowed?
            name,
            created_at
        }

        attr_option {
            id
            attr_id,
            entity_id,
            option_id
            option,
            created_at
        }

        attr_int {
            attr_id,
            entity_id,
            int,
            created_at
        }

        attr_relation {
            attr_id,
            entity_id,
            entity_fk_id,
            created_at
        }

        attr_datetime {
            attr_id,
            entity_id,
            datetime,
            created_at
        }

        attr_string {
            attr_id,
            entity_id,
            var_char,
            created_at
        }

        attr_text {
            attr_id,
            entity_id,
            text,
            created_at
        }

        attr_decimal {
            attr_id,
            entity_id,
            decimal,
            created_at
        }

이 같은 테이블 ... 우리가 UPDATE에 결코 할 수 있도록 할 우리가 수 있기 때문에 단지 INSERT INTO ... 값을 변경하고 가장 최근의 값이 무엇인지 알 수 있도록 created_at를 추가 각각의 새로운 속성. 이것은 (예외가 여전히 물론 만들 수있는) 기록 데이터의 기록을 유지에 적합합니다.

첫째, 기업의 어떤 "유형"인가? (사용자, 게시, 의견 등 ..)

SELECT * FROM entity_type et LEFT JOIN entity e ON e.entity_type_id = et.id WHERE e.id = ?

다음으로,이 엔티티의 속성은 무엇인가? (표 ATTR)

SELECT * FROM attr WHERE entity_id = ?

다음으로, 어떤 값이 개체의 속성에 존재 하는가? (ATTR _ ### 표)

SELECT * FROM attr_option, attr_int, attr_relation, attr_text, ... WHERE entity_id = ?
vs
SELECT * FROM attr_option WHERE entity_id = ? if( ! multiple) ORDER BY created_at DESC LIMIT 1
SELECT * FROM attr_int WHERE entity_id = ? ORDER BY created_at DESC LIMIT 1
SELECT * FROM attr_relation WHERE entity_id = ? ORDER BY created_at DESC LIMIT 1
SELECT * FROM attr_text WHERE entity_id = ? ORDER BY created_at DESC LIMIT 1
...

어떤 관계는이 엔티티를 위해 존재 하는가?

우리는 (34)의 ID와 "포스트"엔터티를 가지고 우리가 (ENTITY_TYPE = 2),이 우리가 제품 엔티티에 주석 개체 ID를 가져 오기 위해 허용 할 수의 "의견"을 원하는 가정 :

SELECT * FROM entity AS e
LEFT JOIN attr_relation AS ar ON ar.entity_id = e.id
WHERE ar.entity_id = 34 AND e.entity_type = 2;

그렇다 (어쨌든 키 - 값 저장에 필요) 여러 쿼리에서 어떤 문제가이 방식으로 존재하는 것인가?

해결법

  1. ==============================

    1.EAV '데이터베이스'[원문]를 tablulate 관계, 또는 쿼리 관계, 또는 쿼리 메타 데이터, 또는 유형 검사없이 기능을, 데이터베이스 및 메타 데이터의 트리플에 그대로 수학적으로 똑 바르게 문서화되지 않은 설명, 또는 무결성 또는 최적화를 유지, 또는 원자 거래, 또는 제어 동시성.

    EAV '데이터베이스'[원문]를 tablulate 관계, 또는 쿼리 관계, 또는 쿼리 메타 데이터, 또는 유형 검사없이 기능을, 데이터베이스 및 메타 데이터의 트리플에 그대로 수학적으로 똑 바르게 문서화되지 않은 설명, 또는 무결성 또는 최적화를 유지, 또는 원자 거래, 또는 제어 동시성.

    소프트웨어 엔지니어링 원리는 사운드 EAV 데이터베이스 [원문] 사용 완전히 DBMS의 기능을 복원 적절한 추상화 (종류, 운영 프로세스, 통역 모듈)을 정의하는 구성 지시.

    A (파편) 데이터베이스 설명을 하나의 EAV 트리플과 그 의미에서 매핑의 기계적 특성은 보여이 쉽습니다.

    Greenspun 의역하려면 어떤 충분히 복잡한 EAV 프로젝트는 DBMS의 절반의 임시, 비공식적으로 지정, 버그 쟁이, 슬로우 구현이 포함되어 있습니다.

    나는 반복 : EAV없이 DBMS와 데이터베이스 및 메타 데이터의 트리플에서 문서화되지 않은 설명이다. 단지 당신이 DDL 솔루션은 성능 요구 사항을 충족 할 수 있음을 보여 주었다 데이터베이스의 부품과 EAV 솔루션이 할 수있는 가치가 그것입니다 사용 EAV.

  2. ==============================

    2.다음은이 디자인에 몇 가지 문제가 있습니다.

    다음은이 디자인에 몇 가지 문제가 있습니다.

    이들의 대부분을 해결하는 유일한 방법은 응용 프로그램 코드를 사용하는 것입니다. 즉 EAV의 문제 : 당신은 SQL 부여에 대해 우리가 가지고 많은 제약을 개혁 끝낸다. 그것은 내부 플랫폼 효과 안티 패턴의 예 :

    여섯 번째 정상 형태는 EAV하지 않습니다. 여섯 번째 정규 양식에, 당신은 수 속성이 아닌 데이터 유형에 따라 별도의 테이블이 필요합니다. 당신은 적절한 이름과 데이터 유형으로 기존의 열을 사용합니다. 별개의 테이블에이 속성을 저장하는 것은 당신에게 역사의 개정을 저장 할 수있는 기능을 제공하는 것이다.

    이 수단은 여전히 ​​6NF에 NULL을 NOT 모델 수는 없지만, 적어도 당신은 꽤 기존의 방법으로 UNIQUE 및 FOREIGN KEY를 모델링 할 수 있습니다.

  3. ==============================

    3."나는 EAV 데이터베이스에 대한 책을 읽은되었으며, 짧은 오심의 대부분은 정말 관련이있는 것으로 보인다, 정말 나쁜 EAV 디자인이나 데이터에서 어려움이 발생보고합니다."

    "나는 EAV 데이터베이스에 대한 책을 읽은되었으며, 짧은 오심의 대부분은 정말 관련이있는 것으로 보인다, 정말 나쁜 EAV 디자인이나 데이터에서 어려움이 발생보고합니다."

    보고서를 생성하는 어려움이 EAV DB가 나타내는 사실의 종류에서 본질적으로 필연적으로 파생 : "속성 생년월일의 값을 사람 XYZ이기 때문이다 ..." "사람 XYZ에 대한 속성 DECEASEDATE의 값 것은 ..."등 등 .

    즉하지만, 정확히 100 최종 사용자가 사람 XYZ (또는 다른), 최종 사용자 및 피봇과 매우 가깝다 DB, 추가 변환 (사이 에고 어딘가에에 대한 정보를 전달하기위한 데이터 구조를 생각하는 전형적인 양식을하지 않습니다 %) 필수적이다. 각 추가 변환은 버그 및 성능 손실의 잠재적 인 소스입니다.

    "보통은 EAV에 대해 불평하는 사람들은 RDBMS에 기능적으로 분리 테이블 + 컬럼을 복제하려고 이하 세 개의 테이블을 사용하고 볼 때. 때로는 그 하나의 TEXT 값 열에서 문자열로 소수에 이르기까지 모든 것을 기억 수단."

    즉 만 EAV의 단점 중 하나입니다. 특성 수준의 형 제약 어렵게하거나 불가능하게 정의하려면된다. 그러나이 외에 다른 사람이있다.

    "당신이 조심하지 않으면 아주 나쁜 될 수있는 데이터의 무결성을 통해 안전 가드와 EAV도 망쳐 놨."

    이것은 전적으로 어떤 주어진 규칙의 위반을 구성하는 시나리오를 표현의 어려움과 똑같은 의미있는 쿼리를, 표현의 어려움과 똑같은 일 보고서 생성의 어려움, 상관 관계가있다.

    "그러나, EAV은 기록 데이터를 추적 할 수있는 쉬운 방법을 제공한다과 시스템 뒷면 갔다 SQL 및 키 - 값 저장 시스템 간의 부품을 이동할 수있게 해준다."

    BS & 헛소리. EAV는 멀리는 다른 "일반"속성으로 적용되는 것들에서 시간 정보를 이동합니다 엄격하게 적용했다. 이렇게하지 않으면, 당신은 더 이상 (엄격) EAV를 적용하지 않는. 참조 빌 Karwin의 대답! EAV = 6NF !!!!!!!!! 6NF는 여전히 DB도이 다른 "일반적인"는 EAV에 대한 모든 효과적으로 DB에서 해당 구조를 제거 (필립의 대답 빌의 '내부 플랫폼'발언 참조)하는 모든 "구조"를 가지고있다.

  4. from https://stackoverflow.com/questions/21714715/designing-an-eav-database-correctly-for-historical-data by cc-by-sa and MIT license