2010-10-06 43 views
114

Một số đồng nghiệp và tôi đã tham gia vào một cuộc tranh luận về cách tốt nhất để lưu trữ dữ liệu lịch sử. Hiện tại, đối với một số hệ thống, tôi sử dụng một bảng riêng để lưu trữ dữ liệu lịch sử và tôi giữ một bảng gốc cho bản ghi hiện tại, đang hoạt động. Vì vậy, giả sử tôi có bảng FOO. Theo hệ thống của tôi, tất cả các bản ghi hoạt động sẽ đi vào FOO, và tất cả các bản ghi lịch sử sẽ đi vào FOO_Hist. Nhiều lĩnh vực khác nhau trong FOO có thể được cập nhật bởi người dùng, vì vậy tôi muốn giữ một tài khoản chính xác về mọi thứ được cập nhật. FOO_Hist giữ các trường giống hệt như FOO ngoại trừ một HIST_ID tăng tự động. Mỗi lần FOO được cập nhật, tôi thực hiện một câu lệnh chèn vào FOO_Hist tương tự như: insert into FOO_HIST select * from FOO where id = @id.Cách lưu trữ dữ liệu lịch sử

Đồng nghiệp của tôi nói rằng đây là thiết kế tồi vì tôi không nên sao chép chính xác một bảng vì lý do lịch sử và chỉ nên chèn một bản ghi khác vào bảng đang hoạt động với cờ cho biết đó là mục đích lịch sử.

Có tiêu chuẩn để xử lý lưu trữ dữ liệu lịch sử không? Dường như với tôi rằng tôi không muốn làm lộn xộn hồ sơ tích cực của mình với tất cả hồ sơ lịch sử của tôi trong cùng một bảng cho rằng nó có thể là hơn một triệu hồ sơ (tôi đang suy nghĩ lâu dài).

Bạn hoặc công ty của bạn xử lý việc này như thế nào?

Tôi đang sử dụng MS SQL Server 2008, nhưng tôi muốn giữ câu trả lời chung chung và tùy ý của bất kỳ DBMS nào.

Trả lời

50

Hỗ trợ dữ liệu lịch sử trực tiếp trong hệ điều hành sẽ làm cho ứng dụng của bạn phức tạp hơn nhiều so với nếu không. Nói chung, tôi sẽ không khuyên bạn nên làm điều đó trừ khi bạn có một yêu cầu khó khăn để thao tác các phiên bản lịch sử của một bản ghi trong hệ thống.

Nếu bạn nhìn kỹ, hầu hết các yêu cầu về dữ liệu lịch sử rơi vào một trong hai loại:

  • Audit logging: Đây là khấm khá hơn được thực hiện với các bảng kiểm toán. Thật dễ dàng để viết một công cụ tạo ra các kịch bản lệnh để tạo các bảng nhật ký kiểm tra và các trình kích hoạt bằng cách đọc siêu dữ liệu từ từ điển dữ liệu hệ thống. Đây là loại công cụ có thể được sử dụng để trang bị thêm kiểm tra đăng nhập vào hầu hết các hệ thống. Bạn cũng có thể sử dụng hệ thống con này để thay đổi dữ liệu chụp nếu bạn muốn triển khai kho dữ liệu (xem bên dưới).

  • Báo cáo lịch sử: Báo cáo về trạng thái lịch sử, 'as-at' vị trí hoặc báo cáo phân tích theo thời gian. Có thể thực hiện các yêu cầu báo cáo lịch sử đơn giản bằng cách kiểm tra các bảng ghi nhật ký kiểm toán của loại được mô tả ở trên. Nếu bạn có các yêu cầu phức tạp hơn thì có thể tiết kiệm hơn để triển khai một siêu thị dữ liệu cho báo cáo hơn là thử và tích hợp lịch sử trực tiếp vào hệ điều hành.

    Các thứ nguyên thay đổi chậm là cơ chế đơn giản nhất để theo dõi và truy vấn trạng thái lịch sử và phần lớn theo dõi lịch sử có thể được tự động hóa. Các trình xử lý chung không khó để viết.Nói chung, báo cáo lịch sử không phải sử dụng dữ liệu cập nhật từng phút, do đó, cơ chế làm mới theo đợt thường là tốt. Điều này giúp kiến ​​trúc hệ thống cốt lõi và báo cáo của bạn tương đối đơn giản.

