엔티티 속성 값 데이터베이스 대 엄격한 관계형 모델 전자 상거래


136

EAV / CR 데이터베이스 모델이 잘못 되었다고 말하는 것이 안전합니다 . 그것은 말했다

질문 : 런타임시 변경 될 수있는 전자 상거래 제품을 설명하는 속성의 "클래스"를 처리하기 위해 어떤 데이터베이스 모델, 기술 또는 패턴을 사용해야합니까?

좋은 전자 상거래 데이터베이스에는 옵션 클래스를 저장합니다 (예 : TV 해상도는 각 TV의 해상도를 갖지만 다음 제품은 TV가 아니고 "TV 해상도"가 아닐 수 있음). 어떻게 저장하고 효율적으로 검색하며 사용자가 제품을 설명하는 가변 필드로 제품 유형을 설정할 수 있습니까? 검색 엔진이 고객이 일반적으로 콘솔 깊이에 따라 TV를 검색하는 것을 발견하면 필드에 콘솔 깊이를 추가 한 다음 런타임에 각 TV 제품 유형에 대해 단일 깊이를 추가 할 수 있습니다.

좋은 전자 상거래 앱에는 유용한 제품들이 있습니다. 여기에는 일련의 제품이 표시되고 "TV 해상도"를 헤더로 볼 수있는 "드릴 다운"사이드 메뉴가 있으며 가장 일반적인 5 가지 TV 해상도는 발견 세트. 하나를 클릭하면 해당 해상도의 TV 만 표시되므로 사이드 메뉴에서 다른 범주를 선택하여 드릴 다운 할 수 있습니다. 이러한 옵션은 런타임에 추가 된 동적 제품 속성입니다.

심도 깊은 논의:

간단히 말해 인터넷이나 모델 설명에 다음과 같은 설정을 "수정 적으로"수정할 수있는 링크가 있습니까? Noel Kennedy에게 카테고리 테이블을 제안 해 주셔서 감사하지만 그보다 더 큰 필요성이있을 수 있습니다. 의미를 강조하기 위해 아래에 다른 방법으로 설명합니다. 문제를 해결하기 위해 시점 수정이 필요하거나 EAV / CR에 대해 더 깊이 들어가야 할 수도 있습니다.

EAV / CR 모델에 대한 긍정적 인 반응을 좋아하십시오. 저의 동료 개발자들은 모두 Jeffrey Kemp가 아래에서 언급 한 내용을 말합니다. 문제는:

  • 엔티티 추가 및 제거 매주 속성
    (키워드는 미래의 속성을 지시 검색)
  • 새로운 엔티티가 매주 도착합니다
    (제품은 부품으로 조립됩니다)
  • 오래된 엔티티는 매주 사라짐
    (아카이브, 덜 인기있는, 계절별)

고객이 다음 두 가지 이유로 제품에 속성을 추가하려고합니다.

  • 유사 제품 간의 부서 / 키워드 검색 / 비교 차트
  • 결제 전 소비자 제품 구성

속성은 키워드 검색뿐만 아니라 의미를 가져야합니다. "휘핑 크림 프로스팅"이있는 모든 케이크를 비교하려면 케이크를 클릭하고 생일 테마를 클릭하고 휘핑 크림 프로스팅을 클릭 한 다음 크림 프로스팅이 모두 휘핑되어 있다는 사실을 알고 흥미로운 모든 케이크를 확인할 수 있습니다. 이것은 케이크에만 국한된 것이 아니라 단지 예일뿐입니다.


외래 키 자체를 참조하는 '카테고리'테이블을 가질 수없는 이유는 무엇입니까?
Noel Kennedy

29
EAV 데이터베이스 모델이 일부 애플리케이션에 적합하기 때문에 나쁘다고 말하는 것은 안전하지도 정확하지도 않습니다.
spencer7593 2016 년

Entity Framework 4에서와 같이 부모로부터 상속되는 다양한 속성으로 다양한 객체를 장식하면 어떻게 되나요? 이러한 개체를 어떻게 유지합니까?
Zachary Scott

