2008-09-30 31 views
14

Tôi có một câu hỏi liên quan đến hai cột bổ sung (timeCreated, timeLastUpdated) cho mỗi bản ghi mà chúng ta thấy trong nhiều giải pháp. Câu hỏi của tôi: Có một lựa chọn tốt hơn?Làm cách nào để tránh thêm các trường dấu thời gian vào các bảng của bạn?

Kịch bản: Bạn có một DB lớn (về mặt bảng, không phải bản ghi), sau đó khách hàng đến và yêu cầu bạn thêm "dấu thời gian" vào 80% bảng của bạn.

Tôi tin rằng điều này có thể được thực hiện bằng cách sử dụng một bảng riêng biệt (TIMESTAMPS). Bảng này sẽ có, ngoài cột dấu thời gian rõ ràng, tên bảng và khóa chính cho bảng đang được cập nhật. (Tôi giả định ở đây rằng bạn sử dụng một int làm khóa chính cho hầu hết các bảng của bạn, nhưng tên bảng sẽ rất có thể phải là một chuỗi).

Để hình dung điều này giả sử kịch bản cơ bản này. Chúng tôi sẽ có hai bảng:

THANH TOÁN: - (hồ sơ của bạn bình thường)
dấu thời gian: - {current timestamp} + {TABLE_UPDATED, id_of_entry_updated, timestamp_type}

Lưu ý rằng trong thiết kế này bạn không cần những hai cột "phụ" trong đối tượng thanh toán gốc của bạn (theo cách này, có thể làm cho nó thông qua giải pháp ORM của bạn) vì bạn hiện đang lập chỉ mục theo TABLE_UPDATEDid_of_entry_updated. Ngoài ra, timestamp_type sẽ cho bạn biết mục nhập có được chèn hay không (ví dụ: "1"), cập nhật (ví dụ: "2") và bất kỳ mục nào khác bạn có thể muốn thêm, như "xóa".

Tôi muốn biết bạn nghĩ gì về thiết kế này. Tôi quan tâm nhất đến các phương pháp hay nhất, những gì hoạt động và quy mô theo thời gian. Tài liệu tham khảo, liên kết, các mục blog được chào đón nhiều hơn. Tôi biết ít nhất một bằng sáng chế (đang chờ xử lý) cố giải quyết vấn đề này, nhưng có vẻ như các chi tiết không được công khai vào lúc này.

Chúc mừng, Eduardo

Trả lời

12

Khi bạn đang ở đó, hãy ghi lại người dùng đã thực hiện thay đổi.

Lỗ hổng có thiết kế bảng riêng biệt (ngoài hiệu suất kết nối được đánh dấu bởi người khác) là nó giả định rằng mỗi bảng có cột nhận dạng cho khóa. Điều đó không phải lúc nào cũng đúng.

Nếu bạn sử dụng SQL Server, phiên bản 2008 mới hỗ trợ thứ gì đó mà họ gọi là Change Data Capture, điều này sẽ làm giảm đi rất nhiều nỗi đau mà bạn đang nói đến. Tôi nghĩ rằng Oracle có thể có một cái gì đó tương tự như là tốt.


Cập nhật: Rõ ràng Oracle gọi nó giống như SQL Server. Hay đúng hơn, SQL Server gọi nó là điều tương tự như Oracle, kể từ khi triển khai thực hiện của Oracle đến đầu tiên;)
http://www.oracle.com/technology/oramag/oracle/03-nov/o63tech_bi.html

+0

Đây là bài viết hạnh phúc nhất từng làm cho tôi. Tôi đã sẵn sàng để nhập một bài viết có nhu cầu chính xác điều này. Tôi không nghĩ rằng Oracle có một cái gì đó như thế này. Nếu có, tôi sẽ tự đá. – MusiGenesis

+0

Tôi nhận được tức giận suy nghĩ về tất cả thời gian tôi đã lãng phí thêm các trường ModifiedBy và CreatedDateTime vào các bảng của tôi. – MusiGenesis

+0

Uh, vâng, Oracle đã có điều này trong nhiều năm. –

1

Ưu điểm của phương pháp bạn đề nghị là nó cung cấp cho bạn tùy chọn thêm các lĩnh vực khác để bảng dấu thời gian của bạn, như theo dõi người dùng thực hiện các thay đổi. Bạn cũng có thể theo dõi các chỉnh sửa đối với các trường nhạy cảm, ví dụ như ai đã hủy hợp đồng này?

