it-swarm-ko.tech

동적 데이터베이스 스키마

동적 논리 데이터베이스 스키마에 스토리지를 제공하기 위해 권장되는 아키텍처는 무엇입니까?

명확히하기 위해 : 시스템이 프로덕션에서 한 번 사용자에 의해 스키마를 확장하거나 변경할 수있는 모델에 스토리지를 제공 해야하는 경우이를 가능하게 할 좋은 기술, 데이터베이스 모델 또는 스토리지 엔진은 무엇입니까?

설명 할 몇 가지 가능성 :

  • 동적으로 생성 된 DML을 통해 데이터베이스 객체 생성/변경
  • 많은 수의 희소 물리적 열이있는 테이블 작성 및 '중복'논리 스키마에 필요한 테이블 만 사용
  • 동적 열 값을 행으로 저장하는 '길고 좁은'테이블을 생성 한 다음 특정 엔터티에 대한 모든 값을 포함하는 '짧고 넓은'행 집합을 생성하기 위해 피벗해야하는 테이블
  • BigTable/SimpleDB PropertyBag 유형 시스템 사용

실제 경험을 바탕으로 한 답변은 크게 감사하겠습니다.

65
Fake Jim

당신이 제안하는 것은 새로운 것이 아닙니다. 많은 사람들이 그것을 시도했습니다 ... 대부분의 사람들은 "무한"유연성을 추구하고 그보다 훨씬 적은 것으로 끝납니다. 데이터베이스 디자인의 "roach motel"입니다. 데이터가 들어오지 만 데이터를 가져 오는 것은 거의 불가능합니다. 어떤 종류의 제약 조건에 대한 코드 작성을 시도하고 개념화하면 무슨 의미인지 알 수 있습니다.

최종 결과는 일반적으로 디버그, 유지 관리 및 데이터 일관성 문제로 가득 찬 훨씬 더 어려운 시스템입니다. 이것은 always 사례가 아니지만, 그렇지 않은 경우가 종종 있습니다. 대부분 프로그래머가이 열차의 잔해가 다가오는 것을 보지 못하고 방어 적으로 코드를 작성하지 못하기 때문에. 또한 "무한한"유연성이 실제로 필요하지 않은 경우가 종종 있습니다. 개발자 팀이 "Gosh 나는 어떤 종류의 데이터를 여기에 넣을지 알 수 없으므로 최종 사용자는 괜찮습니다."라는 사양을 얻을 때 매우 나쁜 "냄새"입니다. 사용할 수있는 사전 정의 된 속성 유형이 있음 (일반 전화 번호를 코딩하고 번호를 작성하도록 함) – 정규화 된 시스템에서는 사소한 것이며 유연성과 무결성을 유지합니다!

아주 좋은 개발 팀이 있고이 디자인으로 극복해야 할 문제를 친밀하게 인식한다면, 버그가 많은 시스템은 아니지만 잘 설계된 시스템을 성공적으로 코딩 할 수 있습니다. 대부분의 경우.

그래도 왜 당신에게 많은 확률이 쌓일까요?

나를 믿지 않습니까? Google "하나의 진정한 조회 테이블"또는 "단일 테이블 디자인". 좋은 결과 : http://asktom.Oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056

http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=

http://www.dbazine.com/ofinterest/oi-articles/celko22

http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2

36
Matt Rogish

MSSQL의 강력한 형식의 xml 필드가 우리에게 효과적이었습니다.

20
Bloodhound

다른 사람들이 말했듯이 다른 선택이 없다면 이것을하지 마십시오. 이것이 필요한 경우는 사용자가 사용자 정의 데이터를 기록 할 수있는 상용 제품을 판매하는 경우입니다. 회사 제품이이 범주에 속합니다.

고객이이를 수행하도록 허용해야하는 경우 다음과 같은 몇 가지 팁이 있습니다.
-robust 관리 도구를 만들어 스키마 변경을 수행하고 다른 방법으로는 이러한 변경을 수행 할 수 없습니다.
-관리 기능으로 만듭니다. 일반 사용자가 액세스 할 수 없습니다.
-모든 스키마 변경에 대한 모든 세부 정보를 기록합니다. 이렇게하면 문제를 디버깅하는 데 도움이되며 고객이 어리석은 일을하면 CYA 데이터도 제공합니다.

