Sử dụng MongoDB và PostgreSQL cùng nhau


25

Dự án hiện tại của tôi về cơ bản là một hệ thống quản lý tài liệu nhà máy.

Điều đó nói rằng, có một số nếp nhăn (ngạc nhiên, ngạc nhiên). Mặc dù một số nếp nhăn khá cụ thể đối với dự án, tôi tin rằng có một số quan sát và câu hỏi chung được đưa ra mà không có câu trả lời chính tắc (dù sao tôi có thể tìm thấy) và có thể áp dụng cho miền vấn đề rộng hơn . Có rất nhiều ở đây và tôi không chắc nó phù hợp với định dạng Hỏi & Đáp của StackExchange nhưng tôi nghĩ đó là một câu hỏi có thể trả lời và b) không đủ cụ thể để nó có thể mang lại lợi ích cho cộng đồng. Một số cân nhắc của tôi là dành riêng cho tôi nhưng tôi nghĩ rằng câu hỏi có thể được sử dụng cho bất kỳ ai phải đối mặt với việc quyết định SQL vs NoQuery so với cả hai.

Bối cảnh:

Ứng dụng web chúng tôi đang xây dựng chứa dữ liệu có quan hệ rõ ràng về bản chất cũng như dữ liệu được định hướng theo tài liệu. Chúng tôi muốn có bánh của chúng tôi và ăn nó quá.

TL; DR: Tôi nghĩ # 5 dưới đây vượt qua bài kiểm tra mùi. Phải không Có ai có kinh nghiệm với việc tích hợp SQL và NOSQL như vậy trong một ứng dụng không? Tôi đã cố gắng liệt kê tất cả các cách tiếp cận có thể cho loại vấn đề này dưới đây. Tôi đã bỏ lỡ một sự thay thế đầy hứa hẹn?

Phức tạp:

  • Có nhiều lớp tài liệu khác nhau. Các yêu cầu đã gọi cho hàng tá tài liệu khác nhau. Con số này sẽ chỉ tăng lên. Trường hợp tốt nhất có thể là một trong đó chúng ta có thể tận dụng một ngôn ngữ cụ thể của miền, tạo mã và lược đồ linh hoạt để các chuyên gia miền có thể xử lý việc thêm các lớp tài liệu mới mà không cần sự can thiệp của các DBA hoặc lập trình viên. (Lưu ý: đã biết rằng chúng tôi đang thực hiện Quy tắc thứ mười của Greensasta )
  • Tính toàn vẹn của bài viết thành công trước đó là một yêu cầu trung tâm của dự án. Các dữ liệu sẽ được kinh doanh quan trọng. Có thể hy sinh toàn bộ ngữ nghĩa ACID trên văn bản với điều kiện là những thứ được viết thành công bằng văn bản.
  • Các tài liệu là phức tạp. Tài liệu nguyên mẫu trong trường hợp cụ thể của chúng tôi sẽ yêu cầu lưu trữ hơn 150 mẩu dữ liệu riêng biệt cho mỗi phiên bản tài liệu. Trường hợp bệnh lý có thể là một thứ tự cường độ tồi tệ hơn, nhưng chắc chắn không phải là hai.
  • Một lớp tài liệu duy nhất là một mục tiêu di động được cập nhật vào thời điểm muộn hơn.
  • Chúng tôi thích những thứ miễn phí chúng tôi nhận được từ Django khi chúng tôi nối nó vào cơ sở dữ liệu quan hệ. Chúng tôi muốn giữ các tiện ích miễn phí mà không phải quay lại hai phiên bản Django để sử dụng ngã ba django-nonrel. Việc bỏ hoàn toàn ORM tốt hơn là hạ cấp xuống 1.3.

Về cơ bản, đó là sự nhầm lẫn của dữ liệu quan hệ (công cụ ứng dụng web điển hình của bạn như người dùng, nhóm, v.v., cũng như siêu dữ liệu tài liệu mà chúng ta sẽ cần để có thể cắt và xúc xắc với các truy vấn phức tạp trong thời gian thực) và dữ liệu tài liệu (ví dụ hàng trăm trường mà chúng tôi không có hứng thú tham gia hoặc truy vấn bởi - trường hợp sử dụng duy nhất cho dữ liệu của chúng tôi sẽ là để hiển thị tài liệu duy nhất mà nó được nhập vào).

