program tip

동적 데이터베이스 스키마

radiobox 2020. 11. 15. 11:06
반응형

동적 데이터베이스 스키마


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

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

설명 할 수있는 몇 가지 가능성 :

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

실제 경험을 바탕으로 한 모든 답변은 대단히 감사하겠습니다.


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

최종 결과는 일반적으로 디버그, 유지 관리가 훨씬 더 어렵고 데이터 일관성 문제로 가득 찬 시스템입니다. 이것이 항상 그런 것은 아니지만 종종 그렇게 되는 경우가 많습니다. 대부분 프로그래머가이 열차 사고가 오는 것을 보지 못하고 방어 적으로 코딩하지 못하기 때문입니다. 또한 "무한한"유연성이 실제로 필요하지 않은 경우가 종종 있습니다. 개발팀이 "어떻게 여기에 어떤 종류의 데이터를 넣을지 전혀 모르겠습니다. 그러니 무엇이든 넣도록하겠습니다"라는 사양을 개발 팀이받을 때 그것은 매우 나쁜 "냄새"입니다. 그리고 최종 사용자는 괜찮습니다. 사용할 수있는 사전 정의 된 속성 유형 (일반 전화 번호,

당신이 아주 좋은 개발 팀을 가지고 있고이 디자인으로 극복해야 할 문제를 잘 알고 있다면, 끔찍한 버그가있는 시스템이 아니라 잘 디자인 된 시스템을 성공적으로 코딩 할 수 있습니다. 대부분.

그래도 왜 당신에게 너무 많은 배당률이 쌓여있는 것으로 시작합니까?

나를 믿지 않습니까? Google "One True Lookup Table"또는 "단일 테이블 디자인". 좋은 결과 : 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=3

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

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


MSSQL의 강력한 형식의 xml 필드가 우리를 위해 일했습니다.


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

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

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


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

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

하이라이트:

  • 풍부한 쿼리 기능 (SQL DB에 가장 가까운)
  • 프로덕션 준비 (foursquare, sourceforge 사용)

Lowdarks (mongo를 올바르게 사용할 수 있도록 이해해야하는 항목) :


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

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

논리 테이블에 대한 논리 데이터 스키마는 다른 테이블 행 'type'(첫 번째 배열 요소)을 사용하여 동일한 데이터베이스에 보관되었습니다. 또한 동일한 'type'필드를 사용하여 copy-on-write 스타일의 단순 버전 관리도 지원했습니다.

장점 :

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

단점 :

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

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


관계형 DB를 갖는 요점은 데이터를 안전하고 일관되게 유지하는 것입니다. 사용자가 스키마를 변경하도록 허용하는 순간 데이터 무결성이 유지됩니다.

예를 들어 CMS 시나리오와 같이 이기종 데이터를 저장해야하는 경우 XSD에서 유효성을 검사 한 XML을 연속으로 저장하는 것이 좋습니다. 물론 성능과 쉬운 검색 기능을 잃지 만 IMHO와의 좋은 절충안입니다.

2016 년 이후로 XML은 잊어 버려! JSON을 사용하여 적절하게 입력 된 열을 백엔드로 사용하여 비 관계형 데이터 백을 저장합니다. 일반적으로 많은 최신 SQL 데이터베이스가 JSON을 기본적으로 이해하더라도 속도가 느린 bag 내부의 값으로 쿼리 할 필요가 없습니다 .


여러분이 정말로 원하는 것은 실제 데이터를 저장하기위한 유연한 스키마를 설명 할 수있는 데이터베이스 스키마 인 "메타 스키마"와 같은 것 같습니다. 동적 스키마 변경은 특히 사용자가 변경하도록 허용 된 경우에는 다루지 않고 다루고 싶은 것이 아닙니다.

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

"메타 스키마"가 의미하는 바를 명확히하려면 :

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

    PRIMARY KEY (id)
);

