Truy vấn hiệu quả cho một mô hình EAV nâng cao


7

Tôi bị mắc kẹt trong cách xây dựng một truy vấn hiệu quả, trả về dữ liệu của cấu trúc EAV sau.

Ngày nay, một bảng sản phẩm đã tồn tại, chứa 4 trường cố định. Chúng tôi muốn nâng cấp hệ thống, cho phép vô số trường sản phẩm bổ sung, được xác định bởi nhà sản xuất của từng sản phẩm. Chúng tôi gọi những trường bổ sung này là 'tham số'.

Một tham số có thể thuộc loại dữ liệu sau:

  • Bản văn
  • Ngày (phạm vi)
  • Boolean
  • Dropdownvalue (đơn)
  • Dropdownvalues ​​(nhiều)

Dựa vào đó, tôi đã tạo ra mô hình cơ sở dữ liệu sau:

Sơ đồ cơ sở dữ liệu :

  • Sản phẩm : bảng sản phẩm gốc, chứa các trường cố định.
  • Tham số : bảng này xác định tất cả các loại tham số. Hiện tại 5: Văn bản, Ngày, Boolean, Giá trị thả xuống (đơn), Giá trị thả xuống (nhiều)
  • Nhà sản xuấtParameter : bảng này lưu trữ các tham số được xác định bởi nhà sản xuất sản phẩm (Bảng nhà sản xuất không có trong hình) cho tất cả các sản phẩm của mình.
  • ProductParameter : đây là nơi lưu trữ dữ liệu sản phẩm thực tế của tất cả các tham số đã xác định. Một tham số của loại 'Văn bản', lưu trữ thông tin của nó trong trường 'Văn bản', 'Ngày' trong 'DatumBegin' và 'DatumEnd', Bit / Boolean trong 'Boolean'.
  • ParameterValueListItem : bảng này chứa các giá trị được xác định trước của các giá trị Dropdownlist cho cả khớp nối đơn và ghép. Đây là những giá trị bạn có thể thấy trong Danh sách thả xuống khi tạo hoặc thay đổi sản phẩm.
  • ProductParameterValueListItem : đây là nơi dữ liệu sản phẩm thực tế được lưu trữ cho các giá trị Dropdownlist.

Tôi cần xây dựng một trang web trong ASP.NET C # hiển thị danh sách tất cả dữ liệu sản phẩm, bao gồm từng tham số được xác định với giá trị của sản phẩm đó. Tôi cần có khả năng lọc danh sách bằng cách tìm kiếm trên bất kỳ trường / tham số nào. Danh sách này cũng cần được sắp xếp trên bất kỳ trường / tham số nào.

Tôi đã cố gắng lọc danh sách bằng cách tham gia bên ngoài Sản phẩm - ProductParameter - ProductParametervalueListItem - ParameterValueListItem để có được kết quả bảng chứa tất cả dữ liệu và sau đó lọc danh sách đó bằng cách sử dụng mệnh đề động, được xây dựng và chuyển qua ứng dụng web. Điều này hoạt động khi bạn tìm kiếm trên 1 tham số nhưng khi bạn bắt đầu tìm kiếm trên nhiều tham số, bạn sẽ nhận được kết quả không chính xác vì mỗi tham số là một dòng khác nhau trong kết quả bảng và đơn giản là không có kết quả 'AND' giữa tham số A và B, bởi vì chúng không tồn tại trong cùng một bản ghi (dòng).

Bất cứ ai có thể tư vấn cho tôi làm thế nào điều này có thể đạt được? Giải pháp hoàn hảo nhất sẽ là 1 kết quả bảng, chứa tất cả dữ liệu và từng tham số được hiển thị dưới dạng một cột trong cùng một hàng sản phẩm. Đây có phải là quá phức tạp để xử lý ở cấp cơ sở dữ liệu?

Cảm ơn đã đọc đến đây. Mọi lời khuyên đều được chào đón.

Câu trả lời:


3

Trước hết, những gì bạn sắp thiết kế có lẽ là một ý tưởng RẤT xấu. Một giải pháp tốt hơn sẽ là có một lược đồ động nơi bạn thêm các bảng mới và để ứng dụng hiểu cách truy vấn các bảng đó (bạn có thể đặt chúng vào một lược đồ). Điều này phần lớn tránh tất cả các vấn đề về kế hoạch khóa và truy vấn mà bạn nhất định gặp phải với mô hình này. Không có gì sai với các ứng dụng chạy CREATE TABLEbây giờ và một lần nữa.

Thứ hai, tôi không chắc chắn tôi hiểu tại sao bạn đã bình thường hóa Parametervào bảng riêng của nó? Tại sao không đặt nó trực tiếp vào ManufacturerParameterbàn.

