MongoDB와 PostgreSQL을 함께 사용 문서 클래스 당 하나의 테이블 각 문서 클래스는

현재 진행중인 프로젝트는 기본적으로 밀 문서 관리 시스템입니다.

즉, 약간의 주름이 있습니다 (놀람, 놀라움). 일부 주름은 프로젝트에 따라 상당히 다르지만, 일반적인 정답이없고 (어쨌든 찾을 수 있음) 더 넓은 문제 영역에 적용 할 수있는 일반적인 관찰 및 질문이 있다고 생각합니다. . 여기에는 많은 것이 있으며 이것이 StackExchange Q & A 형식에 적합하다고 확신하지는 않지만 a) 대답 할 수있는 질문과 b) 커뮤니티에 도움이 될만큼 구체적이지 않은 것으로 생각합니다. 내 고려 사항 중 일부는 나에게 특정 적이지만 SQL 대 NoSQL 대 두 가지를 결정하는 데 어려움을 겪는 사람이라면 누구나이 질문을 사용할 수 있다고 생각합니다.

배경:

우리가 구축하는 웹 앱에는 문서 지향 데이터뿐만 아니라 본질적으로 관계가 명확한 데이터가 포함되어 있습니다. 우리는 케이크를 먹고 싶어요.

TL; DR : 아래 # 5는 냄새 테스트를 통과 한 것 같습니다. 당신 은요? 누구나 단일 응용 프로그램에서 SQL과 NOSQL의 통합에 경험이 있습니까? 이 문제 클래스에 가능한 모든 접근 방식을 아래에 나열했습니다. 유망한 대안을 놓쳤습니까?

복잡성 :

  • 여러 종류의 문서가 있습니다. 요구 사항에는 이미 수십 개의 다른 문서가 필요합니다. 이 숫자는 계속 올라갑니다. 가장 좋은 경우는 도메인 전문가가 DBA 또는 프로그래머의 개입없이 새로운 문서 클래스 추가를 처리 할 수 ​​있도록 간단한 도메인 별 언어, 코드 생성 및 유연한 스키마를 활용할 수있는 경우입니다. (참고 : 이미 Greenspun의 10 번째 규칙을 준수 하고 있음을 알고 있음 )
  • 이전의 성공적인 쓰기의 무결성은 프로젝트의 핵심 요구 사항입니다. 데이터는 비즈니스에 중요합니다. 쓰기에 대한 완전한 ACID 의미는 성공적으로 기록 된 것들이 기록 된 상태로 유지 될 경우 희생 될 수 있습니다.
  • 문서 자체는 복잡합니다. 특정 사례의 프로토 타입 문서는 문서 인스턴스 당 150 개 이상의 고유 한 데이터를 저장해야합니다. 병리학 적 사례는 수십 배 악화 될 수 있지만 확실히 두 가지는 아닙니다.
  • 단일 클래스의 문서는 나중에 업데이트 될 움직이는 대상입니다.
  • 우리는 관계형 데이터베이스에 연결할 때 장고에서 얻는 무료 자료를 좋아합니다. django-nonrel 포크를 사용하기 위해 두 장고 버전을 건너 뛰지 않고 공짜를 유지하고 싶습니다. ORM을 완전히 덤프하면 1.3으로 다운 그레이드하는 것이 좋습니다.

본질적으로 이는 관계형 데이터 (사용자, 그룹 등의 일반적인 웹 응용 프로그램뿐만 아니라 복잡한 쿼리로 실시간으로 슬라이스 및 주사위를 사용하는 데 필요한 문서 메타 데이터) 및 문서 데이터 (예 : 우리가 참여하거나 쿼리하는 데 관심이없는 수백 개의 필드-데이터의 유일한 유스 케이스는 입력 된 단일 문서를 표시하는 것입니다).

선호하는 방법에 대해 위생 검사 (내 게시 기록을 확인하는 경우 DBA가 아니라는 사실에 대해 매우 명시적임)를 수행하고 다른 해결을 위해 내가 겪은 모든 옵션을 열거하고 싶었습니다. 관계형 및 비 관계형 데이터와 관련된 광범위한 문제.

제안 된 솔루션 :

1. 문서 클래스 당 하나의 테이블

각 문서 클래스는 모든 메타 데이터 및 데이터에 대한 열이있는 자체 테이블을 가져옵니다.