이러한 작업을 성공적으로 수행 할 수 있으면 (특히 첫 번째 작업) 언급 한 모든 아키텍처가 작동합니다. 사용자 지정 필드에 저장된 데이터에 액세스 할 때 DBMS의 쿼리 기능을 활용할 수 있으므로 데이터베이스 객체를 동적으로 변경하는 것이 좋습니다. 다른 세 가지 옵션을 사용하려면 많은 양의 데이터를로드 한 다음 대부분의 데이터 처리를 코드로 수행해야합니다.

16
Josh Yeager

비슷한 요구 사항이 있으며 스키마가없는 MongoDB 를 사용하기로 결정했습니다.

MongoDB ( "humongous")는 C++ 프로그래밍 언어로 작성된 확장 가능한 고성능의 스키마없는 문서 지향 데이터베이스 인 오픈 소스입니다. (위키 백과)

하이라이트:

  • 풍부한 쿼리 기능이 있습니다 (SQL DB와 가장 유사 할 수 있음)
  • 생산 준비 완료 (foursquare, sourceforge 사용)

저암 (몽고를 올바르게 사용할 수 있도록 이해해야하는 것들) :

9
clyfe

나는 실제 프로젝트에서 그것을했다 :

데이터베이스는 50의 배열 인 하나의 필드를 가진 하나의 테이블로 구성되었습니다. 'Word'인덱스가 설정되어 있습니다. 모든 데이터는 유형이 없으므로 '워드 인덱스'가 예상대로 작동했습니다. 숫자 필드는 문자로 표시되었으며 실제 정렬은 클라이언트 측에서 수행되었습니다. (필요한 경우 각 데이터 유형마다 여러 배열 필드를 가질 수 있습니다).

논리 테이블의 논리 데이터 스키마는 다른 테이블 행 'type'(첫 번째 배열 요소)이있는 동일한 데이터베이스 내에 유지되었습니다. 또한 동일한 '유형'필드를 사용하여 기록 중 복사 스타일의 간단한 버전 관리를 지원했습니다.

장점 :

  1. 데이터베이스를 덤프/재로드 할 필요없이 열을 동적으로 재 배열 및 추가/삭제할 수 있습니다. 모든 새로운 열 데이터는 0 시간에 초기 값 (가상)으로 설정 될 수 있습니다.
  2. 모든 레코드와 테이블의 크기가 동일하기 때문에 조각화가 최소화됩니다. 때로는 더 나은 성능을 제공하기도합니다.
  3. 모든 테이블 스키마는 가상입니다. 모든 논리적 스키마 구조가 가능합니다 (재귀 적이거나 객체 지향적 임).
  4. "한 번만 쓰기, 대부분 읽기, 삭제 없음/삭제 표시"데이터에 적합합니다 (대부분의 웹 앱은 실제로 이와 같습니다).

단점 :

  1. 전체 단어로만 색인 작성, 약어 없음,
  2. 복잡한 쿼리가 가능하지만 약간의 성능 저하가 있습니다.
  3. 선호하는 데이터베이스 시스템이 배열 및 Word 색인을 지원하는지 여부에 따라 다릅니다 (PROGRESS RDBMS에서 보완 됨).
  4. 관계형 모델은 프로그래머의 마음에만 있습니다 (즉, 런타임에만).

이제 다음 단계는 파일 시스템 수준에서 이러한 데이터베이스를 구현하는 것입니다. 비교적 쉬울 수 있습니다.

7
Thevs

관계형 DB를 사용하는 요점은 데이터를 안전하고 일관되게 유지하는 것입니다. 사용자가 스키마를 변경할 수있게되면 데이터 무결성이 유지됩니다.

CMS 시나리오와 같이 이기종 데이터를 저장해야하는 경우 XSD에 의해 유효성이 검증 된 XML을 한 줄에 저장하는 것이 좋습니다. 물론 성능과 손쉬운 검색 기능을 잃어 버렸지 만 IMHO와의 균형이 맞습니다.

2016 년부터는 XML을 잊어 버리세요! JSON을 사용하여 적절한 유형의 열을 백엔드로하여 비 관계형 데이터 백을 저장하십시오. 일반적으로 많은 -가방 내부 값으로 쿼리 할 필요는 없습니다. 많은 현대 SQL 데이터베이스가 JSON을 기본적으로 이해하더라도 속도가 느려집니다.

