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à 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 Document
và 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
Document
và 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 documents
bả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
documents
bả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ớ.
JSON
kiể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ộttext
cột thông thường .