Tôi muốn thực hiện kiểm tra độ tỉnh táo (nếu bạn kiểm tra lịch sử đăng bài của mình, tôi khá rõ ràng về thực tế rằng tôi không phải là một DBA) về phương pháp ưa thích của tôi cũng như liệt kê tất cả các tùy chọn mà tôi đã gặp để giải quyết cho người khác các vấn đề tương tự rộng lớn liên quan đến cả dữ liệu quan hệ và dữ liệu không liên quan.

Đề xuất giải pháp:

1. Một bảng cho mỗi lớp tài liệu

Mỗi lớp tài liệu có bảng riêng, với các cột cho tất cả siêu dữ liệu và dữ liệu.

Ưu điểm:

  • Mô hình dữ liệu SQL tiêu chuẩn đang hoạt động.
  • Dữ liệu quan hệ được xử lý theo cách tốt nhất có thể. Chúng tôi sẽ không chuẩn hóa sau nếu chúng ta cần.
  • Giao diện quản trị tích hợp của Django thoải mái với việc xem xét các bảng này và ORM có thể sống hạnh phúc với 100% dữ liệu ngoài hộp.

Nhược điểm:

  • Cơn ác mộng bảo trì. Hàng chục (hàng trăm?) Bảng có (hàng chục?) Hàng nghìn cột.
  • Logic mức ứng dụng chịu trách nhiệm quyết định chính xác bảng nào sẽ ghi vào. Đặt tên bảng làm tham số cho một truy vấn bốc mùi.
  • Về cơ bản tất cả các thay đổi logic kinh doanh sẽ yêu cầu thay đổi lược đồ.
  • Các trường hợp bệnh lý có thể yêu cầu phân loại dữ liệu cho các biểu mẫu đơn trên nhiều bảng (xem: Số cột tối đa trong bảng PostgreQuery là bao nhiêu? ).
  • Chúng tôi có lẽ sẽ cần phải đi tìm một DBA thực sự, trung thực với Chúa, người không nghi ngờ gì sẽ kết thúc sự ghét bỏ cuộc sống và chúng tôi.

2. Mô hình hóa EAV

Chỉ có một bảng trường. Mô hình thực thể-thuộc tính-giá trị đã được hiểu rõ. Tôi đã bao gồm nó cho đầy đủ. Tôi không nghĩ rằng bất kỳ dự án mới nào được bắt đầu vào năm 2013 sẽ đi theo hướng tiếp cận EAV.

Ưu điểm:

  • Dễ dàng để mô hình.

Nhược điểm:

  • Khó truy vấn hơn.
  • Lớp DB không còn có biểu diễn thẳng cho những gì tạo thành một đối tượng cấp ứng dụng.
  • Chúng tôi sẽ mất kiểm tra ràng buộc cấp DB.
  • Số lượng hàng trên một bảng sẽ tăng nhanh gấp 100 - 1000 lần. Có khả năng điểm đau trong tương lai, hiệu suất khôn ngoan.
  • Chỉ số hạn chế có thể.
  • Lược đồ DB là vô nghĩa khi có liên quan đến ORM. Pin bao gồm các công cụ ứng dụng web được bảo tồn nhưng các mô hình dữ liệu tùy chỉnh sẽ yêu cầu truy vấn tùy chỉnh.

3. Sử dụng các trường hstore hoặc json PostgreSQL

Một trong hai loại trường này sẽ thực hiện thủ thuật lưu trữ dữ liệu schemaless trong bối cảnh của DB quan hệ. Lý do duy nhất tôi không nhảy đến giải pháp này ngay lập tức là nó là tương đối mới (giới thiệu trong phiên bản 8.4 vì vậy không mới), tôi có không tiếp xúc trước với nó và tôi nghi ngờ. Nó gây cho tôi sai vì chính xác những lý do tương tự mà tôi cảm thấy không thoải mái khi ném tất cả dữ liệu đẹp, dễ dàng chuẩn hóa của mình vào Mongo - mặc dù Mongo có thể xử lý các tài liệu tham khảo giữa các tài liệu.

Ưu điểm:

  • Chúng tôi nhận được những lợi ích của Django ORM và quản lý phiên và xác thực tích hợp.
  • Mọi thứ vẫn ở trong một phụ trợ mà trước đây chúng tôi đã sử dụng cho các dự án khác.

