Cách tốt nhất để lưu trữ các đơn vị trong cơ sở dữ liệu


21

Tôi đã kế thừa một cơ sở dữ liệu lớn (SQLServer) với hàng trăm cột biểu thị số lượng của thứ này hay thứ khác. Đơn vị cho các giá trị này (ví dụ: "gallon", "inch", v.v.) được lưu trữ trong trường MS_Des mô tả thuộc tính mở rộng. Tôi tự hỏi nếu có một cách tốt hơn để lưu trữ thông tin này. Tôi cho rằng nó ổn cho mục đích tài liệu, nhưng sẽ khó thực hiện các tính toán chuyển đổi đơn vị mạnh mẽ dựa trên dữ liệu này. Tại thời điểm này tôi chưa sẵn sàng để thực hiện một thay đổi xâm lấn, nhưng nếu tôi có cơ hội để làm như vậy, thực tiễn tốt nhất được đề xuất trong vấn đề này là gì? Các tùy chọn, ngoài đỉnh đầu của tôi, có thể bao gồm:

  • Thay đổi tên cột thành các đơn vị được bao gồm (ví dụ: "TotalVolumeInGallons". Điều này sẽ làm cho thông tin có sẵn hơn một chút, nhưng nó vẫn có vẻ yếu đối với tôi.)
  • Thêm một cột "Đơn vị" riêng biệt để tương ứng với mỗi cột "Số tiền" (cột này có thể là nvarchar HOẶC nó có thể là khóa ngoại cho bảng Đơn vị riêng biệt giúp tính toán chuyển đổi đơn vị dễ dàng hơn. Mặt khác, thêm vào nhiều cột có thể tăng gấp đôi kích thước cơ sở dữ liệu của tôi - với dữ liệu dư thừa khủng khiếp.)
  • Tạo một trường mới trong Thuộc tính mở rộng dành riêng cho các đơn vị. (Thật không may, tôi không nghĩ rằng đây có thể là khóa ngoại đối với bảng Đơn vị.)
  • Có một ý tưởng khác mà tôi đang xem?

CẬP NHẬT: Sau khi đọc câu trả lời của @Todd Everett, một giải pháp khả thi đã xảy ra với tôi, vì vậy tôi sẽ tiếp tục và trả lời câu hỏi của riêng tôi. (Xem bên dưới)


Thực hành tốt nhất là có một hệ thống đo lường duy nhất được sử dụng phổ biến và nhất quán trong suốt ứng dụng. SI sẽ là hệ thống của sự lựa chọn. Các giá trị trong các hệ thống khác sẽ được chuyển đổi trong khi tải hoặc trong lớp trình bày, trong đó mỗi người dùng có thể chọn bộ ưu tiên của mình.
Michael Green

Câu trả lời:


12

Vì bạn đề cập đến hàng trăm cột, tôi sẽ xem xét thiết kế EAV . Trong khi Joe Celko cảnh báo chống lại điều này , tôi nghĩ nó có thể được áp dụng trong trường hợp sử dụng của bạn. Nghe có vẻ như tất cả "số tiền" của bạn là số, vì vậy bạn sẽ tránh được các vấn đề truyền mà Joe mô tả và cần phải biến mọi "giá trị" thành một chuỗi. Nó sẽ hoạt động tốt hơn nữa nếu tất cả các số tiền là số nguyên, nhưng cũng có thể hoạt động nếu một số là số thập phân. Đưa ra Đơn vị đo lường, bạn có thể tiến thêm một bước và triển khai mô hình kiểu "mô hình dữ liệu phổ quát" dựa trên bài viết này của David Hay và cũng được nêu trong cuốn sách Mô hình mô hình dữ liệu: Quy ước về suy nghĩ. Mô hình này có lợi thế bổ sung là cấu hình "số tiền" nào áp dụng cho "thứ" nào nếu bạn cần. Một bước bổ sung được hiển thị trong sách ở trang 162 là bảng Đơn vị chuyển đổi số đo mà bạn có thể sử dụng để chuyển đổi giữa các Đơn vị đo lường khác nhau. Đây là một ví dụ:

UOM Conversion              

UOM From    UOM To        Cal Step  Operator Factor Constant
Kilograms   Pounds        1         *        2.2
Celsius     Fahrenheit    1         *        1.8
Celsius     Fahrenheit    2         +               32

