2012-06-11 66 views
5

Chúng tôi có một yêu cầu trong ứng dụng của chúng tôi, nơi chúng tôi cần lưu trữ tài liệu tham khảo để truy cập sau này.Cơ sở dữ liệu Lịch sử

Ví dụ: Người dùng có thể cam kết hóa đơn tại một thời điểm và tất cả các tham chiếu (địa chỉ khách hàng, số tiền tính toán, mô tả sản phẩm) mà hóa đơn này chứa và tính toán phải được lưu trữ theo thời gian.

Chúng tôi cần giữ các tham chiếu bằng cách nào đó nhưng điều gì sẽ xảy ra nếu ví dụ: tên sản phẩm thay đổi? Vì vậy, bằng cách nào đó chúng ta cần phải sao chép tất cả mọi thứ để tài liệu của nó cho sau này và không bị ảnh hưởng bởi những thay đổi trong tương lai. Ngay cả khi sản phẩm bị xóa, chúng cần được xem xét sau khi hóa đơn được lưu trữ.

Thực tiễn tốt nhất ở đây liên quan đến thiết kế cơ sở dữ liệu là gì? Ngay cả cách tiếp cận linh hoạt nhất là gì khi người dùng muốn chỉnh sửa hóa đơn của mình sau và khôi phục hóa đơn từ db?

Cảm ơn bạn!

Trả lời

9

Dưới đây là một cách để làm điều đó:

enter image description here

Về cơ bản, chúng tôi không bao giờ sửa đổi hoặc xóa các dữ liệu hiện có. Chúng tôi "sửa đổi" bằng cách tạo phiên bản mới. Chúng tôi "xóa" nó bằng cách thiết lập cờ DELETED.

Ví dụ:

  • Nếu sản phẩm thay đổi giá cả, chúng ta chèn một hàng mới vào PRODUCT_VERSION trong khi đơn đặt hàng cũ được lưu giữ kết nối với PRODUCT_VERSION cũ và mức giá cũ.
  • Khi người mua thay đổi địa chỉ, chúng tôi chỉ cần chèn một hàng mới trong CUSTOMER_VERSION và liên kết các đơn hàng mới với điều đó, trong khi vẫn giữ các đơn đặt hàng cũ được liên kết với phiên bản cũ.
  • Nếu sản phẩm bị xóa, chúng tôi không thực sự xóa nó - chúng tôi chỉ cần đặt cờ PRODUCT.DELETED, vì vậy tất cả các đơn đặt hàng được tạo cho sản phẩm đó trong cơ sở dữ liệu sẽ được lưu lại trong cơ sở dữ liệu.
  • Nếu khách hàng bị xóa (ví dụ: do (s) anh ta yêu cầu không được đăng ký), hãy đặt cờ CUSTOMER.DELETED.

Hãy cẩn thận:

  • Nếu tên sản phẩm cần phải là duy nhất, mà không thể được áp dụng khai báo trong mô hình trên. Bạn sẽ cần phải "quảng cáo" NAME từ PRODUCT_VERSION thành PRODUCT, biến nó thành khóa và khả năng từ bỏ khả năng "phát triển" tên sản phẩm hoặc thực thi tính duy nhất trên chỉ PRODUCT_VER mới nhất (có thể thông qua trình kích hoạt).
  • Có vấn đề tiềm ẩn với quyền riêng tư của khách hàng. Nếu một khách hàng bị xóa khỏi hệ thống, nó có thể được mong muốn để loại bỏ dữ liệu vật lý của nó từ cơ sở dữ liệu và chỉ cần thiết lập CUSTOMER.DELETED sẽ không làm điều đó. Nếu đó là mối quan tâm, hãy xóa dữ liệu nhạy cảm về bảo mật trong tất cả các phiên bản của khách hàng hoặc ngắt kết nối các đơn đặt hàng hiện tại khỏi khách hàng thực và kết nối lại với khách hàng "ẩn danh" đặc biệt, sau đó xóa tất cả các phiên bản của khách hàng.

Mô hình này sử dụng nhiều mối quan hệ xác định. Điều này dẫn đến các khóa ngoài "béo" và có thể là một vấn đề về lưu trữ vì MySQL không hỗ trợ nén chỉ mục hàng đầu (không giống như Oracle), nhưng mặt khác là InnoDB always clusters the data trên PK và nhóm này có thể mang lại lợi ích cho hiệu suất. Ngoài ra, JOINs là ít cần thiết.

mô hình tương đương với các mối quan hệ-xác định không và các phím thay thế sẽ trông như thế này:

enter image description here

+0