6
Sklivvz

2 개의 데이터베이스 생성

  • DB1은 정적 테이블을 포함하며 데이터의 "실제"상태를 나타냅니다.
  • DB2는 사용자가 원하는대로 자유롭게 사용할 수 있습니다. DB2에서 이상한 모양의 테이블을 채우려면 코드를 작성해야합니다.
3
AJ.

실제 데이터를 저장하기위한 유연한 스키마를 설명 할 수있는 데이터베이스 스키마 인 일종의 "메타 스키마"가 실제로 원하는 것처럼 들립니다. 동적 스키마 변경은 손대지 않으며, 특히 사용자가 변경을 허용하는 경우에는 엉망이 아닙니다.

이 작업에 더 적합한 데이터베이스를 다른 데이터베이스보다 찾지 않으므로 다른 기준에 따라 데이터베이스를 선택하는 것이 가장 좋습니다. 예를 들어, DB를 호스팅하기 위해 어떤 플랫폼을 사용하고 있습니까? 앱은 어떤 언어로 작성됩니까? 기타

"메타 스키마"가 의미하는 바를 명확히하기 위해 :

CREATE TABLE data (
    id INTEGER NOT NULL AUTO_INCREMENT,
    key VARCHAR(255),
    data TEXT,

    PRIMARY KEY (id)
);

이것은 매우 간단한 예입니다. 귀하의 요구에 더 구체적인 것이있을 것입니다 (그리고 작업하기가 조금 더 쉬울 것입니다). 응용 프로그램 레벨에서 데이터베이스 스키마 자체를 변경할 수없는 것으로 간주해야합니다. 모든 구조적 변화는 데이터 (즉, 해당 스키마의 인스턴스화)에 반영되어야합니다.

3
Daniel Spiewak

질문에 표시된 모델이 모든 프로덕션 시스템에서 사용된다는 것을 알고 있습니다. 내가 일하는 큰 대학/교육 기관에서 다소 큰 것이 사용 중입니다. 특히 길고 좁은 테이블 방식을 사용하여 다양한 데이터 수집 시스템에서 수집 한 데이터를 매핑합니다.

또한 Google은 최근 자사의 코드 사이트를 통해 내부 데이터 공유 프로토콜 인 프로토콜 버퍼를 오픈 소스로 출시했습니다. 이 접근 방식으로 모델링 된 데이터베이스 시스템은 매우 흥미로울 것입니다.

다음을 확인하십시오.

엔티티 속성 값 모델

Google 프로토콜 버퍼

3
siculars

EAV 접근법 나는 최선의 접근법이라고 생각하지만 많은 비용이 듭니다.

2
kamal

Wikipedia에는 ​​문제 공간에 대한 훌륭한 개요가 있습니다.

http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model

2
DenNukem

나는 그것이 오래된 주제라는 것을 알고 있지만 실제로는 결코 잃지 않을 것이라고 생각합니다. 나는 지금 그런 것을 개발하고 있습니다. 여기 내 접근 방식이 있습니다. MySQL, Apache, PHP 및 Zend Framework 2가있는 서버 설정을 응용 프로그램 프레임 워크로 사용하지만 다른 설정과도 잘 작동합니다.

다음은 간단한 구현 안내서입니다. 여기에서 더 발전시킬 수 있습니다.

효과적인 SQL은 너무 복잡하기 때문에 고유 한 쿼리 언어 인터프리터를 구현해야합니다.

예:

select id, password from user where email_address = "[email protected]"

실제 데이터베이스 레이아웃 :

테이블 '사양': (데이터 액세스 계층에 캐시되어야 함)

  • id : int
  • parent_id : 정수
  • 이름 : varchar (255)

표 '항목':

  • id : int
  • parent_id : 정수
  • spec_id : 정수
  • 데이터 : varchar (20000)

테이블 '사양'의 내용 :

  • 1, 0, '사용자'
  • 2, 1, '이메일 주소'
  • 3, 1, '비밀번호'

표 '항목'의 내용 :

우리 자신의 쿼리 언어로 예제의 번역 :

select id, password from user where email_address = "[email protected]"