Nếu yêu cầu của bạn thuộc một trong hai danh mục này, bạn có thể không lưu trữ dữ liệu lịch sử trong hệ điều hành của mình. Việc tách chức năng lịch sử thành một hệ thống con khác có thể sẽ ít nỗ lực hơn và tạo ra cơ sở dữ liệu giao dịch và kiểm toán/báo cáo hoạt động tốt hơn cho mục đích dự định của chúng.

+0

Tôi nghĩ rằng tôi thấy những gì bạn đang nói. Vì vậy, những gì tôi đã làm với bảng FOO_Hist của tôi đã thực sự tạo ra một bảng kiểm toán. Thay vì sử dụng trình kích hoạt để chèn vào bảng kiểm tra khi cập nhật, tôi chỉ chạy một câu lệnh trong chương trình. Đúng không? – Aaron

+4

Khá nhiều. Tuy nhiên, tốt hơn nên thực hiện việc ghi nhật ký kiểm tra này bằng trình kích hoạt; trình kích hoạt đảm bảo rằng mọi thay đổi (bao gồm sửa lỗi dữ liệu thủ công) đều được ghi lại trong nhật ký kiểm tra. Nếu bạn có nhiều hơn 10-20 bảng để kiểm tra thì có lẽ nhanh hơn tất cả để xây dựng công cụ trình tạo trình kích hoạt. Nếu lưu lượng đĩa cho các nhật ký kiểm tra là một vấn đề bạn có thể đặt các bảng nhật ký kiểm tra trên một bộ đĩa riêng biệt. – ConcernedOfTunbridgeWells

+0

Có, tôi 100% đồng ý với điều đó. Cảm ơn bạn. – Aaron

0

Bạn chỉ có thể phân vùng các bảng không?

"Bảng phân vùng và chiến lược chỉ mục sử dụng SQL Server 2008 Khi bảng cơ sở dữ liệu có kích thước lớn hơn hàng trăm gigabyte, có thể trở nên khó tải dữ liệu mới, xóa dữ liệu cũ và duy trì chỉ mục. Mặc dù dữ liệu phải được nạp hoặc loại bỏ có thể rất lớn, làm cho các thao tác INSERT và DELETE trên bảng không thực tế. Phần mềm cơ sở dữ liệu Microsoft SQL Server 2008 cung cấp phân vùng bảng để thực hiện hoạt động dễ quản lý hơn. "

+0

Có, tôi có thể phân đoạn bảng, nhưng đó có phải là tiêu chuẩn khi xử lý dữ liệu lịch sử không? Dữ liệu lịch sử có nên được bao gồm trong cùng một bảng với dữ liệu hoạt động không? Đây là những câu hỏi mà tôi muốn thảo luận. Điều này cũng không phải là tùy ý vì nó liên quan đến SQL Server 2008. – Aaron

24

Tôi không nghĩ rằng có một cách tiêu chuẩn cụ thể để làm điều đó nhưng tôi nghĩ tôi sẽ ném vào một phương pháp có thể. Tôi làm việc trong Oracle và khung ứng dụng web nội bộ của chúng tôi sử dụng XML để lưu trữ dữ liệu ứng dụng.

Chúng tôi sử dụng một cái gì đó gọi là Thạc sĩ - mô hình chi tiết mà lúc đó là đơn giản nhất bao gồm:

Thạc sĩ Bảng ví dụ gọi Widgets thường chỉ chứa một ID. Thường sẽ chứa dữ liệu không thay đổi theo thời gian/không phải là lịch sử.

chi tiết/Lịch sử Bảng ví dụ gọi Widget_Details chứa ít nhất:

  • ID - khóa chính. Xem chi tiết/ID lịch sử
  • MASTER_ID - ví dụ trong trường hợp này gọi là 'WIDGET_ID', đây là FK vào hồ sơ Thạc sĩ
  • START_DATETIME - timestamp cho thấy sự khởi đầu của mà hàng cơ sở dữ liệu
  • END_DATETIME - timestamp cho thấy sự kết thúc hàng cơ sở dữ liệu đó
  • STATUS_CONTROL - cột đơn char cho biết trạng thái của hàng. 'C' cho biết hiện tại, NULL hoặc 'A' sẽ là lịch sử/được lưu trữ. Chúng tôi chỉ sử dụng điều này bởi vì chúng ta không thể chỉ mục trên END_DATETIME là NULL
  • CREATED_BY_WUA_ID - cửa hàng ID của tài khoản đó gây ra hàng để được tạo
  • xmlData - lưu trữ các dữ liệu thực tế