Điều này nói rằng để chuyển đổi từ Kg sang Lb, bước đầu tiên là nhân Kg với 2.2. Ngoài ra còn có một hằng số nếu một chuyển đổi cũng phải bao gồm một giá trị không đổi và khả năng tạo nhiều bước. Vì vậy, khi chuyển đổi, hãy nói Celsius thành Fahrenheit, bạn nhân Celsius với 1.8 và sau đó thêm 32. Khóa sẽ là từ UOM, sang UOM và Bước tính toán.

Đó là giá trị 2 xu của tôi. Tôi hy vọng những tài liệu tham khảo này cung cấp cho bạn một số thực phẩm tốt để suy nghĩ nếu bạn có cơ hội thực hiện khởi động lại trên thiết kế hiện tại.


Cảm ơn về một số thực phẩm rất thú vị cho suy nghĩ - tôi đã học được rất nhiều. Tuy nhiên, tôi không nghĩ EAV là mô hình phù hợp trong trường hợp của tôi (nếu tôi hiểu chính xác đề xuất của bạn) bởi vì, mặc dù chúng tôi có 100 cột, nhưng chúng không có nghĩa là thưa thớt. Tuy nhiên, DID này gợi lên một ý tưởng liên quan (xem CẬP NHẬT trong bài viết gốc của tôi).
kmote

Ý tưởng của bạn nghe có vẻ khá tốt đối với tôi - Tôi không thể nghĩ ra bất kỳ vấn đề nào với nó ngoài những gì bạn đã chỉ ra. Nhưng nếu các cột có thể được đổi tên / thay đổi thì đó sẽ là một vấn đề trong bất kỳ thiết kế nào. Đây là khi sự hợp tác trở nên thú vị - một ý tưởng xuất hiện mà không ai trong chúng ta nghĩ đến để bắt đầu!
Todd Everett

8

Tất cả công việc.

Lưu ý rằng trong trường hợp thứ hai, bạn không thể thêm táo và cam, và do đó dữ liệu đặc biệt dễ bị giải thích sai.

Cũng lưu ý rằng chuyển đổi không thể rất an toàn và dễ bị lỗi làm tròn, tràn, v.v.

Ngoài ra, có những vấn đề vật lý như trọng lượng và nhiệt độ cụ thể. Chuyển đổi 20 gallon nước sang pound sẽ đòi hỏi bạn phải biết mật độ của nước. Nhưng mật độ của nước thay đổi theo nhiệt độ, do đó bạn có thể cần phải biết mật độ đồng thời với phép đo hoặc nhiệt độ tương tự và sử dụng hệ số hiệu chỉnh âm lượng.

Trong trường hợp thuộc tính Mở rộng, điều đó chỉ tốt cho tài liệu - một tên cột tốt sẽ tốt hơn cho tài liệu. Vấn đề với cột ngụ ý là ở một đơn vị cố định theo tên là cuối cùng bạn sẽ đặt mình vào một góc khi bạn thay đổi đơn vị đo lường - khách hàng mới muốn dầu trong thùng chứ không phải gallon - và điều đó sẽ ổn vì dữ liệu của họ được đưa vào cơ sở dữ liệu riêng của nó, nhưng tên cột hiện đang gây hiểu nhầm.

Một lựa chọn khác là lưu trữ các phiên bản chính tắc trong các đơn vị cố định (nghĩa là luôn luôn là kilôgam và mét) ngoài các phép đo ban đầu khác nhau. Các thao tác tổng hợp trên các đơn vị cố định sẽ ổn (ví dụ: ngoại trừ bạn sẽ không thêm nhiệt độ), nhưng bạn không bị mất số đo ban đầu.


1
"Giải thích sai" tiềm năng mà bạn đề cập chính xác là một trong những mối quan tâm của tôi về kiến ​​trúc hiện tại của cơ sở dữ liệu này - và một cái gì đó tôi đang cố gắng tìm cách giảm bớt.
kmote

1
điểm tuyệt vời về nhược điểm tiềm năng của giải pháp tên cột.
kmote

1
@kmote Đây không phải là vấn đề đơn giản - chúng tôi có báo cáo trong đó các giao dịch riêng lẻ có thể có các đơn vị đo lường ban đầu khác nhau, nhưng cũng có tổng số - là tổng số sau khi chuyển đổi sang đơn vị do người dùng chọn.
Cade Roux

7

Một giải pháp đơn giản đã hoạt động tốt với tôi trong quá khứ là lưu trữ tất cả dữ liệu của bạn trong các đơn vị 'cơ sở'. Ví dụ: đơn vị cơ sở của bạn cho chiều dài có thể là milimet và đơn vị cơ sở của bạn cho trọng lượng có thể là kilôgam. Giải pháp này có thể dẫn đến nhu cầu chuyển đổi một số dữ liệu hiện có của bạn thành đơn vị cơ sở, nếu chưa có.