장점 :

  • 표준 SQL 데이터 모델이 사용 중입니다.
  • 관계형 데이터는 최상의 방법으로 처리됩니다. 필요한 경우 나중에 비정규화할 것입니다.
  • Django의 내장 된 관리 인터페이스는 이러한 테이블을 쉽게 검사 할 수 있으며 ORM은 100 %의 데이터만으로도 행복하게 살 수 있습니다.

단점 :

  • 유지 보수의 악몽. 수천 개의 열이있는 수십 (수백?) 테이블.
  • 정확히 어떤 테이블에 쓸 것인지 결정하는 응용 프로그램 수준 논리. 테이블 이름을 쿼리의 매개 변수로 지정하면 문제가 발생합니다.
  • 기본적으로 모든 비즈니스 로직 변경에는 스키마 변경이 필요합니다.
  • 병리학 적 사례는 여러 테이블에서 단일 양식에 대한 데이터 스트라이핑이 필요할 수 있습니다 ( PostgreSQL 테이블의 최대 열 수는 얼마입니까? 참조 ).
  • 우리는 아마 삶과 우리를 미워하게 될 진정한 정직하고 신적인 DBA를 찾아야 할 것입니다.

2. EAV 모델링

필드 테이블 만 있습니다. 엔터티-특성-값 모델링은 이미 잘 알려져 있습니다. 나는 완전성을 위해 그것을 포함시켰다. 2013 년에 시작된 새로운 프로젝트가 의도적으로 EAV 접근 방식을 사용한다고 생각하지 않습니다.

장점 :

  • 모델링하기 쉽습니다.

단점 :

  • 쿼리하기가 더 어렵습니다.
  • DB 계층에는 더 이상 하나의 앱 수준 개체를 구성하는 항목에 대한 간단한 표현이 없습니다.
  • DB 수준 제약 조건 검사가 손실됩니다.
  • 한 테이블의 행 수가 100-1000 배 더 빠르게 증가합니다. 아마도 미래의 고통 지점, 성능 측면.
  • 인덱싱이 제한적입니다.
  • ORM에 관한 한 DB 스키마는 무의미합니다. 배터리에 포함 된 웹 앱은 유지되지만 사용자 지정 데이터 모델에는 사용자 지정 쿼리가 필요합니다.

3. PostgreSQL hstore 또는 json 필드 사용

이러한 필드 유형 중 하나는 관계형 DB 컨텍스트 내에서 스키마없는 데이터를 저장하는 트릭을 수행합니다. 나는이 솔루션으로 이동하지 않는 유일한 이유는 바로 (버전 8.4 그렇게하지 도입이 비교적 새로운입니다 새), 나는 그것을 제로 이전의 노출을하고 난 의심입니다. Mongo가 문서 사이의 참조를 처리 할 수는 있지만, 훌륭하고 쉽게 표준화 된 모든 데이터를 Mongo에 던지는 것이 불안하다고 느끼는 것과 똑같은 이유로 나를 잘못 생각합니다.

장점 :

  • Django ORM과 내장 된 인증 및 세션 관리의 이점을 얻습니다.
  • 모든 것이 이전에 다른 프로젝트에서 성공적으로 사용한 하나의 백엔드에 유지됩니다.

단점 :

  • 개인적으로 이것에 대한 경험이 없습니다.
  • 많이 사용되는 기능처럼 보이지 않습니다. NOSQL 솔루션을 보는 사람들에게는 꽤 권장되는 것처럼 보이지만 선택되고 있다는 증거는 많지 않습니다. 이것은 내가 뭔가를 놓치고 있어야한다고 생각하게합니다.
  • 저장된 모든 값은 문자열입니다. DB 수준 제약 조건 검사가 손실됩니다.
  • hstore의 데이터는 특별히 문서를 보지 않는 한 사용자에게 표시되지 않지만보다 표준적인 열에 저장된 메타 데이터는 표시됩니다. 우리는 그 메타 데이터를 꺾을 것이고, 우리가 만들게 될 다소 큰 hstores가 성능 결점을 초래 할까 걱정합니다.

4. 문서 중심의 전체 보어

모든 것을 문서화하십시오 (MongoDB 의미로). 단일 유형의 컬렉션을 Document만들어 하루에 호출하십시오. 모든 주변 데이터 (사용자 계정, 그룹 등의 데이터 포함)도 몽고에 가져옵니다. 이 솔루션은 분명히 EAV 모델링보다 낫지 만 # 3이 잘못 느꼈던 것과 같은 이유로 나에게 잘못 느낍니다. 둘 다 망치로 드라이버를 사용하는 것처럼 느낍니다.

