각 제품에 많은 매개 변수가있는 여러 종류의 제품에 대한 제품 테이블을 디자인하는 방법
나는 테이블 디자인에 많은 경험이 없습니다. 내 목표는 아래 요구 사항을 충족하는 하나 이상의 제품 테이블을 만드는 것입니다.
많은 종류의 제품 (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의 단점은 다음과 같습니다.
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.
조회 테이블
여기에 언급 한 모든 것 :
- 데이터 유효성 검사
- 속성 이름 철자 유효성 검사
- 필수 열 / 필드
- 종속 속성 파괴 처리
in my opinion don't belong in a database at all because none of databases are capable of handling those interactions and requirements on a proper level as a programming language of an application does.
In my opinion using a database in this way is like using a rock to hammer a nail. You can do it with a rock but aren't you suppose to use a hammer which is more precise and specifically designed for this sort of activity ?
Fetching results in a conventional tabular layout is complex and expensive, because to get attributes from multiple rows you need to do JOIN for each attribute.
This problem can be solved by making few queries on partial data and processing them into tabular layout with your application. Even if you have 600GB of product data you can process it in batches if you require data from every single row in this table.
Going further If you would like to improve the performance of the queries you can select certain operations like for e.g. reporting or global text search and prepare for them index tables which would store required data and would be regenerated periodically, lets say every 30 minutes.
You don't even need to be concerned with the cost of extra data storage because it gets cheaper and cheaper every day.
If you would still be concerned with performance of operations done by the application, you can always use Erlang, C++, Go Language to pre-process the data and later on just process the optimised data further in your main app.
If I use Class Table Inheritance
meaning:
one table for Products, storing attributes common to all product types. Then one table per product type, storing attributes specific to that product type. -Bill Karwin
Which I like the best of Bill Karwin's Suggestions.. I can kind of foresee one drawback, which I will try to explain how to keep from becoming a problem.
What contingency plan should I have in place when an attribute that is only common to 1 type, then becomes common to 2, then 3, etc?
For example: (this is just an example, not my real issue)
If we sell furniture, we might sell chairs, lamps, sofas, TVs, etc. The TV type might be the only type we carry that has a power consumption. So I would put the power_consumption
attribute on the tv_type_table
. But then we start to carry Home theater systems which also have a power_consumption
property. OK its just one other product so I'll add this field to the stereo_type_table
as well since that is probably easiest at this point. But over time as we start to carry more and more electronics, we realize that power_consumption
is broad enough that it should be in the main_product_table
. What should I do now?
Add the field to the main_product_table
. Write a script to loop through the electronics and put the correct value from each type_table
to the main_product_table
. Then drop that column from each type_table
.
Now If I was always using the same GetProductData
class to interact with the database to pull the product info; then if any changes in code now need refactoring, they should be to that Class only.
You can have a Product table and a separate ProductAdditionInfo table with 3 columns: product ID, additional info name, additional info value. If color is used by many but not all kinds of Products you could have it be a nullable column in the Product table, or just put it in ProductAdditionalInfo.
This approach is not a traditional technique for a relational database, but I have seen it used a lot in practice. It can be flexible and have good performance.
Steve Yegge calls this the Properties pattern and wrote a long post about using it.
'IT' 카테고리의 다른 글
적절한 Linq where 절 (0) | 2020.07.05 |
---|---|
Visual Studio는 삭제 된 포인터로 무엇을하며 그 이유는 무엇입니까? (0) | 2020.07.05 |
webpack.config.js 파일 인 angular-cli-새로운 angular6는 ng eject를 지원하지 않습니다 (0) | 2020.07.05 |
자바 스크립트와 스레드 (0) | 2020.07.05 |
대리인 : 술어 조치 기능 (0) | 2020.07.05 |