Giao dịch đa tài liệu mongodb

THAM GIA trong MongoDB rất dễ bị phá vỡ (khi mọi thứ thay đổi, các chương trình ứng dụng phải được mã hóa lại) và thông thường thì MongoDB có hiệu suất thấp hơn nhiều so với Postgres. Bài viết sẽ chia thành từng phần giúp chúng ta có cái nhìn tổng quan nhất về MongoDB và PostgreSQL hỗ trợ THAM GIA như thế nào và giải thích tại sao THAM GIA trong MongoDB lại sẽ bị phá vỡ, cuối cùng là xem xét hiệu quả của THAM GIA trong cả hai

Xuyên suốt bài viết, chúng ta sẽ sử dụng ví dụ phổ biến. nhân viên (nhân viên) và phòng ban (bộ phận) với lược đồ quan hệ như sau.

Giao dịch đa tài liệu mongodb

Chu Thị Thơm @ThomDua

Theo dõi

1. 4K 26 30

Đã đăng vào ngày 22 tháng 5 năm 2020 3. 38 CH 12 phút đọc

1. 1k

0

1

So sánh THAM GIA trong MongoDB và PostgreSQL

  • Report
  • Add to series of me

Bài đăng này đã không được cập nhật trong 2 năm

THAM GIA trong MongoDB rất dễ bị phá vỡ (khi mọi thứ thay đổi, các chương trình ứng dụng phải được mã hóa lại) và thông thường thì MongoDB có hiệu suất thấp hơn nhiều so với Postgres. Bài viết sẽ chia thành từng phần giúp chúng ta có cái nhìn tổng quan nhất về MongoDB và PostgreSQL hỗ trợ THAM GIA như thế nào và giải thích tại sao THAM GIA trong MongoDB lại sẽ bị phá vỡ, cuối cùng là xem xét hiệu quả của THAM GIA trong cả hai

Xuyên suốt bài viết, chúng ta sẽ sử dụng ví dụ phổ biến. nhân viên (nhân viên) và phòng ban (bộ phận) với lược đồ quan hệ như sau. Quan hệ giữa nhân viên và bộ phận ở đây là 1-N (1-nhiều).

Nhưng sẽ có thời điểm nào đó, người quản lý có thể phân nhân viên Hóa đơn để làm việc giữa nhiều bộ phận. Quan hệ giữa nhân viên và bộ phận bây giờ là N-N (nhiều-nhiều). Như vậy, lược đồ quan hệ bên trên không hợp lệ và dữ liệu phải được thay đổi. Add a new works_in table with the fields_pct để chỉ ra thời gian phân chia hóa đơn giữa các bộ phận.

THAM GIA trong MongoDB

Trong MongoDB, có hai cách chính để thể hiện mối quan hệ là "embedded" và "reference". Sử dụng "embedded", phải quyết định tài liệu nào là "outer", tài liệu nào là "inner". Thông thường, những tài liệu được ưa thích sẽ được đặt là "bên ngoài". Trong ngữ cảnh bài viết, nhân viên được đặt làm "bên ngoài"

{
    "_id": "1",
    "ename": "Bill",
    "age": 36,
    "salary": 10000,
    "department": {
        "dname": "Shoe",
        "floor": 1,
        "budget": 1200
    }
}

Nói cách khác, thông tin của bộ phận được lưu bên trong mỗi tài liệu của nhân viên. Về cơ bản, đây là một biểu tượng "nội tuyến". Trong các tài liệu ứng dụng, biểu diễn này có thể có ý nghĩa, những dữ liệu trong đó có cấu trúc, nó có hai điểm yếu

  • Thứ nhất, bộ phận thông tin được lặp lại cho từng nhân viên trong bộ phận

Vì Bill và Fred đều ở bộ phận Giày nên thông tin bộ phận này sẽ bị lặp lại. Khi thông tin Giày được cập nhật, giả sử dụng ngân sách được điều chỉnh, tất cả các bản sao phải được tìm thấy và cập nhật chính xác. Nếu ngay cả khi một bản sao bị hủy bỏ, thì kết quả cơ sở dữ liệu sẽ không được chấp nhận nhất (bị hỏng). Hơn nữa, hoạt động cập nhật nhiều bản ghi này không phải là nguyên tử (theo mặc định của MongoDB); . 0+ giao dịch nhiều tài liệu, nhưng điều kiện này có một số giới hạn chế độ và phải chịu áp lực về hiệu suất. Trường hợp đầu tiên, khả năng cơ sở dữ liệu sẽ bị hỏng, còn trường hợp thứ hai, hiệu suất sẽ kém hơn. Và chắc chắn rằng một trong hai trường hợp này sẽ xảy ra

  • Thứ hai, không có chỗ nào để đặt thông tin của Candy, vì hiện tại không có nhân viên nào trong bộ phận này

Do hai giới hạn chế độ này, chúng tôi sẽ không xem xét biểu hiện này trong bài viết