이것은 매우 간단한 예입니다. 당신은 당신의 필요에 더 구체적인 무언가를 가질 것입니다 (그리고 좀 더 쉽게 작업 할 수 있기를 바랍니다). 그러나 그것은 제 요점을 설명하는 역할을합니다. 데이터베이스 스키마 자체는 응용 프로그램 수준에서 변경할 수없는 것으로 간주해야합니다. 모든 구조적 변경 사항은 데이터에 반영되어야합니다 (즉, 해당 스키마의 인스턴스화).


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

또한 Google은 최근 코드 사이트를 통해 내부 데이터 공유 프로토콜 인 프로토콜 버퍼를 오픈 소스로 공개했습니다. 이 접근법을 기반으로 한 데이터베이스 시스템은 매우 흥미로울 것입니다.

다음을 확인하십시오.

엔터티 속성 값 모델

Google 프로토콜 버퍼


2 개의 데이터베이스 생성

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

EAV 접근 방식이 최선의 접근 방식이라고 생각하지만 비용이 많이 듭니다.


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

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


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

다음은 간단한 구현 가이드입니다.이 가이드에서 직접 발전시킬 수 있습니다.

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

예:

select id, password from user where email_address = "xyz@xyz.com"

물리적 데이터베이스 레이아웃 :

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

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

테이블 '항목':

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

테이블 '사양'의 내용 :

  • 1, 0, 'user'
  • 2, 1, 'email_address'
  • 3, 1, 'password'

Contents of table 'items':

  • 1, 0, 1, ''
  • 2, 1, 2, 'xyz@xyz.com'
  • 3, 1, 3, 'my password'

The translation of the example in our own query language:

select id, password from user where email_address = "xyz@xyz.com"

to standard SQL would look like this:

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 = "xyz@xyz.com" -- with the desired data value
            )
    )

You will need to have the specs table cached in an associative array or hashtable or something similar to get the spec_id's from the spec names. Otherwise you would need to insert some more SQL overhead to get the spec_id's from the names, like in this snippet:

Bad example, don't use this, avoid this, cache the specs table instead!

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 = "xyz@xyz.com"
            )
    )

I hope you get the idea and can determine for yourself whether that approach is feasible for you.

Enjoy! :-)


Over at the c2.com wiki, the idea of "Dynamic Relational" was explored. You DON'T need a DBA: columns and tables are Create-On-Write, unless you start adding constraints to make it act more like a traditional RDBMS: as a project matures, you can incrementally "lock it down".

Conceptually you can think of each row as an XML statement. For example, an employee record could be represented as:

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

This does not imply it has to be implemented as XML, it's just a handy conceptualization. If you ask for a non-existing column, such as "SELECT madeUpColumn ...", it's treated as blank or null (unless added constraints forbid such). And it's possible to use SQL, although one has to be careful about comparisons because of the implied type model. But other than type handling, users of a Dynamic Relational system would feel right at home because they can leverage most of their existing RDBMS knowledge. Now, if somebody would just build it...


In the past I've chosen option C -- Creating a 'long, narrow' table that stores dynamic column values as rows that then need to be pivoted to create a 'short, wide' rowset containing all the values for a specific entity.. However, I was using an ORM, and that REALLY made things painful. I can't think of how you'd do it in, say, LinqToSql. I guess I'd have to create a Hashtable to reference the fields.

@Skliwz: I'm guessing he's more interested in allowing users to create user-defined fields.


ElasticSearch. You should consider it especially if you're dealing with datasets that you can partition by date, you can use JSON for your data, and are not fixed on using SQL for retrieving the data.

ES infers your schema for any new JSON fields you send, either automatically, with hints, or manually which you can define/change by one HTTP command ("mappings"). Although it does not support SQL, it has some great lookup capabilities and even aggregations.


sql already provides a way to change your schema: the ALTER command.

simply have a table that lists the fields that users are not allowed to change, and write a nice interface for ALTER.

참고URL : https://stackoverflow.com/questions/66385/dynamic-database-schema

반응형