Để có tên sản phẩm duy nhất, bạn có thể thêm bảng chỉ có tên sản phẩm, trong đó tên là pk và liên kết đến bảng đó từ PRODUCT_VERSION –

+0

@OweJessen Chắc chắn bạn có thể có bảng LATEST_PRODUCT_VERSION với NAME duy nhất, nhưng điều đó không được tính là giải pháp "khai báo", vì bạn sẽ cần phải chèn và xóa hàng theo cách thủ công trong bảng đó khi các phiên bản sản phẩm mới được tạo. Trừ khi bạn đang sử dụng một DBMS mà cả hai có thể tự động cập nhật các khung nhìn vật chất và thực thi tính duy nhất trên chúng (chẳng hạn như các khung nhìn được lập chỉ mục của MS SQL Server), do đó DBMS tự duy trì LATEST_PRODUCT_VERSION cho bạn. –

1

Bạn có thể thêm một cột trong bảng sản phẩm cho biết nó có đang được bán hay không. Sau đó, khi sản phẩm bị "xóa", bạn chỉ cần đặt cờ để nó không còn có sẵn dưới dạng sản phẩm mới nữa, nhưng bạn giữ lại dữ liệu để tra cứu trong tương lai.

Để xử lý các thay đổi về tên, bạn nên sử dụng ID để tham chiếu đến sản phẩm thay vì sử dụng tên trực tiếp.

+0

Đó là điểm thứ hai sẽ không giúp anh ta nếu anh ta muốn lịch sử bao gồm tên sản phẩm vì nó là khi nó được đã bán. Nói ItemId tương tự áp dụng cho "Coke" cho đến năm 1988 và sau đó là "Coke Classic" sau đó, và anh ta muốn biết rằng nó được gọi là "Coke" trên các đơn đặt hàng cũ hơn. Đề xuất của bạn là những gì anh ta đang cố gắng tránh - bất kỳ báo cáo nào anh ta tạo ra bằng cách sử dụng dữ liệu chuẩn hóa sẽ hiển thị "Coke Classic" trên tất cả các đơn đặt hàng, trước năm 1988 hay không. – David

+0

True .. một cách để đối phó với điều đó là tạo một sản phẩm mới cho các thay đổi tên hoặc thêm một bảng khác để theo dõi tên sản phẩm (các giải pháp tiếp cận giải pháp của @Branko Dimitrijevic). – whrrgarbl

1

Sự cố bạn đang gặp phải, như tôi chắc chắn bạn biết, là kết quả của việc chuẩn hóa cơ sở dữ liệu. Một trong những cách tiếp cận để giải quyết vấn đề này có thể được lấy từ các kỹ thuật Kinh doanh thông minh - lưu trữ trạng thái không chuẩn hóa dữ liệu trong một số Data Warehouse.

bình thường hóa dữ liệu:

  • Orders bảng
    • OrderId
    • ID khách hàng
  • Khách hàng Bảng
    • ID khách hàng
    • FirstName
    • vv
  • Items bảng
    • ItemID
    • ITEMNAME
    • ItemPrice
  • OrderDetails Bảng
    • ItemDetailId
    • OrderId
    • ItemID
    • ItemQty
    • vv

Khi truy vấn và lưu trữ de-bình thường, bảng kho dữ liệu trông giống như

  • OrderId
  • ID khách hàng
  • CustomerName
  • CustomerAddress
  • (khách hàng khác Fields)
  • ItemDetailId
  • ItemID
  • ITEMNAME
  • ItemPrice
  • (Khác OrderDetail và Khoản Fields)

Điển hình, có hoặc một số loại của công việc đã lên lịch để lấy dữ liệu từ các dữ liệu chuẩn hóa vào Kho dữ liệu theo cơ sở được lập biểu, HOẶC nếu de của bạn dấu hiệu cho phép, nó có thể được thực hiện khi một đơn đặt hàng đạt đến một trạng thái nhất định. (Chẳng hạn như được vận chuyển) Có thể là các bản ghi được lưu trữ ở mỗi thay đổi trạng thái (với một trường có tên là OrderStatus đang kiểm tra trạng thái hiện tại), vì vậy dữ liệu được chuẩn hóa hoàn toàn có sẵn cho mỗi bước của quy trình làm việc/thực hiện. Thời gian và cách thức lưu trữ dữ liệu vào kho sẽ khác nhau tùy theo nhu cầu của bạn.


Có rất nhiều chi phí liên quan đến ở trên, nhưng cách tiếp cận chung khác mà tôi biết là mang nhiều chi phí hơn.

Cách tiếp cận khác sẽ là làm cho bảng chỉ đọc.Nếu khách hàng muốn thay đổi địa chỉ của họ, bạn không chỉnh sửa địa chỉ hiện tại của họ, bạn chèn một bản ghi mới.