Thứ ba, nếu bạn khăng khăng tiến hành mô hình hiện tại của mình, có nhiều cách để đạt được những gì bạn muốn (ít nhất là nếu tôi diễn giải chính xác yêu cầu của bạn). Những gì bạn có thể làm là viết truy vấn của mình theo cách nó tổng hợp đối số tìm kiếm khi có kết quả khớp và sau đó sử dụng HAVINGđể lọc ra các giá trị khớp. Tôi giả định rằng chỉ có một trong các lĩnh vực Text, Boolean, Datumvv được dân cư mỗi ProductParameterkỷ lục (có thể bạn muốn thực hiện điều này với một hạn chế)

Ví dụ: để tìm kiếm tất cả các sản phẩm có bolean = true cho một tham số AND text = 'abc' cho một số tham số khác bạn có thể làm:

SELECT P.Name
FROM Product P
JOIN ProductParameter PP
WHERE P.ID = Foo
  AND PP.Boolean = 1 OR PP.Text = 'abc'  ... /* For each filter */
GROUP BY P.Name /* And any other things you want out of product */
HAVING COUNT(*) >= [Number of where clauses]

Nếu bạn cần liệt kê tất cả các tham số của sản phẩm này, bạn có thể sử dụng mẫu truy vấn trên làm truy vấn lồng nhau và tham gia lại ProductParameter.

Truy vấn trên CÓ THỂ được tối ưu hóa bằng cách duy trì một cột được tính toán trong ProductParameterđó có biểu diễn chuỗi của các loại dữ liệu khác nhau trong bảng đó. Bằng cách đó, các câu lệnh OR ở trên có thể được viết lại dưới dạng danh sách IN (mà bạn sẽ muốn chuyển dưới dạng tham số có giá trị bảng).

Tôi muốn nhắc lại rằng những gì bạn đang làm có lẽ rất sai. Nếu bạn làm điều đó, rất có thể bạn sẽ cần điều chỉnh hầu hết các kế hoạch truy vấn của mình - trình tối ưu hóa sẽ không giúp bạn nữa. Và đó là giả sử bạn không có quá nhiều biến thể truy vấn, sẽ chạy bộ đệm kế hoạch đầy đủ.


1

Bất cứ ai có thể tư vấn cho tôi làm thế nào điều này có thể đạt được? Giải pháp hoàn hảo nhất sẽ là 1 kết quả bảng, chứa tất cả dữ liệu và từng tham số được hiển thị dưới dạng một cột trong cùng một hàng sản phẩm. Đây có phải là quá phức tạp để xử lý ở cấp cơ sở dữ liệu?

Bạn có thể sử dụng sql động để xoay EAV vào một bảng có nhiều cột (lưu ý giới hạn cột là 1024) và đặt mỗi sản phẩm trên một hàng. Tôi không nghĩ rằng điều này sẽ thực hiện tốt như bảng được lập chỉ mục chặt chẽ, truyền thống hơn nhưng bạn có thể thử cụ thể hóa kết quả được đặt thành một bảng và đặt các chỉ mục vào đó.


Tôi đã xem xét lệnh trục trước đây nhưng tôi không thể tìm ra cách thực hiện, vì giá trị của một tham số (trường bổ sung) có thể được lưu trữ trong 3 trường khác nhau và thậm chí trong các bảng khác, tùy thuộc vào loại dữ liệu nào được chọn ( Văn bản, Ngày, Boolean, DDLValues ​​(đơn), DDLValues ​​(nhiều). Bạn có biết điều này thậm chí có thể được thực hiện với một thiết lập như thế này không?
Zeep

1
bạn có thể tạo XMLschema và lưu trữ cấu trúc giá trị trong cột XMLValue.
g2server

Tôi có một hệ thống EAV nơi chúng tôi tự động tạo các chế độ xem PIVOT, jsut như @ g2server gợi ý. Khi chúng tôi có hơn một vài triệu hàng trong bảng "giá trị", tốc độ chạy chậm khủng khiếp. Bạn không thể lập chỉ mục trực tiếp chế độ xem PIVOT để CHỌN .. INTO có thể là hy vọng tốt nhất của bạn.
Michael Green

@MichaelGreen Tôi muốn nghe một số chi tiết về điều đó. Vì vậy, CHỌN..INTO đã giảm thời gian truy vấn?
3308043

@ user3308043 - Không, thực hiện truy vấn PIVOT trên lược đồ EAV với hàng trăm thuộc tính và vài triệu hàng đã giảm thời gian truy vấn. Giải pháp là CHỌN truy vấn PIVOT này VÀO bảng "đã chuẩn hóa" trong thời gian thấp điểm, sau đó truy vấn bảng "đã chuẩn hóa" trong giờ làm việc.
Michael Green
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.