1
극단적 인 버전의 EAV를 기반으로 한 시스템에 대한 한 컨설턴트의 경험에 대한이 훌륭한 기사를 다시 살펴보십시오. 읽어! simple-talk.com/opinion/opinion-pieces/bad-carma
Jeffrey Kemp

1
EAV는 매우 실행 가능한 데이터베이스 모델입니다. 나는 당신과 비슷한 문제를 겪고 있으며 해결책은 EAV입니다. 다음 기사를 추천합니다 : sqlblog.com/blogs/aaron_bertrand/archive/2009/11/19/…
Sandor

답변:


75

내가 생각할 수있는 몇 가지 일반적인 장단점이 있습니다. 하나가 다른 것보다 더 나은 상황이 있습니다.

옵션 1, EAV 모델 :

  • 장점 : 간단한 응용 프로그램을 설계하고 개발하는 시간이 줄어 듭니다.
  • 프로 : 쉽게 추가 할 수있는 새로운 엔터티 (사용자가 추가 할 수도 있습니까?)
  • 프로 : "일반적인"인터페이스 구성 요소
  • 단점 : 간단한 데이터 형식을 확인하는 데 필요한 복잡한 코드
  • 단점 : 간단한 보고서를위한 훨씬 더 복잡한 SQL
  • 단점 : 복잡한 보고서가 거의 불가능해질 수 있습니다
  • 단점 : 대용량 데이터 세트의 성능 저하

옵션 2, 각 엔티티를 개별적으로 모델링 :

  • 단점 : 요구 사항 및 디자인을 수집하는 데 더 많은 시간이 필요
  • 단점 : 새로운 실체는 전문가가 모델링하고 설계해야합니다.
  • 단점 : 각 엔터티에 대한 사용자 지정 인터페이스 구성 요소
  • 장점 : 구현하기 쉬운 데이터 형식 제약 조건 및 유효성 검사
  • 장점 : SQL은 작성, 이해 및 디버깅이 용이합니다.
  • 장점 : 가장 복잡한 보고서조차도 비교적 간단합니다
  • Pro : 대용량 데이터 세트를위한 최고의 성능

옵션 3, 조합 (모델 엔터티는 "적절하게"있지만 일부 / 모든 엔터티에 대한 사용자 지정 특성에 대해서는 "확장"을 추가합니다)

  • Pro / Con : 옵션 1보다 요구 사항과 디자인을 수집하는 데 더 많은 시간이 필요하지만 옵션 2만큼 많지는 않습니다. *
  • 단점 : 새로운 실체는 전문가가 모델링하고 설계해야합니다.
  • Pro : 나중에 새로운 속성을 쉽게 추가 할 수 있습니다
  • 단점 : 간단한 데이터 형식의 유효성을 검사하는 데 필요한 복잡한 코드 (사용자 지정 특성의 경우)
  • 단점 : 사용자 정의 인터페이스 구성 요소는 여전히 필요하지만 사용자 정의 속성에 일반 인터페이스 구성 요소가 가능할 수 있습니다
  • 단점 : 사용자 지정 특성이 보고서에 포함 되 자마자 SQL이 복잡해집니다.
  • 단점 : 사용자 지정 특성으로 검색하거나보고 할 필요가없는 한 일반적으로 우수한 성능

* 옵션 3이 설계 단계에서 시간을 절약 할 수 있을지 확실하지 않습니다.

개인적으로 나는 옵션 2에 의지하고 가능한 한 EAV를 피할 것입니다. 그러나 일부 시나리오의 경우 사용자는 EAV와 함께 제공되는 유연성이 필요합니다. 그러나 이것은 큰 비용이 듭니다.


텍스트 값 1-n에 대한 인덱스가있는 단일 테이블이 있으면 C # (ram)에서 원하는 것을 원하는 것에 매핑하십시오. 여전히 EAV처럼 작동하지만 "일치"는 도메인 모델이됩니다. 직렬화와 비슷하지만 인덱싱 된 텍스트 필드에서 SQL 선택을 사용할 수 있습니다. 레코드 당 여러 개의 선택이 없습니다. 모든 "비용"은 RAM에서 발생합니다.
Zachary Scott