Các biểu tượng thay thế là "tham khảo". Trong trường hợp này, bản ghi của Hóa đơn sẽ được lưu trữ dưới dạng

{
    "_id": "1",
    "ename": "Bill",
    "age": 36,
    "salary": 10000,
    "department": "1001"
}

và sẽ có một bộ phận tài liệu riêng biệt để lưu trữ các thuộc tính của các bộ phận

{
    "_id": "1001",
    "dname": "Shoe",
    "floor": 1,
    "budget": 1200
}

Về hiệu quả, biểu diễn này trông rất giống với biểu diễn quan hệ trong lược đồ đầu tiên. Tuy nhiên, nhà phát triển phải biết bộ phận trường tham chiếu đến một tài liệu trong bộ sưu tập bộ phận. Nói cách khác, không có khái niệm về ngoại lệ để hỗ trợ trong việc chỉ định THAM GIA

Bây giờ giả sử sử quản lý quyết định nhân viên có thể phân chia thời gian làm việc của họ giữa nhiều bộ phận. Không có tiêu chuẩn để biểu diễn ngữ cảnh này, nhưng thông thường, một mảng tham chiếu sẽ được sử dụng

Để ghi lại thông tin về cống hiến_pct trong một bộ phận nhất định, chúng ta có thể chuyển đổi trường bộ phận thành một mảng (bộ sưu tập) các đối tượng, bao gồm cả tham chiếu đến bộ sưu tập bộ phận và bộ phận cống hiến_pct. Ví dụ, Hóa đơn nhân viên

bộ phận thu tiền

{
    "_id": "1001",
    "dname": "Shoe",
    "floor": 1,
    "budget": 1200
},
{
    "_id": "1002",
    "dname": "Toy",
    "floor": 2,
    "budget": 1400
}

nhân viên thu tiền

{
    "_id": "1",
    "ename": "Bill",
    "age": 36,
    "salary": 10000,
    "departments": [
      { "dept": "1002", "dedication_pct": 60 },
      { "dept": "1001", "dedication_pct": 40 }
    ]
}

