각 제품에 많은 매개변수가 있는 다양한 종류의 제품에 대한 제품 테이블을 디자인하는 방법
-
22-08-2019 - |
문제
저는 테이블 디자인에 대한 경험이 많지 않습니다.내 목표는 아래 요구 사항을 충족하는 하나 이상의 제품 테이블을 만드는 것입니다.
다양한 종류의 제품(TV, 휴대폰, PC 등)을 지원합니다.각 제품 종류에는 다음과 같은 다양한 매개변수 세트가 있습니다.
휴대폰에는 색상, 크기, 무게, OS 등이 있습니다.
PC에는 CPU, HDD, RAM이 있습니다.
매개변수 세트는 동적이어야 합니다.원하는 매개변수를 추가하거나 편집할 수 있습니다.
제품 종류별로 별도의 표를 작성하지 않고 어떻게 이러한 요구 사항을 충족할 수 있습니까?
해결책
설명하는 유형 계층을 모델링하기위한이 5 가지 옵션이 있습니다.
단일 테이블 상속: 모든 제품 유형에 대한 하나의 테이블, 모든 유형의 모든 속성을 저장하기에 충분한 열이 있습니다. 이것은 의미합니다 많이 열 중 대부분은 주어진 행에 널입니다.
클래스 테이블 상속: 제품의 하나의 테이블, 모든 제품 유형에 공통적 인 속성을 저장합니다. 그런 다음 제품 유형 당 하나의 테이블로 해당 제품 유형에 맞는 속성을 저장합니다.
콘크리트 테이블 상속: 일반적인 제품 속성에 대한 테이블이 없습니다. 대신, 제품 유형 당 하나의 테이블, 일반적인 제품 속성과 제품 별 속성을 모두 저장합니다.
직렬화 된 LOB: 제품의 하나의 테이블, 모든 제품 유형에 공통적 인 속성을 저장합니다. 하나의 추가 열은 XML, Yaml, JSON 또는 다른 형식에 반 구조화 된 데이터 덩어리를 저장합니다. 이 Blob을 사용하면 각 제품 유형에 맞는 속성을 저장할 수 있습니다. 멋진 디자인 패턴을 사용하여 Facade 및 Memento와 같은이를 설명 할 수 있습니다. 그러나 당신은 SQL 내에서 쉽게 쿼리 할 수없는 속성의 덩어리가 있습니다. 전체 덩어리를 응용 프로그램으로 다시 가져 와서 정렬해야합니다.
엔티티 부사장 값: 제품의 하나의 테이블과 열 대신 행에 속성을 피우는 테이블 하나. EAV는 관계형 패러다임과 관련하여 유효한 디자인은 아니지만 많은 사람들이 그것을 사용합니다. 이것은 다른 답변으로 언급 된 "속성 패턴"입니다. 다른 질문을보십시오 EAV 태그 일부 함정에 대한 stackoverflow에.
나는 프레젠테이션에서 이것에 대해 더 많이 썼습니다. 확장 가능한 데이터 모델링.
EAV에 대한 추가적인 생각 : 많은 사람들이 EAV를 선호하는 것처럼 보이지만 그렇지 않습니다. 가장 유연한 솔루션처럼 보이므로 최고입니다. 그러나 격언을 명심하십시오 탄 스타 아프. EAV의 단점 중 일부는 다음과 같습니다.
- 칼럼을 의무적으로 만들 수있는 방법이 없습니다 (
NOT NULL
). - SQL 데이터 유형을 사용하여 항목을 검증하는 방법이 없습니다.
- 속성 이름이 일관되게 철자를 보장 할 방법이 없습니다.
- 주어진 속성의 값, 예를 들어 조회 테이블에 대한 외국 키를 넣을 방법이 없습니다.
- 기존의 표 레이아웃을 가져 오는 결과는 복잡하고 비싸다.
JOIN
각 속성에 대해.
EAV가 제공하는 유연성의 정도는 다른 영역에서 희생을 요구하며, 아마도 코드를보다 전통적인 방식으로 원래 문제를 해결하는 것보다 코드를 복잡하거나 악화시키는 것일 수 있습니다.
그리고 대부분의 경우, 그 정도의 유연성을 갖는 것은 불필요합니다. 제품 유형에 대한 OP의 질문에서 제품 별 속성에 대한 제품 유형 당 테이블을 만드는 것이 훨씬 간단하므로 적어도 동일한 제품 유형의 항목에 대해 일관된 구조가 적용됩니다.
나는 EAV를 사용하는 경우에만 사용합니다 모든 행 잠재적으로 고유 한 속성 세트가 있도록 허용되어야합니다. 유한 한 제품 유형이 있으면 EAV는 과잉입니다. 클래스 테이블 상속은 나의 첫 번째 선택이 될 것입니다.
업데이트 2019 : "많은 사용자 정의 속성"문제에 대한 솔루션으로 JSON을 사용하는 사람들을 더 많이 볼수록 해당 솔루션이 적습니다. 스페셜을 사용하더라도 쿼리를 너무 복잡하게 만듭니다. JSON 기능 그들을 지원하기 위해. JSON 문서를 저장하는 데 더 많은 저장 공간이 필요하고 일반 행과 열로 저장하는 것입니다.
기본적으로 이러한 솔루션 중 어느 것도 관계형 데이터베이스에서 쉽거나 효율적이지 않습니다. "가변 속성"을 갖는 전체 아이디어는 근본적으로 관계형 이론과 상충됩니다.
그것이 내려 오는 것은 당신이 가장 나쁜 솔루션 중 하나를 선택해야한다는 것입니다. 당신의 앱. 따라서 데이터베이스 디자인을 선택하기 전에 어떻게 데이터를 쿼리 할 것인지 알아야합니다. 솔루션 중 하나가 주어진 응용 프로그램에 가장 적합 할 수 있기 때문에 "가장 좋은"솔루션을 선택할 수있는 방법은 없습니다.
다른 팁
@돌 심장
나는 EAV와 MVC를 가지고 여기에 갈 것입니다.
@빌 카빈
다음은 EAV의 단점 중 일부입니다.
No way to make a column mandatory (equivalent of NOT NULL). No way to use SQL data types to validate entries. No way to ensure that attribute names are spelled consistently. No way to put a foreign key on the values of any given attribute, e.g.
조회 테이블의 경우.
여기서 언급한 모든 내용은 다음과 같습니다.
- 데이터 유효성 검사
- 속성 이름 철자 확인
- 필수 열/필드
- 종속 속성의 소멸 처리
제 생각에는 어떤 데이터베이스도 애플리케이션의 프로그래밍 언어처럼 적절한 수준에서 이러한 상호 작용과 요구 사항을 처리할 수 없기 때문에 데이터베이스에 전혀 속하지 않습니다.
제 생각에는 이런 방식으로 데이터베이스를 사용하는 것은 돌을 사용하여 못을 박는 것과 같습니다.바위를 가지고 할 수도 있지만 이런 종류의 활동을 위해 더 정확하고 특별히 설계된 망치를 사용하는 것이 좋지 않을까요?
기존의 테이블 레이아웃을 가져 오는 결과는 복잡하고 비싸다. 여러 행에서 속성을 얻으려면 각 속성에 결합해야합니다.
이 문제는 부분 데이터에 대해 몇 가지 쿼리를 수행하고 애플리케이션을 사용하여 테이블 형식 레이아웃으로 처리하면 해결될 수 있습니다.600GB의 제품 데이터가 있더라도 이 테이블의 모든 단일 행에 대한 데이터가 필요한 경우 일괄 처리할 수 있습니다.
더 나아가 쿼리 성능을 향상시키려면 다음과 같은 특정 작업을 선택할 수 있습니다.보고 또는 전역 텍스트 검색을 수행하고 필요한 데이터를 저장하고 주기적으로(예: 30분마다) 재생성되는 인덱스 테이블을 준비합니다.
추가 데이터 저장 비용은 매일 점점 더 저렴해지기 때문에 걱정할 필요조차 없습니다.
여전히 애플리케이션에서 수행되는 작업 성능에 관심이 있는 경우 언제든지 Erlang, C++, Go 언어를 사용하여 데이터를 사전 처리하고 나중에 기본 앱에서 최적화된 데이터를 추가로 처리할 수 있습니다.
내가 사용하는 경우 Class Table Inheritance
의미:
제품의 하나의 테이블, 모든 제품 유형에 공통적 인 속성을 저장합니다. 그런 다음 제품 유형 당 하나의 테이블로 해당 제품 유형에 맞는 속성을 저장합니다. -Bill Karwin
Bill Karwin의 제안 중 최고를 좋아합니다. 나는 한 가지 단점을 예측할 수 있습니다. 이것은 문제가되는 것을 막는 방법을 설명하려고 노력할 것입니다.
1 유형에 공통적 인 속성이 2, 3 등에 공통적이 될 때 어떤 비상 계획을 세워야합니까?
예를 들어 : (이것은 내 실제 문제가 아닌 예일뿐입니다)
가구를 판매하는 경우 의자, 램프, 소파, TV 등을 판매 할 수 있습니다. TV 유형은 전력 소비가있는 유일한 유형 일 수 있습니다. 그래서 나는 그것을 넣을 것이다 power_consumption
속성 tv_type_table
. 그러나 우리는 또한 홈 시어터 시스템을 가지고 다니기 시작합니다. power_consumption
재산. OK 그 단지 하나의 다른 제품 이므로이 필드를 stereo_type_table
이 시점에서 아마도 가장 쉬운 것입니다. 그러나 시간이 지남에 따라 점점 더 많은 전자 제품을 운반하기 시작하면서 우리는 power_consumption
그것이 있어야 할 정도로 넓습니다 main_product_table
. 지금 무엇을해야합니까?
필드를 main_product_table
. 전자 장치를 통해 루프하기 위해 스크립트를 작성하고 각각의 올바른 값을 넣습니다. type_table
~로 main_product_table
. 그런 다음 각 열에서 그 열을 떨어 뜨립니다 type_table
.
내가 항상 같은 것을 사용하고 있다면 GetProductData
제품 정보를 가져 오기 위해 데이터베이스와 상호 작용하는 클래스; 그러면 코드의 변경 사항이 이제 리팩토링이 필요하면 해당 클래스에만 있어야합니다.
제품 ID, 추가 정보 이름, 추가 정보 값과 같은 3 개의 열이있는 제품 테이블과 별도의 ProductAdDitionInfo 테이블을 가질 수 있습니다. 많은 종류의 제품이 아닌 많은 종류의 제품이 색상을 사용하는 경우 제품 테이블의 무효 열이거나 ProductAdditionalInfo에 넣을 수 있습니다.
이 접근법은 관계형 데이터베이스의 전통적인 기술은 아니지만 실제로는 실제로 많이 사용되는 것을 보았습니다. 유연하고 성능이 우수 할 수 있습니다.
Steve Yegge는 이것을 부릅니다 속성 패턴 그리고 그것을 사용하는 것에 대한 긴 게시물을 썼습니다.