Nhược điểm:

  • Không có kinh nghiệm với điều này, cá nhân.
  • Nó không giống như một tính năng được sử dụng rất cao. Có vẻ như họ được đề xuất khá nhiều cho những người đang xem các giải pháp NOSQL nhưng tôi không thấy nhiều bằng chứng cho thấy họ đang được chọn. Điều này khiến tôi nghĩ rằng tôi phải thiếu một cái gì đó.
  • Tất cả các giá trị được lưu trữ là chuỗi. Mất kiểm tra ràng buộc mức DB.
  • Dữ liệu trong kho sẽ không bao giờ được hiển thị cho người dùng trừ khi họ xem cụ thể một tài liệu, nhưng siêu dữ liệu được lưu trữ trong các cột tiêu chuẩn hơn sẽ có. Chúng tôi sẽ đánh bại siêu dữ liệu đó và tôi lo rằng các cửa hàng khá lớn mà chúng tôi sẽ tạo ra có thể đi kèm với những hạn chế về hiệu suất.

4. Đi đầy đủ theo định hướng tài liệu

Tạo tất cả các tài liệu (theo nghĩa MongoDB). Tạo một bộ sưu tập loại duy nhất Documentvà gọi nó là một ngày. Mang tất cả dữ liệu ngoại vi (bao gồm cả dữ liệu trên tài khoản người dùng, nhóm, v.v.) vào mongo. Giải pháp này rõ ràng là tốt hơn so với mô hình EAV nhưng tôi cảm thấy sai vì cùng lý do # 3 cảm thấy sai - cả hai đều cảm thấy như sử dụng búa của bạn như một tuốc nơ vít.

Ưu điểm:

  • Không cần mô hình dữ liệu trả trước. Có một bộ sưu tập với các tài liệu loại Documentvà gọi nó là một ngày.
  • Được biết là đặc điểm mở rộng tốt, nên bộ sưu tập cần phát triển để bao gồm hàng triệu hoặc thậm chí hàng tỷ tài liệu.
  • Định dạng JSON (BSON) là trực quan cho các nhà phát triển.
  • Theo tôi hiểu (chỉ mơ hồ ở thời điểm này), bằng cách hoang tưởng về mức độ quan tâm đến việc viết, ngay cả một trường hợp duy nhất có thể cung cấp sự an toàn dữ liệu khá mạnh trong trường hợp xảy ra bất cứ điều gì và mọi thứ xảy ra với sự cố ổ cứng.

Nhược điểm:

  • ORM nằm ngoài cửa sổ cho thân cây Django. Các phần mềm miễn phí đi ra ngoài cửa sổ với nó: khung auth, khung phiên, giao diện quản trị, chắc chắn nhiều thứ khác.
  • Phải sử dụng các khả năng tham chiếu của mongo (yêu cầu nhiều truy vấn) hoặc không chuẩn hóa dữ liệu. Chúng tôi không chỉ mất những thứ miễn phí mà chúng tôi nhận được từ Django, chúng tôi còn mất những thứ miễn phí như THAM GIA mà chúng tôi đã được cấp trong PostgreQuery.
  • An toàn dữ liệu. Khi một người đọc về MongoDB, dường như luôn có ít nhất một người đề cập đến việc nó sẽ mất và mất dữ liệu của bạn như thế nào. Họ không bao giờ trích dẫn một sự kiện cụ thể nào và tất cả có thể chỉ là hogwash hoặc chỉ liên quan đến ngọn lửa mặc định cũ và quên mối quan tâm bằng văn bản nhưng nó vẫn làm tôi lo lắng. Tất nhiên chúng tôi sẽ sử dụng một chiến lược sao lưu khá hoang tưởng trong mọi trường hợp (nếu dữ liệu bị hỏng âm thầm cũng có thể là phi vật chất tất nhiên ..).

5. PostgreSQL và MongoDB

Dữ liệu quan hệ đi trong cơ sở dữ liệu quan hệ và dữ liệu tài liệu đi trong cơ sở dữ liệu hướng tài liệu. Các documentsbảng trên cơ sở dữ liệu quan hệ chứa tất cả các dữ liệu chúng tôi có thể cần phải chỉ mục hoặc lát và con xúc xắc trên cũng như một MongoDB ObjectId mà chúng tôi sẽ sử dụng khi chúng tôi cần phải truy vấn cho các giá trị thực tế của các trường trên tài liệu. Chúng tôi sẽ không thể sử dụng ORM hoặc quản trị viên tích hợp cho các giá trị của tài liệu nhưng điều đó không phải là mất mát lớn vì toàn bộ ứng dụng về cơ bản là giao diện quản trị cho các tài liệu và chúng tôi có thể đã phải tùy chỉnh phần cụ thể đó của ORM ở mức độ không thể chấp nhận để làm cho nó hoạt động theo cách chúng ta cần.