thay đổi kỷ lục Logging trong một file riêng biệt có nghĩa là bạn có thể hiển thị nhiều thay đổi đến mức kỷ lục, như:

mm/dd/hh yy: mm: ss thêm bởi XXX mm/dd/yy hh: mm: ss Field PRICE Được thay đổi bởi XXX, mm/dd/yy hh: mm: ss Ghi lại bị xóa bởi XXX

Một bất lợi là mã bổ sung sẽ thực hiện chèn vào bảng chính của bạn.

5

Tôi nghĩ rằng tôi thích thêm dấu thời gian vào các bảng riêng lẻ. Tham gia vào bảng dấu thời gian của bạn trên một phím tổng hợp - một trong số đó là một chuỗi - sẽ chậm hơn và nếu bạn có một lượng lớn dữ liệu thì cuối cùng nó sẽ là một vấn đề thực sự.

Ngoài ra, rất nhiều thời gian khi bạn nhìn vào dấu thời gian, đó là khi bạn đang gỡ lỗi một vấn đề trong ứng dụng của mình và bạn sẽ muốn dữ liệu ngay tại đó thay vì luôn phải tham gia vào bảng khác.

+0

tham gia sẽ không cần sử dụng chuỗi như một phần của mệnh đề "BẬT". Nếu đó là phần đầu tiên của chỉ mục, nó chỉ có thể được kiểm tra một lần cho mỗi truy vấn tùy thuộc vào mức độ ưu việt của trình tối ưu hóa. – BCS

+0

Nhưng nếu anh ấy lưu trữ dấu thời gian từ các bảng khác nhau trong một bảng TIMESTAMP lớn, anh ấy sẽ cần phải phân biệt dấu thời gian INVOICE từ, chẳng hạn như dấu thời gian USERACCOUNT, vì vậy sẽ không phải là: TRÊN TIMESTAMP.id_of_entry VÀ tablename = 'INVOICE '? – Dana

+0

Tôi tin rằng bạn có một điểm, Dana. Tuy nhiên, vì tên bảng là duy nhất, bạn có nghĩ rằng tôi có thể lấy đi bằng một băm đơn giản (như sử dụng biểu diễn ascii của các tên bảng để làm cho nó là một int)? Bằng cách này tôi sẽ kết thúc lập chỉ mục trên hai lĩnh vực int. bạn nghĩ sao? – esegura

0

Tôi nghĩ rằng việc gia nhập thêm bạn sẽ phải thực hiện để có được Dấu thời gian sẽ là một hit hiệu suất nhẹ và một cơn đau cổ. Khác hơn là tôi thấy không có vấn đề.

1

Nếu bạn thiết lập các công cụ thời gian-tem để chạy tắt của trigger, hơn bất kỳ hành động nào có thể đặt ra một trigger (Reads?) có thể được ghi lại. Ngoài ra có thể có một số lợi thế khóa.

(Mang tất cả điều đó với một hạt muối, tôi không DBA hay SQL guru)

10

Tôi đã sử dụng một thiết kế trong đó mỗi bảng để được kiểm toán có hai bảng:

create table NAME (
    name_id int, 
    first_name varchar 
    last_name varchar 
    -- any other table/column constraints 
) 

create table NAME_AUDIT (
    name_audit_id int 
    name_id int 
    first_name varchar 
    last_name varchar 
    update_type char(1) -- 'U', 'D', 'C' 
    update_date datetime 
    -- no table constraints really, outside of name_audit_id as PK 
) 

Một kích hoạt cơ sở dữ liệu được tạo ra để điền vào NAME_AUDIT mọi lúc mọi thứ được thực hiện để NAME. Bằng cách này bạn có một bản ghi về mọi thay đổi được thực hiện cho bảng và khi nào. Ứng dụng không có kiến ​​thức thực sự về điều này, vì nó được duy trì bởi một trình kích hoạt cơ sở dữ liệu.

Tính năng này hoạt động khá tốt và không yêu cầu bất kỳ thay đổi nào đối với mã ứng dụng để triển khai.

+0

