Các thực thể lồng nhau và tính toán trên thuộc tính thực thể lá - Cách tiếp cận SQL hoặc NoQuery


10

Tôi đang làm việc trong một dự án sở thích có tên Menu / Recipe Management.

Đây là cách các thực thể của tôi và mối quan hệ của họ trông như thế nào.

A Nutrientcó tính chất CodeValue

An Ingredientcó một bộ sưu tậpNutrients

A Recipecó Bộ sưu tập Ingredientsvà đôi khi có thể có bộ sưu tập khácrecipes

A Mealcó Bộ sưu tập RecipesIngredients

A Menucó Bộ sưu tậpMeals

Các mối quan hệ có thể được mô tả như là

Thực thể và mối quan hệ

Trong một trong các trang, đối với menu đã chọn, tôi cần hiển thị thông tin chất dinh dưỡng hiệu quả được tính dựa trên thành phần của nó (Bữa ăn, Bí quyết, Thành phần và các chất dinh dưỡng tương ứng).

Hiện tại tôi đang sử dụng SQL Server để lưu trữ dữ liệu và tôi đang điều hướng chuỗi từ mã C # của mình, bắt đầu từ mỗi bữa ăn của menu và sau đó tổng hợp các giá trị dinh dưỡng.

Tôi nghĩ rằng đây không phải là một cách hiệu quả vì việc tính toán này được thực hiện mỗi khi trang được yêu cầu và các thành phần thỉnh thoảng thay đổi.

Tôi đã suy nghĩ về việc có một dịch vụ nền duy trì một bảng gọi là MenuNutrients ( {MenuId, NutrientId, Value}) và sẽ đưa vào / cập nhật bảng này các chất dinh dưỡng hiệu quả khi bất kỳ thành phần nào (Bữa ăn, Công thức, Thành phần) thay đổi.

Tôi cảm thấy rằng một GraphDB sẽ phù hợp với yêu cầu này, nhưng khả năng tiếp xúc với NoQuery của tôi bị hạn chế.

Tôi muốn biết các giải pháp / cách tiếp cận thay thế cho yêu cầu này là hiển thị các chất dinh dưỡng của một menu nhất định.

Hy vọng mô tả của tôi về kịch bản là rõ ràng.


Có bao nhiêu đối tượng chúng ta đang nói chuyện? Hiệu suất sẽ thực sự là một vấn đề?
flup

@flup Trung bình một Menu có thể có 8 bữa, mỗi bữa có thể có 2 công thức và 2 nguyên liệu, mỗi công thức có thể có 6-8 thành phần.
Chandu

Mũi tên của bạn không đúng hướng?
Branko Dimitrijevic

Bạn đã xem mẫu Nerd Dinner Entity Framework chưa?
Akash Kava

Câu trả lời:


8

Dựa trên các yêu cầu và kiến ​​trúc, có thể có các tùy chọn cải tiến hiệu suất:

  • Bạn có thể sử dụng các khung nhìn được lập chỉ mục (matrialized) Để cải thiện hiệu suất đọc ở cấp độ RDBMS (máy chủ Sql).
    Về cơ bản, tất cả những gì bạn cần làm là:
    Tạo chế độ xem thông thường.
    Tạo một chỉ mục cụm trên quan điểm đó .

  • Sử dụng cơ chế rút tiền ở cấp ứng dụng sẽ cải thiện hiệu suất.
    Nếu có thể và khả thi để sử dụng tiền mặt, có một chiến lược tiền mặt như rút tiền mặt đơn lẻ sẽ giúp bạn.

NoSql:
Có rất nhiều bài viết hay về Sql vs NoSql, như thế nàyphần này

Các phần tôi quan tâm:

Sử dụng NoSql ở đâu:

