버그 추적기, 고객 리소스 관리 및 이와 유사한 비즈니스 도구에서 흔히 볼 수있는 "사용자 정의 필드"에 도달하기 시작하면 bajillion 필드가있는 테이블로 백업되지 않는다는 것입니다. 자체).
대신 엔티티 속성 값 테이블 디자인과 유효한 속성을 관리하기위한 관련 관리 도구가 있습니다.
다음 표를 고려하십시오.
+ -------------- +
| 일 |
| -------------- |
| 아이디 |
| 타입 |
| 디스크 |
| attr1 |
| attr2 |
| attr3 |
| attr4 |
| attr5 |
+ -------------- +
이것은 몇 가지 속성을 추가 한 후입니다. 대신 attr1
그것을 읽는 척 artist
또는 tracks
또는 genre
또는 것은이 속성 뭐든간에. 그리고 5 대신에 50 대라면 어떨까요. 분명히 관리 할 수 없습니다. 또한 새 필드를 처리하려면 모델을 업데이트하고 응용 프로그램을 재배치해야합니다. 이상적이지 않습니다.
이제 다음 테이블 구조를 고려하십시오.
+ -------------- + + --------------- ++ ------------- +
| 일 | | thing_attr | | attr |
| -------------- | | --------------- | | ------------- |
| id | <--- + | thing_id (fk) | +> | 아이디 |
| 타입 | | attr_id (fk) | +-+ | 이름 |
| 디스크 | | 가치 | | |
+ -------------- + + --------------- ++ ------------- +
기본 필드를 가지고 있습니다. 두 개의 테이블이 더 있습니다. 속성이있는 것 각 필드는 attr
테이블 의 행입니다 . 그리고 테이블과 테이블과 thing_attr
관련된 외래 키 쌍이 있습니다. 그리고 여기에는 해당 엔터티에 대한 필드 값이 무엇이든 저장할 수있는 값 필드가 있습니다.thing
attr
이제 attr 테이블을 런타임에 업데이트하고 전체 응용 프로그램에 큰 영향을 미치지 않으면 서 새 필드를 추가하거나 제거 할 수있는 구조가 생겼습니다.
쿼리는 조금 더 복잡하고 유효성 검사도 더욱 복잡해집니다 (펑키 저장 프로 시저 또는 모든 클라이언트 쪽). 디자인의 절충.
언젠가 마이그레이션을 수행해야하는 상황을 고려하여 애플리케이션으로 돌아와서 원래 분배 한 스키마보다 수십 개 이상의 속성이 있음을 발견하십시오. 따라서 엔터티 속성 값 테이블을 올바르게 사용하면 더 깔끔한 마이그레이션 및 업그레이드가 가능합니다. (항상 그런 것은 아니지만 가능합니다.)
런타임에 스키마를 수정하는 데 단점이 있습니까? 사물에 새로운 속성이 필요하다고 생각되면 테이블에 열을 동적으로 추가하면됩니까?
적절한 nosql 데이터베이스 버전으로 작업하는 경우이 작업을 수행 할 수 있습니다 (nosql의 적절한 버전은 아마도 위에서 설명한 관계형 데이터베이스 에 대한 EAV 테이블 인 키-값 저장소 일 것입니다). 너무 많은 어려움없이. 그러나 nosql에 대한 모든 타협은 다른 곳에서 자세히 설명되어 있습니다.
대신 관계형 데이터베이스에서 작업하는 경우 스키마가 있어야합니다. 열을 동적으로 추가하면 다음 사항 중 일부가 적용됩니다.
- 메타 데이터베이스 프로그래밍을하고 있습니다. 이 ORM을 사용 하여이 열을 해당 필드에 깨끗하게 매핑하는 대신
select *
데이터를 실제로 확인하기 위해 ( Java의 ResultSetMetaData 참조) 같은 작업을 수행 한 다음 복잡한 코드를 수행 하여 맵에 저장합니다 ( 또는 다른 데이터 유형- 코드의 멋진 필드는 아닙니다 ). 그러면 전통적인 접근 방식과 함께 약간의 유형과 오타가 발생하지 않습니다.
- 귀하는 ORM을 포기했을 것입니다. 이것은 시스템이 당신을 위해 일하는 대신 모든 코드에 대해 원시 SQL을 작성하고 있음을 의미합니다.
- 당신은 깨끗한 업그레이드를 포기했습니다. 고객이 다음 버전에서도 사용하는 하나의 이름을 가진 필드를 추가하면 어떻게됩니까? 매치 메이킹 사이트에서
hasdate
타임 스탬프를 저장하기 위한 필드 를 추가하려는 업그레이드 는 이미 hasdate
성공적인 일치를위한 부울 로 정의되었으며 업그레이드가 중단되었습니다.
- 귀하는 고객이 귀하의 쿼리도 어딘가에 예약어를 사용하여 시스템을 중단하지 않는다고 믿습니다.
- 하나의 데이터베이스 브랜드에 자신을 묶었습니다. 다른 데이터베이스 의 DDL 이 다릅니다. 데이터베이스 유형이 가장 쉬운 예입니다.
varchar2
대 text
등. 열을 추가하는 코드는 MySQL에서는 작동하지만 Postgres, Oracle 또는 SQL Server에서는 작동하지 않습니다.
- 고객이 실제로 데이터를 잘 추가한다고 믿 습니까? 물론, EAV는 이상적이지는 않지만 이제는 개발자가 추가하지 않은 끔찍한 불명확 한 테이블 이름을 얻었습니다 (잘못된 유형의 색인이있는 경우). 등등.
- 응용 프로그램을 실행하는 사용자에게 스키마 수정 권한을 부여했습니다. Little Bobby Drop Tables 는 DDL이 아닌 SQL로 제한되어있을 때 가능하지 않습니다 (
delete * from students
대신 할 수는 있지만 실제로 데이터베이스를 엉망으로 만들 수는 없습니다). 사고 나 악의적 인 활동으로 인한 스키마 액세스로 잘못 될 수있는 것의 수.
이것은 실제로 "하지 마십시오"로 귀결됩니다. 실제로 원하는 경우 EAV 테이블 구조의 알려진 패턴 또는이 구조 전용의 데이터베이스를 사용하십시오. 사람들이 테이블에 임의의 필드를 만들게하지 마십시오. 두통은 그만한 가치가 없습니다.