+1 lợi thế lớn ở đây là các bảng kiểm toán có thể được thêm vào sau đó mà không thay đổi lược đồ mà chúng đang kiểm tra; cảm ơn, tôi đã tự hỏi làm thế nào để thực hiện điều này cho một db tôi đang xây dựng! – jcollum

1

Vâng, tôi thích thiết kế đó và sử dụng nó với một số hệ thống. Thông thường, một số biến thể của:

LogID int 
Action varchar(1)  -- ADDED (A)/UPDATED (U)/DELETED (D) 
UserID varchar(20) -- UserID of culprit :) 
Timestamp datetime -- Date/Time 
TableName varchar(50) -- Table Name or Stored Procedure ran 
UniqueID int   -- Unique ID of record acted upon 
Notes varchar(1000) -- Other notes Stored Procedure or Application may provide 
0

Chúng tôi đã làm chính xác những gì bạn đã làm. Nó là rất tốt cho mô hình đối tượng và khả năng thêm tem mới và các loại tem khác nhau cho mô hình của chúng tôi với mã tối thiểu. Chúng tôi cũng theo dõi người dùng đã thực hiện thay đổi và rất nhiều logic của chúng tôi dựa trên những con tem này. Nó rất tốt.

Một hạn chế là báo cáo và/hoặc hiển thị nhiều dấu khác biệt trên màn hình. Nếu bạn đang làm nó theo cách chúng tôi đã làm nó, nó gây ra rất nhiều tham gia. Ngoài ra, thay đổi kết thúc trở lại là một nỗi đau.

0

Giải pháp của chúng tôi là duy trì bảng "Giao dịch", ngoài bảng "Phiên" của chúng tôi. Các lệnh UPDATE, INSERT và DELETE đều được quản lý thông qua một đối tượng "Transaction" và mỗi lệnh SQL được lưu trữ trong bảng "Transaction" khi nó đã được thực thi thành công trên cơ sở dữ liệu. Bảng "Giao dịch" này có các trường khác như transactiontType (I cho INSERT, D cho DELETE, U cho UPDATE), transactionDateTime, vv và khóa ngoài "sessionId", cho chúng ta biết cuối cùng ai đã gửi hướng dẫn. Nó thậm chí có thể, thông qua một số mã, để xác định ai đã làm gì và khi nào (Gus tạo ra kỷ lục vào thứ hai, Tim đã thay đổi Đơn giá vào ngày thứ ba, Liz thêm một giảm giá thêm vào thứ năm, vv).

Ưu điểm cho giải pháp này là:

  1. bạn có thể nói "những gì ai và khi nào", và để hiển thị nó cho người dùng của bạn! (Bạn sẽ cần một số mã để phân tích câu lệnh SQL)
  2. nếu dữ liệu của bạn được sao chép, sao chép và thất bại, bạn có thể xây dựng lại cơ sở dữ liệu của bạn thông qua bảng này

Nhược điểm là

  1. 100 000 dữ liệu cập nhật mỗi tháng có nghĩa là 100 000 bản ghi trong Tbl_Transaction
  2. Cuối cùng, bảng này có xu hướng được 99% khối lượng cơ sở dữ liệu của bạn

cho chúng tôi băng: tất cả hồ sơ cũ hơn 90 ngày sẽ được tự động xóa mỗi buổi sáng

-1

Philippe,

Đừng chỉ cần xóa những người lớn tuổi hơn 90 ngày, di chuyển chúng đầu tiên vào một DB riêng hoặc ghi chúng vào tập tin văn bản, làm điều gì đó để bảo tồn chúng, chỉ cần di chuyển chúng ra khỏi DB sản xuất chính.

Nếu bao giờ đến với nó, thường thì đó là trường hợp "anh ấy thắng nhiều tài liệu nhất"!

1

Một cơn ác mộng với thiết kế của bạn là mỗi lần chèn, cập nhật hoặc xóa sẽ phải nhấn vào bảng đó. Điều này có thể gây ra các vấn đề về hiệu năng và khóa lớn. Đó là một ý tưởng tồi để khái quát hóa một bảng như thế (không chỉ cho các dấu thời gian). Nó cũng sẽ là một cơn ác mộng để có được dữ liệu ra khỏi.

Nếu mã của bạn sẽ phá vỡ ở cấp GUI từ việc thêm trường bạn không muốn người dùng thấy, bạn đang viết mã không chính xác vào GUI của mình. .

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