장점 :

  • 데이터를 미리 모델링 할 필요가 없습니다. 유형의 문서가 포함 된 컬렉션을 하나 가지고 Document있고 하루에 전화하십시오.
  • 수백만 또는 수십억 개의 문서를 포괄하도록 컬렉션을 확장해야하는 경우 알려진 확장 특성.
  • JSON 형식 (BSON)은 개발자에게 직관적입니다.
  • 필자가 이해할 수 있듯이 (이 시점에서는 모호합니다) 쓰기 인식 수준과 관련하여 편집증을 가짐으로써 단일 인스턴스조차도 하드 드라이브 충돌에 이르기까지 모든 상황에서 매우 강력한 데이터 안전성을 제공 할 수 있습니다.

단점 :

  • ORM은 Django 트렁크의 창 밖입니다. 인증 프레임 워크, 세션 프레임 워크, 관리 인터페이스, 다른 많은 것들과 함께 창밖으로 나가는 공짜.
  • mongo의 참조 기능 (여러 쿼리가 필요함)을 사용하거나 데이터를 비정규 화해야합니다. Django에서받은 공짜를 잃을뿐만 아니라 PostgreSQL에서 당연한 JOIN과 같은 공짜도 잃습니다.
  • 데이터 안전. MongoDB에 대해 읽을 때 항상 데이터를 어떻게 잃고 잃는지를 언급하는 사람이 적어도 한 명있는 것 같습니다. 그들은 결코 특정 사건을 인용하지 않으며, 그것은 단지 호그 워시이거나 오래된 기본 화재와 관련이 있고 쓰기 염려를 잊어 버릴 수는 있지만 여전히 걱정입니다. 우리는 물론 어떤 경우에도 상당히 편집증적인 백업 전략을 이용할 것입니다 (데이터가 자동으로 손상되어 당연히 중요하지 않을 수 있습니다 ..)

5. PostgreSQL 및 MongoDB

관계형 데이터는 관계형 데이터베이스로, 문서 데이터는 문서 지향 데이터베이스로갑니다. documents관계형 데이터베이스 의 테이블에는 문서에서 필드의 실제 값을 쿼리해야 할 때 사용하는 MongoDB ObjectId뿐만 아니라 색인화 또는 슬라이스 및 주사위 분류에 필요한 모든 데이터가 포함됩니다. 문서 자체의 값으로 ORM 또는 기본 제공 관리자를 사용할 수는 없지만 전체 앱이 기본적으로 문서의 관리 인터페이스이므로 손실이 크지 않습니다. ORM의 특정 부분을 허용 할 수없는 정도로 사용자 정의하여 필요한 방식으로 작동 시키십시오.

장점 :

  • 각 백엔드는 자신이 잘하는 것만 수행합니다.
  • 여러 쿼리를 요구하지 않고 모델 간의 참조가 유지됩니다.
  • Django가 사용자, 세션 등에 관한 한 배터리를 유지합니다.
  • documents여러 클래스의 문서가 작성 되더라도 하나의 테이블 만 필요 합니다.
  • 덜 자주 쿼리되는 문서 데이터는 훨씬 더 자주 쿼리되는 메타 데이터와 크게 분리됩니다.

단점 :

  • 문서 데이터를 검색하려면 먼저 SQL DB에 대해 MongoDB에 대해 두 개의 순차적 쿼리가 필요합니다 (동일한 데이터가 Mongo에 저장되어 비정규 화되지 않은 경우보다 나쁘지는 않습니다)
  • 글쓰기는 더 이상 원자 적이 지 않습니다. 단일 Mongo 문서에 대한 쓰기는 원 자성으로 보장되며 PG는 원 자성을 보장 할 수 있지만 두 문서에서 원 자성을 보장하려면 성능과 복잡성에 대한 의심없이 응용 프로그램 논리가 필요합니다.
  • 두 개의 백엔드 = 두 개의 쿼리 언어 = 서로 다른 관리자 요구 사항을 가진 두 개의 다른 프로그램 = 메모리를 찾는 데이터베이스 두 개


답변

몇 가지 생각 ….

