我们该如何设计数据库(四)

其实我一直在准备另一篇博文的基础资料,但是和朋友聊天,他问我最近在做什么,我说在做系统Log模块,并和他交流了一下,于是这篇博客就应运而生。



其实我一直在准备另一篇博文的基础资料,但是和朋友聊天,他问我最近在做什么,我说在做系统Log模块,并和他交流了一下,于是这篇博客就应运而生。

所有数据都可以用如下形式表述:ID,表名,列名,Value。

比如说现在有这么一条数据要插入User表:

ID(Guid,这里为了方便理解用Int) Username Password Email
1 CrazyJinn 123456 CrazyJinn@W.C

这一条记录可以转换为:

ID 表名 列名 Value
1 User Username CrazyJinn
1 User Password 123456
1 User Email CrazyJinn@W.C

你可以在各种对灵活性要求高的地方看到这种设计,比如说在《我们该如何设计数据库(三)》的留言中,就有园友提到了类似的设计。

当然,这种方式效率不是很高;不过可以把聚集索引加到表名上,然后非聚集索引加在列名上,再水平分割一下,如果你心情好,再做个读写分离,相信就非高并发、千万数据量级的应用来说,理论上还是可以接受的。

好了,现在进入正文。

现在要做一个通用的Log模块。

既然是通用的,那就意味着灵活性要非常强,因为你不知道Log中要记录的数据结构是如何的。

而且给我的需求有一个非常变态的地方:要有回退功能。不过这个我们先不去管他。

根据之前的讨论,我们可以很容易设计出一张Log表。

ID 表名 列名 Type(Create\Edit\Delete) Value 最后修改时间

如果处理的全是无关系的问题,这样做就足够了。但是要知道,RDBMS,最重要的就是关系的处理。

比如说要Log这样两张表:

上文所设计出的Log表面对这样的一对多关系是无法储存的,不要往了,我们还有多对多关系。

当然可以拓展Log表来实现储存一对多/多对多关系,虽然我不确定能不能做到,因为我没有就这方面去深入的思考。如果您想到了好的设计,欢迎留言和我探讨。

让我们来重新思考一下Log模块的本质:

1、大量数据。

2、只是大量数据(和别的模块没有关联,纯粹的数据)。

这种场景让我不由自主的想到了Nosql。在这里,使用MongoDB来实现。关于MongoDB入门,可以参考下面两篇文章:

祥叔:《MongoDB开发学习(1)开天辟地,经典入门

Fish Li:《MongoDB实战开发 【零基础学习,附完整Asp.net示例】

MongoDB使用Bson来储存数据,你可以简单的把Bson理解为Json。众所周知,Json是一个非常易于扩充的,松散的的数据格式;基于Json易于扩充的特性,我们可以这样来设计Log表

LogID ID 表名 Content(所储存的内容,包含了最后修改时间,修改类型,以及新的修改ID)

如果我对User表修改了6次,那么我们Log的数据如下图:

我们主要把注意力集中在上图用红框标注的3条数据上。

第一条数据,ContactList是一个Array类型,长度为0,这表示没有对应的Contact。

第二条数据,ContactList长度变为1,这表示这次修改为User添加了一个Contact的关联,我们将第二条数据完全展开来看:



可以看到,包含了一个完整的Contact进来。




第三条数据ContactList为Null,这表示我在某个别的地方修改了User信息。这次修改没有涉及Contact,所以保存为Null。当我们取数据的时候,如果发现某个List为Null,就要递归的向上去查找不为Null的数据。例如我这里,就要去找到第二条数据的ContactList。

为了方便大家理解,我把Json贴在下面。对照前面的图片可以很好的阅读。

 
  1. {
  2. "Content":[{
  3. "_id":newBinData(3,"mtonv7sMCkewsMIjWZ9/qg=="),
  4. "Username":"1",
  5. "Password":"1",
  6. "Number":1,
  7. "LastModified":newDate("27/11/201210:28:18"),
  8. "ContactList":[{
  9. "_id":newBinData(3,"1QwcXGKedUCO27QprZB26Q=="),
  10. "UserID":newBinData(3,"YyQDfuoj6EuuDNl91leigA=="),
  11. "Phone":"Phone1",
  12. "Email":"Email1"
  13. },{
  14. "_id":newBinData(3,"EeWfiFCknkex4H2jEraR/w=="),
  15. "UserID":newBinData(3,"YyQDfuoj6EuuDNl91leigA=="),
  16. "Phone":"Phone2",
  17. "Email":"Email2"
  18. }]
  19. },{
  20. "_id":newBinData(3,"Afk3spV0q0uKM+yNs/SHbw=="),
  21. "Username":"1to2",
  22. "Password":"1to2",
  23. "Number":2,
  24. "LastModified":newDate("27/11/201210:35:03"),
  25. "ContactList":[]
  26. },{
  27. "_id":newBinData(3,"H/5o2lizmUWkaxAZUgNHzg=="),
  28. "Username":"2to3",
  29. "Password":"2to3",
  30. "Number":3,
  31. "LastModified":newDate("27/11/201210:40:28"),
  32. "ContactList":[{
  33. "_id":newBinData(3,"7HDyGU2+A02HbQtUFbOo8A=="),
  34. "UserID":newBinData(3,"H/5o2lizmUWkaxAZUgNHzg=="),
  35. "Phone":"PhoneNew",
  36. "Email":"EmailNew"
  37. }]
  38. },{
  39. "_id":newBinData(3,"zf2SiYW81kufGO7ZgY5r3A=="),
  40. "Username":"3to4",
  41. "Password":"3to4",
  42. "Number":4,
  43. "LastModified":newDate("27/11/201210:41:34"),
  44. "ContactList":null
  45. },{
  46. "_id":newBinData(3,"N68jDslbU0uvdHJTSq0vIg=="),
  47. "Username":"5",
  48. "Password":"6",
  49. "Number":7,
  50. "LastModified":newDate("27/11/201217:14:12"),
  51. "ContactList":null
  52. },{
  53. "_id":newBinData(3,"Fw6OqMNcc0K+rySfgz3dTg=="),
  54. "Username":"9",
  55. "Password":"9",
  56. "Number":9,
  57. "LastModified":newDate("27/11/201217:16:15"),
  58. "ContactList":[{
  59. "_id":newBinData(3,"zfsQRK5A0kGFFcnc5TZ9GA=="),
  60. "UserID":newBinData(3,"YyQDfuoj6EuuDNl91leigA=="),
  61. "Phone":"PhoneNew",
  62. "Email":"EmailNew"
  63. }]
  64. }],
  65. "ModelID":newBinData(3,"YyQDfuoj6EuuDNl91leigA=="),
  66. "ModelName":"User",
  67. "_id":ObjectId("50b4254257751f09a02decba")
  68. }

这样,一个Log功能的雏形就出来了





AD:2013大

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值