Khi bạn có tất cả dữ liệu trong các đơn vị cơ sở tiêu chuẩn, không cần lưu trữ đơn vị trong cơ sở dữ liệu, vì giờ đây nó là một giả định trên toàn hệ thống. Các đơn vị được hiển thị cần thiết cho từng loại đơn vị (ví dụ: có hiển thị mm, inch, cm, m theo chiều dài không) trở thành vấn đề miền ứng dụng / máy khách, có thể được lưu vào bộ nhớ cục bộ.

Các bảng chuyển đổi đơn vị để chuyển đổi giữa các đơn vị được hỗ trợ khác nhau có thể được mã hóa cứng trong ứng dụng của bạn, vì các đơn vị đo lường mới thay đổi rất hiếm khi.

Lưu ý một giải pháp liên quan đến một vấn đề khác là khi lưu trữ dấu thời gian trong cơ sở dữ liệu để luôn lưu trữ chúng trong đơn vị 'cơ sở' - UTC .

Một câu hỏi và trả lời liên quan khác về chủ đề ...


5

Vì bất kỳ đơn vị nào cũng có thể được chuyển đổi sang đơn vị khác cùng loại Với công thức:

y = ((x + xOffset) * multiplicand / denominator) + yOffset

Tôi sẽ tạo một bảng chứa các loại đơn vị cộng với 4 giá trị này.

From Unit     To Unit      Unit Type    From Offset    Multiplicand    Denominator    To Offset
'milligrams'  'grams'      'mass'       0              1               1000           0
'grams'      'kilograms'   'mass'       0              1               1000           0
'grams'      'ounces'      'mass'       0              100000          2835           0
'ounces'     'pound'       'mass'       0              1               16             0

Sau khi đã thêm tất cả các phép đo mà bạn có khả năng chuyển đổi sang và ở hai bên của danh sách, hãy chạy Truy vấn nơi bạn chèn thao tác nghịch đảo bằng cách đơn giản phủ định các độ lệch và hoán đổi bội số và mẫu số và Đơn vị Đến và Đơn vị.

Để thêm Chuyển đổi giữa tất cả các loại, tham gia chéo Với một số bộ lọc có thể chèn Chuyển đổi còn lại.


3

Sau khi đọc câu trả lời của @Todd Everett, một giải pháp đã xảy ra với tôi, vì vậy tôi sẽ tiếp tục và trả lời câu hỏi của riêng tôi. Những gì tôi nghĩ rằng tôi sẽ làm là để tạo ra một riêng biệt ColumnUnitsbảng, với bốn cột: Schema, Table, Column, UnitsID(nơi UnitsID là FK đến một riêng biệt UnitsOfMeasurebảng), do đó việc lập bản đồ bất kỳ cột trao cho đơn vị liên quan của Measure. Rõ ràng nhược điểm lớn nhất của ý tưởng này là các nhà phát triển sẽ phải nhớ chỉnh sửa bảng này bất cứ khi nào họ đổi tên cột hoặc bảng [ có thể sử dụng trình kích hoạt DDL ? ], nếu không hệ thống sẽ bị hỏng. Nhưng giả sử những sự đổi mới như vậy là rất hiếm, và nhà phát triển nhỏ (chỉ một người, trong trường hợp của tôi), kiến ​​trúc này sẽ hoàn toàn khả thi. Ưu điểm là không có thay đổi xâm lấn nào đối với DB hiện tại và tôi chỉ phải lưu trữ giá trị một lần cho mỗi cột, thay vì một lần mỗi hàng như tùy chọn thứ hai trong bài đăng gốc của tôi sẽ yêu cầu.


câu đố thú vị ... và ý tưởng thú vị mà bạn có. ý tưởng của bạn sẽ làm cho nó dễ dàng hơn để truy vấn, nhưng dường như không đạt được nhiều. bạn vừa chuyển dữ liệu tham chiếu đến một nơi khác. điều làm tôi bực mình nhất về thiết kế này
Ngài Swears-a-lot

... là nếu một mục có nhiều thuộc tính hơn, bạn vẫn cần thêm nhiều cột hơn. Vì lý do đó, tôi thích đề xuất của @todd everett về một thiết kế eav.
Ngài Swears-a-lot
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.