일반적으로 서로 밀접하게 관련된 정보를 다른 시스템에 저장하고 싶지 않습니다. 일이 동기화되지 않을 가능성은 중요하며 지금은 하나의 문제 대신 두 가지 문제가 있습니다. Mongo로 할 수있는 한 가지는 데이터를 파이프 라인하거나 파이프 라인하는 데 사용하는 것입니다. 선호하는 것은 PostgreSQL의 모든 것을 가능한 한 유지하는 것입니다. 그러나 그렇게하려면 실제로 PostgreSQL 프로그래밍에 대한 전문 지식이 필요하며 고급 기능 사용에 전념하지 않는 상점에는 적합하지 않습니다. 나는 당신과는 약간 다른 옵션을 볼 수 있습니다. 내가 선호하는 것은 내가 열거 한 것이 아니기 때문에 당신에게 줄 것입니다.

메타 데이터를 공통 데이터, 클래스에 필요한 데이터 및 문서 데이터로 분리 할 수 ​​있습니다. 이와 관련하여 기본 공통 정보와 클래스 당 하나의 테이블이있는 일반 카탈로그 테이블이 있습니다. 이 테이블에는 hstore, json 또는 xml 필드가 있습니다.이 필드에는 나머지 데이터를 저장해야하며 데이터를 저장해야하는 열과 함께 크게 제한되어야합니다. 이렇게하면 클래스별로 이러한 테이블에 넣을 필요가 줄어들지 만 원하는 제약 조건을 활용할 수 있습니다. 세 가지 옵션은 서로 다른 문제가 있으며 별도로 고려할 가치가 있습니다.

hstore 는 비교적 제한적이지만 많은 사람들이 사용합니다. 매우 새로운 것은 아니지만 키 / 값 저장소 일 뿐이며 json 및 xml과 달리 중첩 된 데이터 구조를 사용할 수 없습니다.

json 은 매우 새롭고 실제로 많은 일을하지 않습니다. 이것은 당신이 그것으로 많은 것을 할 수 없다는 것을 의미하지는 않지만, 당신은 즉시 많은 것을하지 않을 것입니다. 그렇다면 plv8js에서 또는 이전 환경, plperlu 또는 plpython에서 많은 양의 프로그래밍을 기대할 수 있습니다. json적어도 현재 개발 스냅 샷에서는 9.3에서 더 잘 지원되므로 해당 버전이 출시되면 상황이 더 좋아질 것입니다.

xml 은 가장 많은 기능과 가장 긴 지원 기록을 가진 세 가지 중에서 가장 잘 지원됩니다. 그리고 다시 XML입니다 …..

그러나 Mongo와 PostgreSQL을 함께 사용하기로 결정한 경우 PostgreSQL은 2 단계 커밋을 지원하므로 쓰기 작업을 실행할 수 있으며 발행 PREPARE TRANSACTION이 성공하면 Mongo에서 원자 쓰기가 수행됩니다. 성공하면 COMMITPostgreSQL에서 할 수 있습니다 .


답변

Presto 또는 Dremio 와 같은 쿼리 엔진을 설정하여 MongoDB 및 Postgres에있는 데이터를 단일 쿼리로 결합 할 수 있습니다. 둘 다이 데이터베이스 각각에 대한 커넥터를 갖고 있으며 ( 여기여기 문서 참조 ) 각각 “SQL on anything”및 “join anything”을 실행하도록 제안합니다.

Presto를 테스트하기 위해 Hadoop, Hive 및 Presto (명령 줄을 사용하지 않으려는 경우 색조 추가)를 사용하여 AWS EMR에 작은 클러스터를 배포 할 수 있습니다.이 기능은 상자에서 작동 합니다. 커넥터 . Hive가 꼭 필요한 것은 아니지만 Mongo와 Postgres의 조인 결과를 사용하여 테이블을 만들 수 있습니다 ( 예를 보려면 이 페이지 를 확인 하십시오 ). 마켓 플레이스 에는 유료 버전 도 있습니다.이 버전 은 (아마도) 많이 최적화되어 있으며 30 일 평가판이 있습니다.

Dremio를 사용하지는 않았지만 AWS, Azure 또는 온 프레미스에 배포하는 몇 가지 쉬운 방법이 있습니다. 그들은이 자신의 웹 사이트에 일부 온라인 과정 은 무료로 수업을 수행하는 데 사용할 수있는 “가상 실험실”에 액세스.