1
@Zim, 이것은 옵션 3과 거의 비슷하게 들립니다. 각 행에는 1-n 개의 추가 "일반"열이 있으며 여기에 저장된 데이터는 응용 프로그램 수준에서 해석됩니다. 한 곳에서 한 레코드에 대한 모든 데이터를 가지면 성능이 향상됩니다. 그러나 이러한 열에 대한 메타 데이터는 어딘가에 저장해야하며, 여기에서 비용이 증가합니다. 물론, 메타 데이터를 램으로 캐시 할 수 있지만 도메인을 애플리케이션 코드에서 직접 모델링하는 것보다 여전히 비용이 많이 듭니다. 그러나 본격적인 EAV 모델보다 확실히 좋습니다!
Jeffrey Kemp

1
+10000 좋은 답변입니다. 요즘 사람들은 데이터베이스 디자인 및 요구 사항 수집에 급증합니다. 오히려 좋은 디자인을 만드는 데 시간이 걸리는 수백 배 이상의 코드를 작성하려고합니다.
Tulains Córdova

옵션 1의 구조 만 제공하는 경우 EAV 옵션 (1)보다 관계형 옵션 (2)에 대해 더 많은 디자인이 필요하지 않습니다 . 관계형 인터페이스는 해당 구조를 설명하는 메타 데이터에서 일반적입니다. 이것은 모든 옵션 2 단점을 제거합니다. 그러나 실제 Con : DDL은 테이블 관리 속도가 너무 느릴 수 있습니다.
philipxy

안녕 @ philipxy, 나는 "더 많은 디자인"을 말하지 않았다. EAV의 단점은 (아마도) 시스템 설계자가 모델 설계에 더 적은 시간 을 할애 하여이 설계 작업을 나중에 "사용자"에게 맡길 수 있다는 것입니다 (이러한 전문 설계의 부재는 옵션 1의 단점으로 이어집니다) . EAV가 설계자에게 비용을 절약하지 못할 경우 EAV를 거부하기 위해 더 많은 연료를 불에 추가합니다. 또한 DDL이 "너무 느리다"고 동의하지 않습니다. DDL이 거의 필요하지 않기 때문에 (즉, 모델의 오류를 수정하거나 새로운 기능을 구현하기 위해) 성능이 상대적으로 중요하지 않아야합니다.
Jeffrey Kemp 1

63

EAV / CR 데이터베이스 모델이 잘못되었다고 말하는 것이 안전합니다.

아뇨. 단지 관계형 데이터베이스를 비효율적으로 사용한다는 것입니다. 순수 키 / 값 저장소는이 모델에서 효과적입니다.

이제 실제 질문에 : 다양한 속성을 저장하고 검색 가능한 상태로 유지하는 방법은 무엇입니까?

EAV를 사용하십시오. 귀하의 경우 단일 추가 테이블이됩니다. 대부분의 RDBM은 속성 이름과 값 모두에 색인을 지정하여 속성 이름 반복에 접두사 압축을 사용하여 실제로 빠르고 컴팩트하게 만듭니다.

EAV / CR을 사용하여 '실제'필드를 바꾸면 추악 해집니다. 모든 도구와 마찬가지로 도구를 과도하게 사용하면 '나쁜'이미지가됩니다.


그래서 질문은 내 범주 중 하나에 대한 15 개의 추가 필드가 있고 eav 모델에서는 16 조인 ​​+ 메인 테이블을 필요로하므로 제품 검색을 위해 16 개의 왼쪽 조인을 만들고 (고객이 원하는 경우 16 곳) 3-4 백만 레코드 ( 사람들이 중고 제품을 판매하는 웹 사이트) 성능이 낮을까요?
babak faghihian

2
이러한 "추가 필드"가 이미 정의되어 있으면 "실제 필드"로 수행하는 것이 가장 좋습니다. 물론 큰 쿼리에서 무제한의 조인을 수행하면 막대한 비용이 들지만 여전히 괜찮을 수 있습니다. 메타 데이터가 많은 프로젝트에서 수행 한 작업은 "주 항목"당 여러 개의 "태그"(EAV 레코드)를 허용하지만 "대형 쿼리"는 사전 정의 된 일부 태그 이름 만 선택하여 총 조인 수를 제한합니다. (현재는 4 개의 태그와 약 5 개의 다른 조인입니다.) 사용자가 특정 항목을 선택 하면 단일 항목에 대한 모든 항목 을 가져 옵니다.
Javier