표준 SQL에 다음과 같이 보입니다.

select 
    parent_id, -- user id
    data -- password
from 
    items 
where 
    spec_id = 3 -- make sure this is a 'password' item
    and 
    parent_id in 
    ( -- get the 'user' item to which this 'password' item belongs
        select 
            id 
        from 
            items 
        where 
            spec_id = 1 -- make sure this is a 'user' item
            and 
            id in 
            ( -- fetch all item id's with the desired 'email_address' child item
                select 
                    parent_id -- id of the parent item of the 'email_address' item
                from 
                    items 
                where 
                    spec_id = 2 -- make sure this is a 'email_address' item
                    and
                    data = "[email protected]" -- with the desired data value
            )
    )

스펙 이름에서 spec_id를 가져 오려면 스펙 테이블을 연관 배열 또는 해시 테이블에 캐시해야합니다. 그렇지 않으면이 코드 조각과 같이 이름에서 spec_id를 가져 오기 위해 더 많은 SQL 오버 헤드를 삽입해야합니다.

나쁜 예, 이것을 사용하지 말고 피하십시오. 대신 specs 테이블을 캐시하십시오!

select 
    parent_id, 
    data 
from 
    items 
where 
    spec_id = (select id from specs where name = "password") 
    and 
    parent_id in (
        select 
            id 
        from 
            items 
        where 
            spec_id = (select id from specs where name = "user") 
            and 
            id in (
                select 
                    parent_id 
                from 
                    items 
                where 
                    spec_id = (select id from specs where name = "email_address") 
                    and 
                    data = "[email protected]"
            )
    )

나는 당신이 아이디어를 얻고 그 접근 방식이 당신에게 적합한 지 스스로 결정할 수 있기를 바랍니다.

즐겨! :-)

2
Oliver Konig

과거에는 옵션 C를 선택했습니다. 동적 열 값을 행으로 저장하는 '길고 좁은'테이블을 만든 다음 특정 엔터티에 대한 모든 값을 포함하는 '짧고 넓은'행 집합을 만들려면 피벗해야합니다.. 그러나 나는 ORM을 사용하고 있었고 그 사실로 인해 고통 스러웠습니다. LinqToSql과 같은 방식으로 생각할 수 없습니다. 필드를 참조하려면 해시 테이블을 만들어야한다고 생각합니다.

@ Skliwz : 사용자가 사용자 정의 필드를 만들 수 있도록하는 데 관심이 있다고 생각합니다.

0
Danimal

C2.com 위키에서 "동적 관계"에 대한 아이디어가 탐구되었습니다. DBA가 필요하지 않습니다. 열과 테이블은 작성시 작성입니다. 기존 RDBMS처럼 작동하도록 제한 조건을 추가하지 않으면 프로젝트가 성숙함에 따라 점진적으로 "잠글"수 있습니다.

개념적으로 각 행을 XML 문으로 생각할 수 있습니다. 예를 들어 직원 레코드는 다음과 같이 나타낼 수 있습니다.

<employee lastname="Li" firstname="Joe" salary="120000" id="318"/>

이것은 not 는 XML로 구현되어야 함을 암시하며, 단지 편리한 개념입니다. "SELECT madeUpColumn ..."과 같이 존재하지 않는 열을 요청하면 추가 제약 조건이 금지되지 않는 한 빈 또는 null로 처리됩니다. 묵시적 유형 모델로 인해 비교에주의해야하지만 SQL 을 사용할 수 있습니다. 그러나 유형 처리 이외의 Dynamic Relational 시스템 사용자는 기존 RDBMS 지식의 대부분을 활용할 수 있기 때문에 집에있는 것처럼 느낄 것입니다. 누군가가 그냥 만들면 ...

0
FloverOwe

ElasticSearch. 날짜별로 분할 할 수있는 데이터 집합을 처리하고 데이터에 JSON을 사용할 수 있으며 데이터 검색을 위해 SQL을 사용하지 않는 경우 특히 고려해야합니다.

ES는 힌트를 통해 자동으로 보내거나 하나의 HTTP 명령 ( "매핑")으로 정의/변경할 수있는 새 JSON 필드에 대해 스키마를 유추합니다. SQL을 지원하지는 않지만 훌륭한 조회 기능과 집계 기능이 있습니다.

0
Oren