Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Database:Membuat Log tindakan, bagaimana menangani berbagai referensi?

Berikut ini adalah bagaimana saya akan melakukannya. Saya memiliki beberapa komentar lagi di bagian bawah setelah Anda melihat skemanya.

Masuk

LogID - ID log unik

Waktu - tanggal/waktu acara

LogType - String atau ID

(komentar sampingan, saya akan menggunakan id di sini sehingga Anda dapat menggunakan tabel pesan yang ditunjukkan di bawah ini, tetapi jika Anda ingin cepat dan kotor, Anda hanya dapat menggunakan string unik untuk setiap waktu log (mis. "Permainan Dimulai", "Pesan Terkirim" , dll)

Aktor Log

LogID - kunci eksternal

LogActorType - String atau ID (seperti di atas, jika ID Anda memerlukan tabel pencarian)

LogActorID - Ini adalah id unik untuk tabel untuk jenis misalnya Pengguna, Grup, Game

Urutan - ini adalah urutan aktor.

Pesan Log

LogType - kunci eksternal

Pesan - string panjang (varchar(maks)?)

Bahasa - string(5) sehingga Anda dapat memasukkan bahasa yang berbeda misalnya "US-en"

Contoh Data(menggunakan 3 contoh Anda)

Masuk

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

Pesan Log

LogType Message 
1       {0} Made a new friend {1}
2       {0}, {1}, {2} played a game ({3})
3       {0} joined a group ({1})

Pengguna

ID Name
1  User A
2  User B
3  User C

Permainan

ID Name
1  Name of game

Grup

ID Name
1  Name of group

Jadi, inilah hal-hal baik tentang desain ini.

  • Sangat mudah untuk memperpanjang

  • Ini menangani masalah multi-bahasa terlepas dari aktornya

  • Ini mendokumentasikan diri sendiri, tabelLogMessage menjelaskan dengan tepat apa yang seharusnya dikatakan oleh data yang Anda simpan.

Beberapa hal buruk tentangnya.

  • Anda harus melakukan beberapa pemrosesan yang rumit untuk membaca pesan.

  • Anda tidak bisa hanya melihat DB dan melihat apa yang telah terjadi.

Dalam pengalaman saya, bagian bagus dari desain semacam ini lebih banyak daripada bagian buruknya. Apa yang telah saya lakukan untuk memungkinkan saya melihat log dengan cepat dan kotor adalah membuat tampilan (yang tidak saya gunakan untuk kode aplikasi) yang dapat saya lihat ketika saya perlu melihat apa yang terjadi melalui bagian belakang akhir.

Beri tahu saya jika Anda memiliki pertanyaan.

Pembaruan - Beberapa contoh kueri

Semua contoh saya ada di sqlserver 2005+, beri tahu saya jika ada versi lain yang Anda ingin saya targetkan.

Lihat tabel LogActor(Ada beberapa cara untuk melakukan ini, yang terbaik tergantung pada banyak hal termasuk distribusi data, kasus penggunaan, dll)Berikut adalah dua:

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

Secara umum saya pikir a) lebih baik daripada b) Misalnya jika Anda kehilangan tipe aktor a) akan memasukkannya (dengan nama nol). Namun b) lebih mudah untuk dipelihara (karena pernyataan UNION ALL membuatnya lebih modular.) Ada cara lain untuk melakukan ini (misalnya CTE, view, dll). Saya cenderung melakukannya seperti b) dan dari apa yang saya lihat, tampaknya itu setidaknya praktik standar jika bukan praktik terbaik.

Jadi, 10 item terakhir di log akan terlihat seperti ini:

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 - Seperti yang Anda lihat, lebih mudah untuk memilih semua item log dari tanggal daripada X terakhir, karena kami memerlukan sub-kueri (mungkin sangat cepat) untuk ini.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Peningkatan Nilai PDO PHP, Mysql

  2. Mysql:Hitung catatan (termasuk nol) per bulan

  3. Gabungkan nilai dua baris menjadi satu

  4. Cara tercepat untuk menyisipkan objek jika tidak ada dengan SQLAlchemy

  5. MySQL - Mengapa aturan COLLATION diabaikan oleh operator LIKE untuk karakter Jerman