Vì vậy, nếu địa chỉ của tôi là AddressId 12 khi tôi đặt hàng đầu tiên trên trang web của bạn trong Jamnuary, thì tôi chuyển vào ngày 4 tháng 7, tôi sẽ nhận được một AddressId mới gắn với tài khoản của mình. (Nói AddressId 123123 vì trang web của bạn rất thành công và đã thu hút được rất nhiều khách hàng.)

Đơn đặt hàng trước khi ngày 4 tháng 7 sẽ có AddressId 12 liên kết với họ và đơn đặt hàng vào hoặc sau ngày 4 tháng 7 có AddressId 123123.

Lặp lại mẫu đó với mọi bảng cần giữ lại dữ liệu lịch sử.


Tôi có cách tiếp cận thứ ba nhưng việc tìm kiếm rất khó. Tôi sử dụng nó trong một ứng dụng duy nhất, và nó thực sự hoạt động khá tốt trong trường hợp duy nhất này, trong đó có một số nhu cầu kinh doanh khá cụ thể để xây dựng lại dữ liệu chính xác như ở một thời điểm cụ thể. Tôi sẽ không sử dụng nó trừ khi tôi có nhu cầu kinh doanh tương tự.

Ở trạng thái cụ thể, hãy tuần tự hóa dữ liệu vào tài liệu Xml hoặc một số tài liệu khác mà bạn có thể sử dụng để tạo lại dữ liệu. Điều này cho phép bạn lưu các dữ liệu như nó đã được tại thời điểm nó đã được tuần tự, giữ lại cấu trúc bảng ban đầu và relaitons.

+0

vâng .... những gì @David Stratton nói ... loại bỏ câu trả lời thông tục hơn của tôi về cùng một ý tưởng. – GDP

+0

@Greg P ​​- Tôi sẽ bầu bạn. Câu trả lời của bạn ngắn gọn hơn và vẫn có liên quan. – David

+0

Thêm nó trở lại cho hậu thế ... không muốn được lặp đi lặp lại khi có một câu trả lời ngắn gọn hơn, cảm ơn mặc dù. – GDP

1

Bạn đã mở ra một cuộc tranh luận đời đời giữa cách tiếp cận thuần túy và thực tế.

Từ quan điểm bình thường hóa của cơ sở dữ liệu của bạn, bạn nên "giữ" tất cả dữ liệu có liên quan. Nói cách khác, hãy nói tên sản phẩm thay đổi, lưu ngày thay đổi để bạn có thể quay ngược thời gian và xây dựng lại hóa đơn của mình với tên sản phẩm đó và tất cả dữ liệu khác như đã tồn tại vào ngày đó.

Cách tiếp cận chuẩn hóa "de" là xem hóa đơn đó là "thời điểm trong thời gian", ghi lại trong dữ liệu bảng có liên quan thực sự là ngày đó. Cách tiếp cận này cho phép bạn kéo lên hóa đơn đó mà không có bất kỳ sự phụ thuộc nào, nhưng bạn không bao giờ có thể tạo lại hóa đơn đó từ đầu.

0

Khi bạn có dữ liệu nhạy cảm về thời gian, bạn sử dụng những thứ như bảng sản phẩm và khách hàng dưới dạng bảng tra cứu và lưu trữ thông tin trực tiếp trong các bảng Đơn đặt hàng/đơn đặt hàng.

Vì vậy, bảng thứ tự có thể chứa tên và địa chỉ của khách hàng, chi tiết có chứa tất cả thông tin liên quan về produtct bao gồm giá đặc biệt (bạn không bao giờ muốn dựa vào bảng sản phẩm để biết thông tin về giá vượt quá thời gian tra cứu mệnh lệnh).

Đây không phải là không chuẩn hóa, dữ liệu thay đổi theo thời gian nhưng bạn cần giá trị lịch sử, vì vậy bạn phải lưu trữ tại thời điểm bản ghi được tạo hoặc bạn sẽ mất dữ liệu intergrity. Bạn không muốn báo cáo tài chính của bạn đột nhiên cho biết bạn đã bán được 30% vào năm ngoái vì bạn có cập nhật giá. Đó không phải là những gì bạn bán.

+1

"Đây không phải là không chuẩn hóa ..." Đúng vậy. Trong các hệ thống quan hệ, dữ liệu trùng lặp có nghĩa là "cùng một giá trị với cùng một nghĩa". Ở đây, các giá trị có thể giống nhau, nhưng ý nghĩa thì khác. (Giá hiện tại, ví dụ, so với giá tại thời điểm đặt hàng.) –

Các vấn đề liên quan