Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Cơ sở dữ liệu:Lập Nhật ký các hành động, làm thế nào để xử lý các tham chiếu khác nhau?

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ngừng MySQL dung nạp nhiều NULL trong một ràng buộc DUY NHẤT

  2. Tại sao tôi gặp lỗi JPEG 42 khi nó được lưu trữ trong cơ sở dữ liệu?

  3. Cách nối điểm vào LINESTRING SQL

  4. mysql chuyển đổi từ UTC sang IST

  5. Cách chọn từ MySQL trong đó Tên bảng là Biến