그러나 물론 특정 시스템은 현재 hstore필드 로 포팅되고 있습니다 (PostgreSQL을 사용하는 이유 중 하나)
Javier

15
//이 시점에서 Magento / Adobe PSD 형식에 대해 말씀 드리겠습니다 .
// Magento / PSD 는 좋은 전자 상거래 플랫폼 / 형식 이 아닙니다 . Magento / PSD 도 나쁜 전자 상거래 플랫폼 / 형식 이 아닙니다 . 그것을 그렇게 부르는 것은
// Zencart 또는 OsCommerce와 같은 다른 나쁜 전자 상거래 플랫폼 / 포맷 에 모욕적입니다. 아니요, Magento / PSD 는 끔찍한 전자 상거래 플랫폼 / 형식 입니다. 데
// 몇 주 동안이 코드 작업을 마쳤습니다. Magento / PSD에 대한 증오 가 격렬한 화염 에 휩싸였습니다
// 백만 태양의 격렬한 열정으로 불타고 있습니다.

http://code.google.com/p/xee/source/browse/trunk/XeePhotoshopLoader.m?spec=svn28&r=11#107

내부 모델은 누군가 멍청이 게임에 스키마를 넣고 그것을 밀봉하여 페인트 해커에 넣는 것처럼 기괴합니다.

실제 : 저는 미들웨어 이행 앱을 개발 중이며 주소 정보를 얻기위한 쿼리 중 하나입니다.

CREATE OR REPLACE VIEW sales_flat_addresses AS
SELECT sales_order_entity.parent_id AS order_id, 
       sales_order_entity.entity_id, 
       CONCAT(CONCAT(UCASE(MID(sales_order_entity_varchar.value,1,1)),MID(sales_order_entity_varchar.value,2)), "Address") as type, 
       GROUP_CONCAT( 
         CONCAT( eav_attribute.attribute_code," ::::: ", sales_order_entity_varchar.value )
         ORDER BY sales_order_entity_varchar.value DESC
         SEPARATOR '!!!!!' 
       ) as data
  FROM sales_order_entity
       INNER JOIN sales_order_entity_varchar ON sales_order_entity_varchar.entity_id = sales_order_entity.entity_id
       INNER JOIN eav_attribute ON eav_attribute.attribute_id = sales_order_entity_varchar.attribute_id
   AND sales_order_entity.entity_type_id =12
 GROUP BY sales_order_entity.entity_id
 ORDER BY eav_attribute.attribute_code = 'address_type'

주문에 대한 정확한 주소 정보, 지연

-

요약 : 다음과 같은 경우 에만 마 젠토를 사용하십시오.

  1. 많은 돈을 받고 있습니다
  2. 당신은해야합니다
  3. 고통을 즐기십시오

이것은 오래된 게시물이지만 클라이언트를 위해 Magento 프로젝트를 시작했을 때 3 개월 전에 발견 되었기를 바랍니다. boggle / paint-shaker 유추를 위해 +1!
trevorc

1
꽤 심심한 마 젠토는 전자 상거래 시스템 측면에서 최고라고 생각합니다. 어쩌면 그것은 단지 마케팅이 매우 좋다
Herr

1
Magento는 유지 관리 수준으로 인해 인기가 없지만 사용자 정의 기능으로 누구나 아키텍처를 변경하거나 수정하지 않고도 새로운 기능을 구현할 수 있습니다. 이 기능은 비용과 함께 제공됩니다.
Diego Mendes

FE와 BE에 대한 트리플 통증과 더 많은 고통을 피하려면 Magento 2에서 멀리 떨어져
TheBlackBenzKid

15

NoSQL 데이터베이스를 언급 한 사람이 아무도 없습니다.

프로덕션 컨텍스트에서 NoSQL을 연습 한 적이 없었습니다 (MongoDB를 테스트하고 감동했습니다). NoSQL의 요점은 다양한 속성을 가진 항목을 동일한 "문서"에 저장할 수 있습니다.


