Sau đây là cách tôi thực hiện. Tôi có thêm một số nhận xét ở phía dưới sau khi bạn đã xem lược đồ.
Nhật ký
LogID - ID nhật ký duy nhất
Thời gian - ngày / giờ diễn ra sự kiện
LogType - Chuỗi hoặc ID
(bình luận bên, tôi sẽ đi kèm với một id ở đây để bạn có thể sử dụng bảng thông báo được hiển thị bên dưới, nhưng nếu bạn muốn nhanh chóng, bạn có thể chỉ cần một chuỗi duy nhất cho mỗi lần ghi nhật ký (ví dụ:"Trò chơi đã bắt đầu", "Đã gửi tin nhắn" , v.v.)
LogActor
LogID - khóa ngoài
LogActorType - Chuỗi hoặc ID (như trên, nếu là ID, bạn sẽ cần một bảng tra cứu)
LogActorID - Đây là một id duy nhất cho loại bảng, ví dụ:Người dùng, Nhóm, Trò chơi
Trình tự - đây là thứ tự của các tác nhân.
LogMessage
LogType - khóa ngoại
Thông báo - chuỗi dài (varchar (max)?)
Ngôn ngữ - chuỗi (5) để bạn có thể tắt ngôn ngữ khác nhau, ví dụ:"US-en"
Dữ liệu mẫu (sử dụng 3 ví dụ của bạn)
Nhật ký
ID Time LogType
1 1/1/10 1
2 1/1/10 2
3 1/1/10 3
LogActor
LogID LogActorType LogActorID Sequence
1 User 1 1
1 User 2 2
2 User 1 1
2 User 2 2
2 User 2 3
2 Game 1 4
3 User 3 1
3 Group 1 2
LogMessage
LogType Message
1 {0} Made a new friend {1}
2 {0}, {1}, {2} played a game ({3})
3 {0} joined a group ({1})
Người dùng
ID Name
1 User A
2 User B
3 User C
Trò chơi
ID Name
1 Name of game
Nhóm
ID Name
1 Name of group
Vì vậy, đây là những điều thú vị về thiết kế này.
-
Nó rất dễ dàng để mở rộng
-
Nó xử lý các vấn đề đa ngôn ngữ phụ thuộc vào các tác nhân
-
Đó là tài liệu tự ghi lại, bảngLogMessage giải thích chính xác dữ liệu bạn đang lưu trữ nên nói như thế nào.
Một số điều tồi tệ về nó.
-
Bạn phải thực hiện một số xử lý phức tạp để đọc được tin nhắn.
-
Bạn không thể chỉ nhìn vào DB và xem điều gì đã xảy ra.
Theo kinh nghiệm của tôi, những phần tốt của kiểu thiết kế này nhiều hơn những phần xấu. Những gì tôi đã làm để cho phép tôi xem nhanh nhật ký là tạo một chế độ xem (mà tôi không sử dụng cho mã ứng dụng) mà tôi có thể xem khi tôi cần xem những gì đang diễn ra qua mặt sau kết thúc.
Hãy cho tôi biết nếu bạn có thắc mắc.
Cập nhật - Một số truy vấn mẫu
Tất cả các ví dụ của tôi đều có trong sqlserver 2005+, hãy cho tôi biết nếu có phiên bản khác mà bạn muốn tôi nhắm mục tiêu.
Xem bảng LogActor (Có một số cách để thực hiện việc này, cách tốt nhất phụ thuộc vào nhiều thứ bao gồm phân phối dữ liệu, các trường hợp sử dụng, v.v.) Đây là hai cách:
a)
SELECT
LogId,
COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
Sequence
FROM LogActor A
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence
b)
SELECT
LogId,
U.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
UNION ALL
SELECT
LogId,
Ga.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
UNION ALL
SELECT
LogId,
Go.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence
Nói chung, tôi nghĩ a) tốt hơn b) Ví dụ nếu bạn đang thiếu một loại tác nhân a) sẽ bao gồm nó (với tên rỗng). Tuy nhiên, b) dễ bảo trì hơn (vì câu lệnh UNION ALL làm cho nó trở nên mô-đun hơn.) Có nhiều cách khác để thực hiện việc này (ví dụ:CTE, views, v.v.). Tôi có xu hướng làm điều đó như b) và từ những gì tôi thấy, đó có vẻ là ít nhất là phương pháp tiêu chuẩn nếu không phải là phương pháp tốt nhất.
Vì vậy, 10 mục cuối cùng trong nhật ký sẽ giống như sau:
SELECT
LogId,
M.Message,
COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
Time,
A.Sequence
FROM Log
LEFT JOIN LogActor A ON Log.LogID = A.LogID
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
LEFT JOIN LogMessage M ON Log.LogType = M.LogMessage
WHERE LogID IN (SELECT Top 10 LogID FROM Log ORDER BY Date DESC)
ORDER BY Date, LogID, A.Sequence
NB - Như bạn có thể thấy, việc chọn tất cả các mục nhật ký từ một ngày sẽ dễ dàng hơn so với ngày X cuối cùng, bởi vì chúng tôi cần một truy vấn phụ (có thể rất nhanh) cho việc này.