Vì vậy, về cơ bản, một thực thể bắt đầu bằng việc có 1 hàng trong chủ và 1 hàng trong chi tiết. Các chi tiết có ngày kết thúc NULL và STATUS_CONTROL của 'C'. Khi cập nhật xảy ra, hàng hiện tại được cập nhật để có END_DATETIME của thời gian hiện tại và status_control được đặt thành NULL (hoặc 'A' nếu được ưu tiên). Một hàng mới được tạo trong bảng chi tiết, vẫn được liên kết với cùng một master, với status_control 'C', id của người thực hiện cập nhật và dữ liệu mới được lưu trữ trong cột XMLDATA.

Đây là cơ sở của mô hình lịch sử của chúng tôi. Logic Tạo/Cập nhật được xử lý trong một gói Oracle PL/SQL, do đó bạn chỉ cần chuyển hàm ID hiện tại, ID người dùng và dữ liệu XML mới của bạn và nội bộ nó thực hiện tất cả việc cập nhật/chèn các hàng để thể hiện điều đó trong mô hình lịch sử . Thời gian bắt đầu và kết thúc cho biết thời điểm hàng trong bảng đang hoạt động.

Bộ nhớ có giá rẻ, chúng tôi thường không xóa dữ liệu và muốn giữ đường mòn kiểm tra. Điều này cho phép chúng tôi xem dữ liệu của chúng tôi trông như thế nào tại bất kỳ thời điểm nào. Bằng cách lập chỉ mục status_control = 'C' hoặc sử dụng Chế độ xem, sự lộn xộn không chính xác là một vấn đề. Rõ ràng các truy vấn của bạn cần phải tính đến bạn nên luôn sử dụng phiên bản hiện tại (NULL end_datetime và status_control = 'C') của một bản ghi.

+0

Xin chào Chris, nếu bạn làm như vậy, ID (khóa chính) phải thay đổi phải không? làm thế nào về quan hệ với một bảng khác nếu nó được sử dụng bởi những cái khác? – projo

+0

@projo ID trên bảng chính của bạn là PK và khái niệm "PK" cho bất kỳ khái niệm nào bạn đang xử lý. ID trên bảng chi tiết là PK để xác định một phiên bản lịch sử cho bản gốc (đó là một cột khác về chi tiết). Khi tạo mối quan hệ, bạn thường tham chiếu đến PK thực sự của khái niệm (ví dụ: ID trên bảng chính hoặc cột MASTER_ID trên chi tiết của bạn) và sử dụng STATUS_CONTROL = 'C' để đảm bảo bạn đang nhận phiên bản hiện tại. Hoặc bạn có thể tham khảo ID chi tiết để liên kết một cái gì đó với một thời điểm cụ thể. –

+0

+1 Tôi đã thực hiện mô hình này với thành công lớn trên một số dự án lớn. –

7

Tôi nghĩ rằng cách tiếp cận của bạn là chính xác. Bảng lịch sử phải là bản sao của bảng chính không có chỉ mục, đảm bảo bạn cũng có dấu thời gian cập nhật trong bảng.

Nếu bạn thử các cách tiếp cận khác sớm đủ, bạn sẽ phải đối mặt với các vấn đề:

  • bảo trì overhead
  • nhiều cờ trong Selects
  • truy vấn chậm
  • phát triển của bảng, chỉ số
0

Câu hỏi thực sự là bạn có cần sử dụng dữ liệu lịch sử và dữ liệu hoạt động cùng nhau để báo cáo không? Nếu vậy hãy giữ chúng trong một bảng, phân vùng và tạo một khung nhìn cho các bản ghi hoạt động để sử dụng trong các truy vấn hoạt động. Nếu bạn chỉ cần thỉnh thoảng nhìn chúng (để nghiên cứu các vấn đề về leagal hoặc một số vấn đề như vậy) thì hãy đặt chúng vào một bảng riêng biệt.

+1

Có khó khăn hơn khi 'JOIN' hai bảng trong một vài báo cáo lịch sử hoặc khó sửa đổi mỗi bảng chèn/cập nhật/xóa đơn lẻ để nhận biết các mối quan tâm lịch sử? Trên thực tế, nhật ký kiểm tra sẽ bao gồm cả dữ liệu hiện tại trong bảng lịch sử, do đó, bảng hiện tại thậm chí không cần thiết trong báo cáo. –

-1