MongoDB에 쓰려면 데이터베이스 레벨 잠금이 필요 하며 이는 동시 프로덕션 트래픽을 의미합니다.
Bill Karwin

잠금 지속 시간은 마이크로 초 단위입니다.
Hello World

12

ETL 유형의 응용 프로그램에서와 같이 성능이 주요 요구 사항이 아닌 경우 EAV에는 또 다른 이점이 있습니다. 차등 저장.

나는 초과 요구 사항이 도메인 객체의 히스토리를 첫 번째 "버전"에서 현재 상태로 볼 수있는 기능인 여러 애플리케이션을 구현했습니다. 해당 도메인 개체에 많은 수의 특성이있는 경우 각 변경 시마다 새 행을 해당 테이블에 삽입해야합니다 (히스토리가 유실되므로 업데이트가 아니라 삽입). 이 도메인 객체가 Person이라고 가정하고 Persons 수명주기 동안 다양한 속성으로 평균 100 회 이상의 변경 사항을 추적 할 수있는 500k Persons가 있다고 가정하겠습니다. 단 하나의 주요 도메인 개체를 가진 응용 프로그램이 드물다는 사실과 함께 데이터베이스 크기가 빠르게 제어 할 수 없게된다는 사실을 빨리 알게 될 것입니다.

쉬운 해결책은 중복 정보를 반복적으로 저장하지 않고 주요 도메인 개체에 대한 차등 변경 사항 만 저장하는 것입니다.

모든 비즈니스 모델은 새로운 비즈니스 요구를 반영하기 위해 시간이 지남에 따라 변경됩니다. 기간. EAV 사용은 박스에서 사용할 도구 중 하나 일뿐입니다. 그러나 자동으로 "나쁜"것으로 분류되어서는 안됩니다.


2
"EAV 사용은 상자에서 사용할 도구 중 하나이지만 자동으로"나쁜 "것으로 분류되어서는 안됩니다. +1
Catchops

Btw, 이것을 SCD (천천히 치수 변경)라고합니다. 또한 bitemporal 요구 사항 (특정 유형 4 SCD의 경우)은이 특성이있는 속성에 대한 EAV 스키마를 요구합니다. NoSQL의 99 %에는 기본 조인이 없으므로이 유형의 데이터와 "실시간"조인이 필요한 경우 EAV가 유일한 방법입니다.
cowbert

3

나는 같은 문제로 고심하고 있습니다. 기존의 두 가지 전자 상거래 솔루션 인 Magento (EAV) 및 Joomla (정규 관계형 구조)에 대한 다음 논의를 확인하는 것이 흥미로울 수 있습니다. https://forum.virtuemart.net/index.php?topic=58686.0

마젠 토의 EAV 성능은 실제 쇼퍼입니다.

그렇기 때문에 표준화 된 구조에 집중하고 있습니다. 유연성 부족을 극복하기 위해 나중에 편집 할 수있는 별도의 데이터 사전 (XML 또는 별도의 DB 테이블)을 추가 할 계획이며,이를 바탕으로 제품 범주를 표시하고 새로운 속성 세트를 비교하기위한 애플리케이션 코드는 다음과 같습니다. SQL 스크립트와 함께 생성됩니다.

이러한 경우 이러한 아키텍처는 유연하고 성능이 뛰어난 스위트 스폿으로 보입니다.

실제 환경에서 ALTER TABLE을 자주 사용하면 문제가 발생할 수 있습니다. Postgres를 사용하고 있으므로 MVCC와 트랜잭션 DDL이 고통을 덜어 줄 것입니다.


2

나는 여전히 가장 낮은 의미의 EAV 원자 수준에서 모델링에 투표합니다. 컨텐츠 모델, 속성, 그레인 등의 반복 요구 사항을 결정하기 위해 특정 사용자 커뮤니티에 적합한 표준, 기술 및 응용 프로그램을 사용하십시오.


2

