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

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

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

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

ID(Guid,这里为了方便理解用Int)UsernamePasswordEmail
1CrazyJinn123456[email protected]

这一条记录可以转换为:

ID表名列名Value
1UserUsernameCrazyJinn
1UserPassword123456
1UserEmail[email protected]

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

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

好了,现在进入正文。

现在要做一个通用的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表

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

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

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

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

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

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

#p#

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

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

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

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

就此搁笔

原文链接:http://www.cnblogs.com/CrazyJinn/archive/2012/12/04/2794785.html

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/248557.html<

(0)
运维的头像运维
上一篇2025-04-27 15:35
下一篇 2025-04-27 15:37

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注