Một tùy chọn khác là lưu trữ dữ liệu hoạt động trên cơ sở [hàng ngày | hàng giờ | bất kỳ]. Hầu hết các công cụ cơ sở dữ liệu support the extraction of the data into an archive.

Về cơ bản, ý tưởng là tạo ra một lịch trình Windows hoặc CRON công việc mà

  1. xác định các bảng hiện tại trong cơ sở dữ liệu hoạt động
  2. chọn tất cả dữ liệu từ mỗi bảng vào một tập tin CSV hoặc XML
  3. nén dữ liệu đã xuất sang tệp ZIP, tốt nhất là với dấu thời gian của thế hệ trong tên tệp để lưu trữ dễ dàng hơn.

Nhiều công cụ cơ sở dữ liệu SQL đi kèm với một công cụ có thể được sử dụng cho mục đích này. Ví dụ: khi sử dụng MySQL trên Linux, lệnh sau có thể được sử dụng trong công việc CRON để lập lịch trích xuất:

+0

Bạn có thể giải thích lý do cho việc bỏ phiếu không? – hamdiakoguz

+0

Điều này không phù hợp với dữ liệu lịch sử vì nếu ai đó thay đổi giá trị và thay đổi giá trị đó trong chu kỳ lưu trữ, các cập nhật sẽ bị mất. Cũng không có cách nào dễ dàng để xem xét các thay đổi đối với một thực thể theo thời gian hoặc để khôi phục một thực thể một phần. – Sgoettschkes

0

Tôi biết bài đăng cũ này nhưng chỉ muốn thêm vài điểm. Tiêu chuẩn cho các vấn đề như vậy là những gì phù hợp nhất cho tình huống. hiểu được nhu cầu lưu trữ như vậy và việc sử dụng tiềm năng dữ liệu theo dõi lịch sử/kiểm toán/thay đổi là rất importat.

Kiểm tra (mục đích bảo mật): Sử dụng bảng chung cho tất cả các bảng có thể kiểm tra của bạn. xác định cấu trúc để lưu trữ tên cột, trước các trường giá trị và sau giá trị.

Lưu trữ/lịch sử: cho các trường hợp như theo dõi địa chỉ trước đó, số điện thoại, v.v ... tạo một bảng riêng biệt FOO_HIST tốt hơn nếu lược đồ bảng giao dịch hoạt động của bạn không thay đổi đáng kể trong tương lai (nếu bảng lịch sử của bạn phải có cùng một cấu trúc). nếu bạn dự đoán chuẩn hóa bảng, thay đổi loại bỏ dữ liệu/loại bỏ cột, lưu trữ dữ liệu lịch sử của bạn ở định dạng xml. xác định một bảng với các cột sau (ID, ngày, phiên bản lược đồ, XMLData). điều này sẽ dễ dàng xử lý các thay đổi lược đồ. nhưng bạn phải đối phó với xml và có thể giới thiệu một mức độ phức tạp cho việc truy xuất dữ liệu.

0

Bạn có thể tạo một thể hóa/views lập chỉ mục trên bàn. Dựa trên yêu cầu của bạn, bạn có thể cập nhật toàn bộ hoặc một phần các khung nhìn. Vui lòng xem điều này để tạo mview và đăng nhập. How to create materialized views in SQL Server?

0

Chỉ muốn thêm tùy chọn mà tôi đã bắt đầu sử dụng vì tôi sử dụng Azure SQL và điều nhiều bảng đã quá cồng kềnh đối với tôi. Tôi đã thêm một trình kích hoạt chèn/cập nhật/xóa trên bảng của tôi và sau đó chuyển đổi trước/sau khi thay đổi thành json bằng cách sử dụng tính năng "FOR JSON AUTO".

SET @beforeJson = (SELECT * FROM DELETED FOR JSON AUTO) 
SET @afterJson = (SELECT * FROM INSERTED FOR JSON AUTO) 

Điều đó trả về biểu diễn JSON cho bản ghi trước/sau khi thay đổi. Sau đó, tôi lưu trữ các giá trị đó trong bảng lịch sử với dấu thời gian khi thay đổi xảy ra (tôi cũng lưu trữ ID cho hồ sơ hiện tại về mối quan tâm). Sử dụng quá trình tuần tự hóa, tôi có thể kiểm soát cách dữ liệu được chèn lấp trong trường hợp thay đổi lược đồ.

Tôi đã tìm hiểu về điều này từ liên kết này here

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