Nếu DB của bạn là 3NF và bạn không tham gia (bạn chỉ cần chọn một loạt các bảng và đặt tất cả các đối tượng lại với nhau, AKA là điều mà hầu hết mọi người làm trong một ứng dụng web.

Khi sử dụng hãy sẵn sàng để:

  • Bạn kết thúc công việc viết để làm những việc như tham gia dữ liệu từ các bảng / bộ sưu tập khác nhau, một việc mà RDBMS sẽ tự động làm cho bạn.
  • Khả năng truy vấn của bạn với NoQuery bị tê liệt nghiêm trọng. MongoDb có thể là thứ gần gũi nhất với SQL nhưng nó vẫn còn rất xa. Tin tôi đi Các truy vấn SQL là siêu trực quan, linh hoạt và mạnh mẽ. Các truy vấn NoSql thì không.
  • Các truy vấn MongoDb có thể truy xuất dữ liệu từ chỉ một bộ sưu tập và chỉ tận dụng một chỉ mục. Và MongoDb có lẽ là một trong những cơ sở dữ liệu NoQuery linh hoạt nhất. Trong nhiều tình huống, điều này có nghĩa là nhiều chuyến đi khứ hồi đến máy chủ để tìm các bản ghi liên quan. Và sau đó bạn bắt đầu khử chuẩn hóa dữ liệu - có nghĩa là các công việc nền.
  • Thực tế rằng nó không phải là một cơ sở dữ liệu quan hệ có nghĩa là bạn sẽ không có (ràng buộc bởi một số người thực hiện kém) các ràng buộc khóa ngoại để đảm bảo dữ liệu của bạn nhất quán. Tôi đảm bảo với bạn rằng điều này cuối cùng sẽ tạo ra sự không nhất quán dữ liệu trong cơ sở dữ liệu của bạn. Được chuẩn bị. Nhiều khả năng bạn sẽ bắt đầu viết các quy trình hoặc kiểm tra để giữ cho cơ sở dữ liệu của bạn nhất quán, điều này có thể sẽ không hoạt động tốt hơn là để RDBMS làm điều đó cho bạn.
  • Hãy quên đi các khung trưởng thành như ngủ đông.

Bên cạnh quyết định sử dụng hoặc không sử dụng NoSQL, một bài báo hữu ích về NoSQL DBMS So sánh và ý định của họ có thể được tìm thấy ở đây là một số trong số họ đang tập trung vào cao đọc, viết thấp, map-giảm, HA ...
Có một cái nhìn tại bảng xếp hạng và mức độ phổ biến của chúng , theo thể loại có thể hữu ích.


Cảm ơn các chi tiết. Sẽ kiểm tra các liên kết và lấy lại cho bạn.
Chandu

3

Tôi thực sự bạn không cần sử dụng db biểu đồ, chỉ cần lưu trữ các giá trị bắt buộc ở một mức cao hơn. Nó giống như lưu trữ một OrderOrderItems. bạn không phải tính tổng mỗi lần đơn hàng sắp được hiển thị. Thay vào đó, bạn chỉ cần tính tổng, thùng và các thứ khác và lưu trữ chúng với của bạn Order.

order.Subtotal = order.Items.Sum(item => item.Price);
order.Tax = order.Subtotal * 0.25m; // just a value
order.Total = order.Subtotal + order.Tax;

// fast forward time
var subTotal = order.Items.Sum(item => item.Price);
var tax = subTotal * 0.25m;
var total = subTotal + tax;

if (toal == order.Total) {
   Console.Log("Why the hell I've just re-calculated total?");
}

3

Tôi đề nghị xem xét mẫu Phân chia trách nhiệm truy vấn lệnh .

Về cơ bản thay vì tạo một mô hình duy nhất để đọc và viết, bạn có thể tạo 2 mô hình khác nhau. Một cái được tối ưu hóa để cập nhật và cái khác được tối ưu hóa cho các truy vấn (đọc, báo cáo, ...). Hai mô hình được đồng bộ hóa (thường có tính nhất quán cuối cùng) bằng cách sử dụng các sự kiện miền (xem DDD).

Tôi đã bắt đầu nghiên cứu mô hình này vài tháng trước và nó thực sự đã thay đổi cách mô hình hóa phần mềm của tôi. Nó không phải là dễ dàng bởi vì nó là một sự thay đổi lớn, đặc biệt là khi được sử dụng với các kỹ thuật khác như DDD và Tìm nguồn sự kiện. Nhưng cho giá trị nó.

Có rất nhiều tài nguyên có sẵn trên mạng, tìm kiếm CQRS và DDD (và cuối cùng là Tìm nguồn sự kiện).

Mẫu này có thể được sử dụng trên cả SQL và noSql.

Trong trường hợp của bạn, bạn có thể kích hoạt một sự kiện mỗi khi các chất dinh dưỡng được thay đổi để cập nhật mô hình đọc được tối ưu hóa để đọc. Mô hình đọc có thể là ví dụ về chế độ xem không chuẩn hóa các chất dinh dưỡng của menu (tại sao không sử dụng db nosql để đọc hiệu quả). Bạn có thể có nhiều mô hình đọc dựa trên các truy vấn mà bạn cần thực hiện.

Có một số hàm ý sử dụng phương pháp này nhưng nó rất có thể mở rộng và mở rộng.


Đây là cách tiếp cận tôi đang suy nghĩ, nhưng không chắc chắn về cách lấy dữ liệu cho mô hình đọc (về cơ bản một số quy trình sẽ giúp tôi lấy dữ liệu cho mô hình đọc).
Chandu

Thông thường mô hình đọc được cập nhật tại mỗi thay đổi. Bạn nên thực hiện ui với các lệnh (dựa trên tác vụ) thay vì sử dụng các thao tác crud. Theo cách này, mỗi lệnh đơn được phản ánh đến mô hình đọc. Bạn không cần phải thực hiện các truy vấn khác. Các lệnh thiết kế cho phép hệ thống nắm bắt được ý định thực sự của người dùng.

2

Nó phụ thuộc rất nhiều vào cách bạn làm để có được thực đơn và các chất dinh dưỡng ban đầu. Tại sao bạn nghĩ rằng nó sẽ không hiệu quả?

Theo những gì tôi hiểu, bạn vào DB, lấy menu, rồi lại đi, lấy từng công thức, rồi lại đi và lấy từng thành phần, v.v. Điều này thực sự không hiệu quả, vì có rất nhiều truy vấn và các chuyến đi khứ hồi đến máy chủ, đây là nguồn chính của sự chậm trễ. Điều này được gọi là vấn đề CHỌN N + 1.

Những gì bạn nên làm là tìm nạp tất cả dữ liệu trong một truy vấn duy nhất, bằng cách sử dụng JOINs cho tất cả các bảng từ menu cho đến các chất dinh dưỡng, để máy chủ DB có thể sử dụng tất cả các mối quan hệ và chỉ mục để lấy dữ liệu cùng một lúc. Ứng dụng khách C # chỉ xử lý và hiển thị kết quả cuối cùng. Làm như vậy sẽ hiệu quả hơn nhiều so với việc đi từng người một.

Nói chung, bằng cách sử dụng các kỹ thuật truy vấn phù hợp và các chỉ mục phù hợp cho các truy vấn quan trọng, cơ sở dữ liệu quan hệ có thể thực hiện rất tốt trên các bảng lớn đang tải.


Cảm ơn, tôi hiểu rằng nó phụ thuộc vào các tham gia. Vì các thành phần của menu thỉnh thoảng thay đổi, tôi không muốn chạy phép tính mỗi khi có ai đó truy cập trang. Thay vào đó tôi muốn một dịch vụ nền để thực hiện phép tính và tôi có thể chỉ cần đọc nó ra khỏi bảng khi cần. Vấn đề với tính toán là xác định toàn bộ chuỗi khi một trong các thành phần thay đổi.
Chandu

Chỉ tìm kiếm một vài mối quan hệ không phát sinh trong bất kỳ tính toán nào, ngay cả khi có 5 hoặc 6 JOINgiây không phải là gánh nặng trên máy chủ (trừ khi chúng ta đang nói về việc tìm nạp hàng trăm hoặc hàng nghìn), nếu lập chỉ mục đúng đang ở Ngay cả với các tập dữ liệu lớn, bạn luôn có thể xây dựng chế độ xem trên toàn bộ kết quả và thậm chí lập chỉ mục cho chế độ xem có kết quả được tính toán trước, nếu hiệu suất trở thành vấn đề.

2

Có vẻ như bạn đã dành thời gian suy nghĩ về cách tốt nhất để mô hình hóa dữ liệu để có thể dễ dàng cập nhật và truy vấn. Tuy nhiên, bây giờ bạn đang ở thời điểm mà bạn cần cung cấp quyền truy cập vào dữ liệu. Hai điều đó là mối quan tâm riêng biệt.

Bạn đề cập đến việc tải lại trang đang gây ra một truy vấn mới cho cơ sở dữ liệu. Bạn cũng đề cập rằng cơ sở dữ liệu đôi khi sẽ được cập nhật và khi nào bạn muốn những cập nhật đó được hiển thị kịp thời trên trang. Phương pháp tốt nhất của bạn để giảm chi phí truy vấn là không thực hiện chúng. Nếu bạn đang chạy cùng một truy vấn nhiều lần và nhận được cùng một kết quả, tại sao không lưu trữ chúng trong một thời gian? Bạn sẽ có thể thực hiện một số bộ nhớ đệm ngược dòng mà không sửa đổi phần còn lại của dự án. Tôi khuyên bạn nên đọc về phần còn lại. Bất kể nếu bạn triển khai dự án trong một vấn đề rdbms hoặc nosql với hiệu suất của loại này được xử lý tốt nhất bằng cách giảm số lần bạn phải truy cập cơ sở dữ liệu. Giả sử bạn có 100 yêu cầu cho cùng một công thức trong 60 giây. Nếu bạn lưu trong 60 giây thì bạn chỉ truy cập cơ sở dữ liệu một lần để cải thiện hiệu suất 100 lần. Để thấy rằng mức độ cải thiện tương tự bằng cách chuyển sang nosql sẽ đòi hỏi nhiều công việc hơn.

Các hệ thống loại Nosql có thể là một giải pháp tuyệt vời khi bạn có lượng dữ liệu khổng lồ hoặc yêu cầu tốc độ đọc hoặc ghi cực cao. Tuy nhiên, hiệu suất bổ sung đi kèm với chi phí loại bỏ những thứ như tính toàn vẹn tham chiếu.


1

Có vẻ như đối với mục đích thử nghiệm hoặc kiến ​​thức mà bạn muốn dùng thử Graph-DB nhưng ví dụ của bạn rõ ràng là một ví dụ về dữ liệu phân cấp trong đó chúng ta có thể truy sâu / lên thông qua một nút. Tôi không phải là chuyên gia về Graph / Neo DB nhưng tôi có thể thấy không có nhiều phức tạp trong cách người dùng / bạn có thể yêu cầu dữ liệu từ lược đồ này. Tôi thấy sự lựa chọn của thiết kế cơ sở dữ liệu / lược đồ rất phụ thuộc vào cách thức và loại dữ liệu sẽ được truy vấn đối với nó. Khi bạn sử dụng SQLSERVER "HVELyI" D là tùy chọn tốt nhất theo quan điểm của tôi để đặt các nút này như một phần của Tree.


1

Đề nghị của tôi là suy nghĩ như một cái máy và không giống như một con người. Nó có vẻ lặp đi lặp lại, nhưng những gì máy móc là tốt. Một điều mà bạn phải tự hỏi mình là "dù sao tôi cũng phải truy xuất mọi đối tượng để hiển thị trên trang của mình?" Nếu có, tiếp tục những gì bạn đang làm, so với truy xuất dữ liệu, chu kỳ cpu là không đáng kể khi làm toán đơn giản.

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.