Khi muốn có được các thông tin liên quan, quản lý có thể THAM GIA thủ công trong ứng dụng (dễ bị lỗi và khó cho nhà phát triển) hoặc sử dụng $lookup (có giới hạn riêng, ví dụ:. can't $lookup from sharded collection or can not supports RIGHT or FULL OUTER JOINS 'kết nối'

THAM GIA trong Postgres

Về lý thuyết, có thể sử dụng một biểu diễn được nhúng trong Postgres và kiểu dữ liệu jsonb Postgres cho phép điều này. Tuy nhiên, rất lạ khi thấy trong thực tế vì những nhược điểm đã nêu ở trên. Thay vào đó, thường sử dụng biểu tượng trong lược đồ đầu tiên, tương ứng với "tham chiếu" trong MongoDB

Sử dụng SQL thông thường, có thể tìm thấy danh sách tất cả các bộ phận và tổng lương của nhân viên của họ theo mô hình dữ liệu của sơ đồ lược đồ đầu tiên như.

Khi nhân viên có thể làm việc trong nhiều bộ phận, người ta thường sử dụng biểu diễn trong Lược đồ thứ 2. Truy vấn trên có thể dễ dàng chuyển đổi thành. Lưu ý rằng chỉ cần thêm cống hiến_pct vào mệnh đề tổng hợp và thay thế nhân viên bằng công việc_in thay đổi thuộc tính trong điều kiện THAM GIA để chuyển từ THAM GIA đầu tiên sang thứ hai.

THAM GIA dễ dàng bị phá vỡ trong MongoDB

Bây giờ hãy xem lại trường hợp của dữ liệu trong Lược đồ đầu tiên, JOIN giữa các nhân viên và các bộ phận là 1-N. Để xây dựng một tài liệu chứa tổng lương cho từng bộ phận, trong MongoDB là

db.employee.aggregate([
  {
    $lookup: {
      from: "department",
      localField: "department",
      foreignField: "_id",
      as: "dept"
    }
  },
  {
    $unwind: "$dept"
  },
  {
    $group: {
      "_id": "$dept.dname",
      "salary": { "$sum": "$salary" },
    }
  }
]);

Kết quả,

{ "_id" : "Shoe", "totalsalary" : 22000 }
{ "_id" : "Toy", "totalsalary" : 15000 }

Chúng ta có thể thấy mã này phức tạp hơn nhiều so với mã trong Postgres, vì MongoDB không có khái niệm THAM GIA quan hệ và là một ngôn ngữ cấp thấp hơn SQL. Ngoài ra, nó yêu cầu nhà phát triển phải xây dựng một thuật toán cho việc truy vấn THAM GIA

Trong trường hợp này, kết hợp $unwind, $lookup và $group để truy vấn thông tin mong muốn. Đáng sợ hơn, khi chúng ta chuyển sang ngữ cảnh của Lược đồ thứ hai, (thêm lĩnh vực cống hiến_pct), mã truy vấn THAM GIA trong MongoDB phải viết lại khá nhiều

db.employee.aggregate([
  {
    $unwind: "$departments"
  },
  {
    $project: {
      "_id": 0,
      "salary": 1,
      "department": "$departments.dept",
      "dedication_pct": "$departments.dedication_pct"
    }
  },
  {
    $lookup:
    {
      from: "department",
      localField: "department",
      foreignField: "_id",
      as: "dept"
    }
  },
  {
    $unwind: "$dept"
  },
  
  {
    $group:
    {
      _id: "$dept.dname",
      totalsalary: { $sum: { $multiply: [ "$salary", "$dedication_pct", 0.01 ] } }
    }
  }
]);

Kết quả,

________số 8_______

Do đó, khi thay đổi ngữ cảnh của THAM GIA từ 1-N sang N-N, ứng dụng phải được viết lại đáng kể. Ngược lại, trong Postgres, các truy vấn vẫn gần như không thay đổi và đơn giản

Tuy nhiên, tất cả các kết quả trước đây đều có chút sai lệch, do bộ phận Candy không có nhân viên và không xuất hiện trong JOIN

Giả sử , quản lý thực sự muốn xem cả ba bộ phận với tổng lương của họ. Nói cách khác, quản lý mong muốn được nhìn thấy bộ phận Kẹo với tổng lương bằng 0 ngoài hai bộ phận còn lại. Trong Postgres, điều này chỉ cần thay đổi đơn giản cho truy vấn, cụ thể là thêm RIGHT OUTER JOIN vào bộ phận bảng.

Tuy nhiên, trong MongoDB không hỗ trợ cho phép kết nối RIGHT OUTER JOIN. Do đó, cần phải thêm "0" thủ công. Tất nhiên, đây là gánh nặng cho các nhà phát triển và cồng kềnh dễ bị lỗi

Các RDBMS có thể hiển thị tính năng độc lập dữ liệu vượt trội so với các giải pháp cấp thấp hơn như MongoDB. Bởi vì cơ sở dữ liệu tồn tại trong thời gian rất dài và ngữ cảnh có thể được thay đổi theo thời gian, tính độc lập dữ liệu vượt trội là một tính năng rất đáng mong đợi, có trong Postgres nhưng không có trong MongoDB. Vì vậy, THAM GIA trong MongoDB rất dễ bị phá vỡ

So sánh hiệu năng của PostgreSQL với MongoDB

Trong phần này, chúng ta xem xét hiệu suất của hai truy vấn trong phần trước, cụ thể là tìm tổng lương của từng bộ phận, có hoặc không có bộ phận không có nhân viên

Tất cả các mã nguồn trong phần này đều có ở đây, bạn đọc quan tâm có thể tìm thấy dữ liệu tổng hợp trong Postgres, sau đó sử dụng hàm JSON của Postgres để xuất dữ liệu theo định dạng phù hợp để nhập vào Mongo. Sau đó, chúng ta chạy hai truy vấn trên cả hai tập dữ liệu và so sánh thời gian thực hiện

Điểm chuẩn được thử nghiệm trên AWS, sử dụng phiên bản EC2 i3. xlarge (4 nhân, RAM 32GB), bộ định dạng cục bộ trên đĩa NVMe được định dạng bằng XFS. Điều chỉnh cơ bản được thực hiện trên ví dụ Postgres và những điều tốt nhất về sản xuất Mongo đã vượt qua. Điểm chuẩn được thực hiện bằng cách sử dụng 4000 bộ phận ghi chép và 20 triệu nhân viên, với một nhân viên được phân định công việc nhiều nhất giữa một và ba bộ phận. Kích thước dữ liệu là 6,1 GB ở Postgres và 1,6 GB ở Mongo (sử dụng nén mặc định). Tổng thời gian thực hiện được hiển thị trong các bảng dưới đây. MongoDB chậm hơn 130 lần so với Postgres vì ​​cách JOIN duy nhất là nhân viên lặp lại cho mỗi lần thực hiện tra cứu trong bảng bộ phận. Ngược lại, Postgres có thể sử dụng cách này (được gọi là thay thế lặp) cũng như hợp nhất THAM GIA và băm THAM GIA, và trình tối ưu hóa truy vấn Postgres sẽ chọn cách tốt nhất. MongoDB bị hạn chế trong một cách duy nhất. Bất kể khi nào (và hầu như luôn luôn như vậy) cách duy nhất này kém hơn thì sẽ dẫn đến hiệu suất kém.

Thay đổi cách thực hiện truy vấn MongoDB hoặc cấu trúc lại cơ sở dữ liệu (và yêu cầu đó phải viết lại tất cả các truy vấn) hoặc triển khai trình tối ưu hóa truy vấn trong ứng dụng (đây là một công việc rất lớn