제품 카탈로그 속성에 관한 것이므로 해당 속성에 대한 유효성 검사 요구 사항이 다소 제한되어있는 경우 EAV의 유일한 단점은 쿼리 성능뿐 아니라 쿼리가 속성을 가진 여러 "사물"(제품)을 처리 할 때만 문제가됩니다. 쿼리 성능은 "ID가 234 인 제품의 모든 속성을 제공합니다"는 아니지만 최적의 성능은 여전히 ​​빠릅니다.

한 가지 해결책은 제품 카탈로그의 관리자 / 편집 측에 대해서만 SQL 데이터베이스 / EAV 모델을 사용하고 제품을 검색 가능하게하는 제품으로 비정규 화하는 프로세스를 갖는 것입니다. 이미 속성이 있으므로 패싯을 원할 가능성이 높으므로 Solr 또는 ElasticSearch 일 수 있습니다. 이 접근 방식은 기본적으로 EAV 모델의 모든 단점을 피하고 추가 된 복잡성은 업데이트시 전체 제품을 JSON으로 직렬화하는 것으로 제한됩니다.


2

EAV에는 많은 단점이 있습니다.

  1. 시간이 지남에 따른 성능 저하 응용 프로그램의 데이터 양이 특정 크기 이상으로 증가하면 해당 데이터의 검색 및 조작이 점점 더 효율적이지 않을 수 있습니다.
  2. SQL 쿼리는 매우 복잡하고 쓰기가 어렵습니다.
  3. 데이터 무결성 문제. 필요한 모든 필드에 외래 키를 정의 할 수 없습니다.
  4. 고유 한 메타 데이터를 정의하고 유지해야합니다.

1. 이것은 대부분의 관계형 데이터베이스에서도 마찬가지입니다. 이것이 샤딩이 발명 된 이유입니다. 2. 데이터 모델링은 복잡하고 구현하기 어려울 수 있습니다. OLAP 큐브 스키마 변경을 기다리는 데 몇 주에서 몇 달이 걸렸습니다. 3. 대부분의 소프트웨어에서 이미 수행되었습니다. 4. 관계형 스키마를 모델링 할 때 "ERwin, Excel 및 Visio에서"이 작업을 수행해야합니다.
cowbert

1

약간 다른 문제가 있습니다. 스파 스 값이 많은 많은 속성 (EAV를 사용하는 것이 좋은 이유 일 수 있음) 대신 스프레드 시트와 같은 것을 저장하고 싶습니다. 시트의 열은 변경 될 수 있지만 시트 내의 모든 셀에는 데이터가 포함되지 않습니다 (드문 드문 경우).

하나는 EAV를 사용하는 것과 다른 하나는 Postgres ARRAY를 사용하여 셀 데이터를 저장하는 두 가지 디자인을 벤치마킹하기 위해 작은 테스트 세트를 만들었습니다 .

EAV 여기에 이미지 설명을 입력하십시오

정렬 여기에 이미지 설명을 입력하십시오

두 스키마 모두 적절한 열에 인덱스가 있으며 인덱스는 플래너에서 사용합니다.

그것은 밝혀졌다 어레이 기반 스키마가 크기 순서 빨랐다 삽입 및 쿼리 모두. 빠른 테스트에서 두 가지 모두 선형으로 확장 된 것으로 보입니다. 그러나 테스트는 그리 철저하지 않습니다. 제안과 포크는 환영합니다. MIT 라이센스하에 있습니다.


배열 모델을 사용하여 시트 열 (예 : vlookup)에서 어떻게 결합 했습니까? 자체 배열 병합 정렬 함수를 작성할 필요가 없습니까? 셀 값의 키로 셀의 sheet_id + x- 좌표 + y 좌표를 사용한 경우 사전 컴파일 된 병합 정렬만큼 좋을 수도 있습니다. (excel을 에뮬레이트하려면 0-18278이 A-ZZZ 열인 x 좌표에 대한 룩업 테이블을 미리 생성하십시오 (excel은 16384에서 최대 값임)), sheet_id = uuid 및 x-coord = 0 및 y-coord 값을 선택할 수 있습니다 <1001 <열 A의 첫 1000 행을 얻으려면
cowbert

@ cowbert 당신이 맞아요; 실제로 관심있는 열을로드하고 Python에서 조인을 수행합니다. 느슨하게!
z0r
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.