Ưu điểm:

  • Mỗi phụ trợ chỉ làm những gì nó giỏi.
  • Tham chiếu giữa các mô hình được bảo tồn mà không yêu cầu nhiều truy vấn.
  • Chúng tôi có thể giữ pin mà Django đã cung cấp cho chúng tôi khi có liên quan đến người dùng, phiên, v.v.
  • Chỉ cần một documentsbảng cho dù có bao nhiêu lớp tài liệu khác nhau được tạo.
  • Dữ liệu tài liệu ít được truy vấn thường được tách biệt mạnh mẽ với siêu dữ liệu được truy vấn thường xuyên hơn.

Nhược điểm:

  • Việc truy xuất dữ liệu tài liệu sẽ yêu cầu 2 truy vấn tuần tự, đầu tiên là đối với SQL DB và sau đó là MongoDB (mặc dù điều này không tệ hơn nếu cùng một dữ liệu được lưu trữ trong Mongo và không được chuẩn hóa)
  • Viết sẽ không còn là nguyên tử. Một văn bản chống lại một tài liệu Mongo duy nhất được đảm bảo là nguyên tử và PG rõ ràng có thể đảm bảo tính nguyên tử nhưng đảm bảo tính nguyên tử của văn bản trên cả hai sẽ yêu cầu logic ứng dụng, không nghi ngờ gì về hiệu suất và hình phạt phức tạp.
  • Hai phụ trợ = hai ngôn ngữ truy vấn = hai chương trình khác nhau với các yêu cầu quản trị khác nhau = hai cơ sở dữ liệu ganh đua cho bộ nhớ.

Tôi sẽ đi cho một cột với một JSONkiểu dữ liệu. Đừng sợ sử dụng các tính năng mới trong Postgres - nhóm Postgres không phát hành các tính năng không ổn định. Và 9.2 không phải là mới thực sự). Ngoài ra, bạn có thể sử dụng các tính năng JSON mới trong 9.3 khi có. Nếu bạn luôn xử lý đầy đủ các tài liệu trong mã ứng dụng của mình (thay vì sử dụng SQL), bạn cũng có thể lưu trữ JSON trong một textcột thông thường .
a_horse_with_no_name

Để người trả lời tiềm năng: xin vui lòng cung cấp một câu trả lời! Tuy nhiên, vì câu hỏi này đã tồn tại khá lâu mà không có câu trả lời "hoàn hảo", tuy nhiên, tôi dự định sẽ trả lời câu hỏi với một hậu quả đầy đủ về trải nghiệm khi chúng tôi thực hiện và chuyển sang sản xuất. Nó có thể là một năm trong tương lai, nhưng đừng lo lắng - OP sẽ giao hàng. Tôi hy vọng đó là những gì mà những người đã ủng hộ / nêu lên câu hỏi cụ thể này sẽ hữu ích nhất: xác minh rằng nó hoạt động hoặc giải thích về những gì rào cản đã giết chết tùy chọn bên cạnh.
chucksmash

2
@chucksmash. Bạn đã đi với # 5, sau khi tất cả? Làm thế nào bạn quản lý để thực hiện cả hai dbs? Những công cụ nào bạn đã sử dụng? Nếu không, tại sao?
xpanta

@chucksmash Vẫn đang chờ phản hồi mà bạn đã hứa.
Bhashit Parikh

