나는 테이블 디자인에 많은 경험이 없습니다. 내 목표는 아래 요구 사항을 충족하는 하나 이상의 제품 테이블을 만드는 것입니다.
-
많은 종류의 제품 (TV, 전화, PC 등)을 지원합니다. 각 제품 종류는 다음과 같은 다른 매개 변수 세트를 갖습니다.
-
전화는 색상, 크기, 무게, OS가 있습니다 …
-
PC에는 CPU, HDD, RAM이 있습니다 …
-
-
매개 변수 세트는 동적이어야합니다. 원하는 매개 변수를 추가하거나 편집 할 수 있습니다.
각 제품 종류에 대한 별도의 표없이 이러한 요구 사항을 어떻게 충족시킬 수 있습니까?
답변
설명하는 유형 계층 구조를 모델링하기위한 최소한 다음 5 가지 옵션이 있습니다.
-
단일 테이블 상속 : 모든 제품 유형에 대해 하나의 테이블이며 모든 유형의 모든 속성을 저장하기에 충분한 열이 있습니다. 이것은 많은 열을 의미 하며 대부분의 주어진 행에서 NULL입니다.
-
클래스 테이블 상속 : 모든 제품 유형에 공통적 인 속성을 저장하는 제품에 대한 하나의 테이블. 그런 다음 제품 유형마다 하나의 테이블이 있으며 해당 제품 유형에 특정한 속성이 저장됩니다.
-
콘크리트 테이블 상속 : 일반적인 제품 속성에 대한 테이블이 없습니다. 대신 제품 유형 당 하나의 테이블로 공통 제품 속성과 제품 별 속성이 모두 저장됩니다.
-
직렬화 된 LOB : 모든 제품 유형에 공통적 인 속성을 저장하는 제품에 대한 하나의 테이블. 하나의 추가 열은 반 구조적 데이터의 BLOB를 XML, YAML, JSON 또는 기타 형식으로 저장합니다. 이 BLOB를 사용하면 각 제품 유형에 특정한 속성을 저장할 수 있습니다. Facade 및 Memento와 같은 멋진 디자인 패턴을 사용하여이를 설명 할 수 있습니다. 그러나 SQL 내에서 쉽게 쿼리 할 수없는 다양한 속성이 있습니다. 전체 blob을 다시 응용 프로그램으로 가져 와서 정렬해야합니다.
-
Entity-Attribute-Value : Products에 대한 하나의 테이블과 속성을 열 대신 행으로 피벗하는 테이블. EAV는 관계형 패러다임과 관련하여 유효한 디자인은 아니지만 많은 사람들이이를 사용합니다. 이것은 다른 답변에서 언급 한 “속성 패턴”입니다. 일부 함정에 대해서는 StackOverflow 에서 eav 태그로 다른 질문을 참조하십시오 .
Extensible Data Modeling 프레젠테이션에서 이에 대해 더 많이 썼습니다 .
EAV에 대한 추가 생각 : 많은 사람들이 EAV를 선호하는 것처럼 보이지만, 저는 그렇지 않습니다. 가장 유연한 솔루션처럼 보이므로 최고입니다. 그러나 adage TANSTAAFL 을 명심하십시오 . EAV의 단점은 다음과 같습니다.
- 열을 필수로 만들 수있는 방법은 없습니다 (에 해당
NOT NULL
). - SQL 데이터 유형을 사용하여 항목의 유효성을 검사 할 방법이 없습니다.
- 속성 이름의 철자를 일관되게 보장 할 방법이 없습니다.
- 주어진 속성의 값에 외래 키를 넣을 방법이 없습니다 (예 : 조회 테이블).
- 기존 테이블 형식 레이아웃에서 결과를 가져 오는 것은 복잡하고 비용이 많이 듭니다. 여러 행에서 속성을 가져 오려면
JOIN
각 속성에 대해 수행해야하기 때문 입니다.
EAV의 유연성 정도는 다른 영역에서 희생을 요구하며, 아마도 기존의 방식으로 원래 문제를 해결하는 것보다 코드를 복잡하거나 악화시킬 수 있습니다.
대부분의 경우 유연성을 가질 필요는 없습니다. 제품 유형에 대한 OP의 질문에서 제품 별 속성에 대해 제품 유형별로 테이블을 작성하는 것이 훨씬 간단하므로 최소한 동일한 제품 유형의 항목에 대해 일관된 구조가 적용됩니다.
모든 행 에 고유 한 속성 집합을 가질 수 있어야하는 경우에만 EAV를 사용 합니다. 유한 제품 유형 세트를 사용하는 경우 EAV가 과잉 상태입니다. 클래스 테이블 상속이 나의 첫 번째 선택이 될 것입니다.
2019 년 업데이트 : “많은 사용자 정의 속성”문제에 대한 솔루션으로 JSON을 사용하는 사람들이 많을수록 그 솔루션을 좋아하지 않습니다. 특수 JSON 함수 를 사용하여 지원하는 경우에도 쿼리를 너무 복잡하게 만듭니다 . 일반 행과 열에 저장하는 것보다 JSON 문서를 저장하는 데 더 많은 저장 공간이 필요합니다.
기본적으로 이러한 솔루션 중 어느 것도 관계형 데이터베이스에서 쉽고 효율적이지 않습니다. “가변 속성”을 갖는 전체 아이디어는 기본적으로 관계 이론과 상충됩니다.
그것은 무엇에 내려 오는 것은 당신이 가장 나쁜 기반으로하는 솔루션 중 하나를 선택해야한다는 것입니다 귀하의 응용 프로그램을. 따라서 데이터베이스 디자인을 선택하기 전에 데이터를 쿼리하는 방법을 알아야합니다. 솔루션 중 하나가 특정 응용 프로그램에 가장 적합 할 수 있으므로 “최고의”솔루션을 선택할 수있는 방법이 없습니다.
답변
@돌 심장
나는 EAV와 MVC와 함께 여기에 갈 것입니다.
@Bill Karvin
EAV의 단점은 다음과 같습니다.
- 열을 필수로 만들 수있는 방법은 없습니다 (NOT NULL과 동일).
- SQL 데이터 유형을 사용하여 항목의 유효성을 검사 할 방법이 없습니다.
- 속성 이름의 철자를 일관되게 보장 할 방법이 없습니다.
- 주어진 속성의 값에 외래 키를 넣을 방법이 없습니다 (예 : 조회 테이블).
여기에 언급 한 모든 것 :
- 데이터 유효성 검사
- 속성 이름 철자 유효성 검사
- 필수 열 / 필드
- 종속 속성 파괴 처리
내 의견으로는 응용 프로그램의 프로그래밍 언어와 같이 적절한 수준에서 이러한 상호 작용 및 요구 사항을 처리 할 수있는 데이터베이스가 없기 때문에 데이터베이스에 전혀 속하지 않습니다.
내 생각에 이런 식으로 데이터베이스를 사용하는 것은 손톱을 망치로 바위를 사용하는 것과 같습니다. 바위로 할 수는 있지만 이런 종류의 활동을 위해 더 정확하고 구체적으로 설계된 망치를 사용하지 않습니까?
여러 행에서 속성을 가져 오려면 각 속성에 대해 JOIN을 수행해야하므로 기존 테이블 형식 레이아웃에서 결과를 가져 오는 것은 복잡하고 비용이 많이 듭니다.
이 문제는 부분 데이터에 대한 쿼리를 거의하지 않고 응용 프로그램에서 테이블 형식 레이아웃으로 처리하여 해결할 수 있습니다. 600GB의 제품 데이터가 있더라도이 표의 모든 단일 행의 데이터가 필요한 경우 일괄 처리 할 수 있습니다.
계속 진행 쿼리 성능을 향상 시키려면보고 또는 글로벌 텍스트 검색과 같은 특정 작업을 선택하고 필요한 데이터를 저장하고 주기적으로 재생성되는 인덱스 테이블을 준비하여 30 분마다 알려주십시오.
추가 데이터 스토리지 비용은 매일 저렴하고 저렴 해 지므로 걱정할 필요가 없습니다.
애플리케이션에서 수행하는 작업의 성능에 여전히 관심이있는 경우, 항상 Erlang, C ++, Go Language를 사용하여 데이터를 사전 처리하고 나중에 기본 앱에서 최적화 된 데이터를 추가로 처리 할 수 있습니다.
답변
Class Table Inheritance
의미를 사용하면 :
모든 제품 유형에 공통적 인 속성을 저장하는 제품에 대한 하나의 테이블. 그런 다음 제품 유형마다 하나의 테이블이 있으며 해당 제품 유형에 특정한 속성이 저장됩니다. 빌 카윈
Bill Karwin의 제안 중 가장 좋은 점은 무엇입니까 .. 문제점을 방지하는 방법을 설명하려고하는 한 가지 단점을 예견 할 수 있습니다.
1 유형에만 공통 인 속성이 2, 3 등에 공통적 인 속성이있을 때 어떤 비상 계획을 세워야합니까?
예를 들면 다음과 같습니다 (실제 문제가 아니라 예일 뿐임)
가구를 판매하는 경우 의자, 램프, 소파, TV 등을 판매 할 수 있습니다. TV 유형은 전력 소비량이있는 유일한 유형일 수 있습니다. 그래서에 power_consumption
속성을 넣을 것 tv_type_table
입니다. 그러나 우리는 power_consumption
재산 이있는 홈 시어터 시스템을 가지고 다니기 시작 합니다. 다른 하나의 제품만으로도이 필드를 추가 할 것 stereo_type_table
입니다. 아마도이 시점에서 가장 쉬운 방법 일 것입니다. 그러나 시간이 지남에 따라 점점 더 많은 전자 장치를 휴대하기 시작하면서 전자 장치가 전자 장치에 power_consumption
포함될만큼 충분히 넓습니다 main_product_table
. 지금 어떻게해야합니까?
에 필드를 추가하십시오 main_product_table
. 전자 장치를 반복하고 올바른 값을 각각 type_table
에 입력하는 스크립트를 작성 하십시오 main_product_table
. 그런 다음 각 열에서 해당 열을 삭제하십시오 type_table
.
이제 항상 같은 GetProductData
클래스를 사용하여 데이터베이스와 상호 작용하여 제품 정보를 가져옵니다. 코드 변경에 리팩토링이 필요한 경우 해당 클래스에만 적용됩니다.
답변
제품 테이블과 제품 ID, 추가 정보 이름, 추가 정보 값의 3 개 열이있는 별도의 ProductAdditionInfo 테이블이있을 수 있습니다. 모든 종류의 제품이 아닌 많은 제품에서 색상을 사용하는 경우 제품 테이블에서 Null을 허용하거나 열을 ProductAdditionalInfo에 넣을 수 있습니다.
이 방법은 관계형 데이터베이스에 대한 전통적인 기술은 아니지만 실제로 많이 사용하는 것을 보았습니다. 유연하고 성능이 우수 할 수 있습니다.
Steve Yegge는 이것을 Properties 패턴 이라고 부르고이를 사용하는 것에 대한 긴 글을 썼습니다.