@chucksmash OP đã không giao hàng ... :(
Albert Rothman

Câu trả lời:


13

Một vài suy nghĩ....

Thông thường, người ta không muốn lưu trữ các mẩu thông tin liên quan chặt chẽ trong các hệ thống khác nhau. Cơ hội để mọi thứ không đồng bộ là rất đáng kể và bây giờ thay vì một vấn đề trên tay bạn có hai. Một điều bạn có thể làm với Mongo là sử dụng nó để dẫn dữ liệu của bạn vào hoặc ra dữ liệu. Sở thích của tôi là giữ mọi thứ trong PostgreSQL trong phạm vi có thể. Tuy nhiên, tôi sẽ lưu ý rằng làm như vậy thực sự đòi hỏi kiến ​​thức chuyên môn về lập trình PostgreSQL và không dành cho các cửa hàng không muốn dành cho việc sử dụng các tính năng nâng cao. Tôi thấy một bộ tùy chọn hơi khác so với bạn. Vì sở thích của tôi không phải là thứ tôi thấy được liệt kê nên tôi sẽ đưa nó cho bạn.

Bạn có thể có thể tách siêu dữ liệu của bạn thành dữ liệu chung, dữ liệu cần thiết cho các lớp và dữ liệu tài liệu. Về vấn đề này, bạn sẽ có một bảng danh mục chung với thông tin chung cơ bản cộng với một bảng cho mỗi lớp. Trong bảng này, bạn sẽ có một trường hstore, json hoặc xml sẽ lưu trữ phần còn lại của dữ liệu cùng với các cột nơi bạn đang lưu trữ dữ liệu phải bị hạn chế đáng kể. Điều này sẽ làm giảm những gì bạn cần đặt trong các bảng này cho mỗi lớp, nhưng sẽ cho phép bạn tận dụng các ràng buộc theo cách bạn muốn. Ba tùy chọn có các vấn đề khác nhau và đáng để xem xét riêng:

hstore tương đối hạn chế nhưng cũng được rất nhiều người sử dụng. Nó không phải là cực kỳ mới nhưng nó chỉ là một kho lưu trữ khóa / giá trị và không có khả năng cấu trúc dữ liệu lồng nhau, không giống như json và xml.

json là khá mới và không thực sự làm rất nhiều ngay bây giờ. Điều này không có nghĩa là bạn không thể làm được gì nhiều với nó, nhưng bạn sẽ không làm được gì nhiều. Nếu bạn có thể mong đợi thực hiện một số lượng đáng kể chương trình, có thể là trong plv8js hoặc, nếu bạn muốn gắn bó với môi trường cũ hơn, plperlu hoặc plpython. jsonđược hỗ trợ tốt hơn trong 9.3 mặc dù ít nhất là trong các ảnh chụp nhanh phát triển hiện tại, vì vậy khi phiên bản đó được phát hành, mọi thứ sẽ trở nên tốt hơn.

xml là hỗ trợ tốt nhất trong ba, với nhiều tính năng nhất và lịch sử hỗ trợ lâu nhất. Sau đó, một lần nữa, nó là XML .....

Tuy nhiên, nếu bạn quyết định đồng hành cùng Mongo và PostgreSQL, lưu ý rằng PostgreQuery hỗ trợ cam kết 2 pha nghĩa là bạn có thể chạy các thao tác ghi, sau đó phát hành PREPARE TRANSACTIONvà nếu điều này thành công thì hãy viết nguyên tử của bạn bằng Mongo. Nếu điều đó thành công, bạn có thể COMMITtrong PostgreSQL.


1
Đây là tất cả những gợi ý tuyệt vời. Tôi đã đề cập đến việc sử dụng hstore / json trước đây (và đã âm thầm giảm giá xml, bởi vì, tốt, xml) nhưng tôi đã không nghĩ đến việc sử dụng chúng theo cách bạn đề xuất. Trên hết, gợi ý cam kết 2 pha của Postgres là vàng. Tôi không có ý tưởng này tồn tại. Cảm ơn vì những gợi ý tuyệt vời.
chucksmash

Cam kết 2 giai đoạn thực sự là vàng. Nó làm cho việc sử dụng một NoQuery song song rất khả thi. Đặc biệt là nếu dữ liệu giữa 2 DB chỉ liên quan đến nhau hiếm khi và chúng chủ yếu giải quyết các vấn đề khác nhau
haknick

0

Bạn có thể thiết lập một công cụ truy vấn như Presto hoặc Dremio để tham gia dữ liệu cư trú trong MongoDB và Postgres với một truy vấn duy nhất. Cả hai đều có trình kết nối cho mỗi cơ sở dữ liệu này (xem các tài liệu ở đâyở đây ) và đề xuất, tương ứng, chạy "SQL trên bất cứ thứ gì" và "tham gia bất cứ thứ gì".

Để kiểm tra Presto, bạn có thể triển khai một cụm nhỏ trên AWS EMR với Hadoop, Hive và Presto (thêm màu sắc nếu bạn không muốn sử dụng dòng lệnh), nó hoạt động từ hộp - đảm bảo làm theo các hướng dẫn sau để thiết lập các đầu nối . Hive không thực sự cần thiết, nhưng với nó, bạn có thể tạo các bảng bằng kết quả từ các phép nối giữa Mongo và Postgres (kiểm tra trang này để biết ví dụ). Ngoài ra còn có một phiên bản trả tiền trên thị trường , được cho là được tối ưu hóa mạnh mẽ và có bản dùng thử 30 ngày.

Tôi chưa sử dụng Dremio, nhưng có một vài cách dễ dàng để triển khai nó trên AWS, Azure hoặc tại cơ sở. Họ có một số khóa học trực tuyến trên trang web của họ , với quyền truy cập vào một "phòng thí nghiệm ảo" mà bạn có thể sử dụng để theo dõi các lớp học miễn phí.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.