数据库大小表问题
最近比较忙,因此有时候有些想写文章的想法,但只是在blog里面做了个标记,并没有实际的写出来。今天就要过节了,不防忙里偷闲一下,顺便把这些天的欠债给补上吧:)首先从数据库大小表来补吧。
背景:数据库大小表即一个系统后台数据库的实现有多种。对于有许多属性的一个事物,我们可以使用一张表来表示,当然也可以使用多张表进行分类进行表示。对于是使用一张表进行实现还是使用多张表来进行实现,这对于很多做后台开发的人员来讲是一个争论不体的问题了。下面我们将讨论各自的优缺点。
大表:大表实现有其自身的优点,那就是对于后台服务来讲,IO是一个主要的瓶颈。我们知道,程序和后台数据库交互是需要付出这方面的代价的,那么这就意味着和数据库多交互一次,那么就必须付出相应的IO代价。但对于大表来讲,一次可以将尽可能多的数据一次提取出来,然后对数据做分析整合,这样就可以尽可能少的和后台数据库交互,那么自然它的实现结果是IO代价小。这样系统从性能上来讲是比较好的。但其不是没有缺点,因为尽可能多的数据放在一张表里面,那么必然造成的结果就是逻辑不太清晰,不容易理解,不容易维护,特别是对于不是一对一关系的数据就更难了。
小表:我们从别一个方面看问题,可能就会有另一番景象。我们实现一个系统的时候,我们首先考虑的是系统的部署和结构,很自然下一步想到的这些结构如何由后台数据库来支撑。那么很自然我们会把一系统的某一块的东西使用一张表来支撑,这样逻辑十分清晰;而且从扩展方面,我们可以在这张表内部考虑很多可扩展的点,这是大表很难做到的。因此,这种思想最终的结果也是很明显的,那就是后台会有很多张相应的表,各个子系统会单独有自已的数据库读写和维护。那么这种实现,必然的代价就是数据库读取次数多,IO压力大。
跳出大小表的争论:现在我们想,是否可以跳出大小表的争论点来讨论大小表问题呢?究竟是大表好还是小表好,我们自已的系统的实现究竟是采用大表还是小表呢?笔者认为还是要看应用,需求决定一切。没有不变的技术,只有无限变化的应用。在我们考虑是采用大表还是小表的时候,我们应该考虑它们各自给我们可以带来哪些好处,然后做一些比较和权衡,最终得出自已需要的结论。比如,我们做的系统对象是一家企业,该企业使用此系统来管理内部员工数据,那么现在我们很清楚IO代价不是什么问题,因此甚至我们可以说大表给我们带来的优点是可以乎略的。但是采用小表就不一样了,因为它逻辑清晰,可能之后还会添加不同的考核属性,可扩展性是很重要的。但是如果我们做的应用如果是一个网部的线上服务,比如GOOGLE, BAIDU, SOHU(呵呵,口气大了些)这时必须要考此IO读取代价了,因为每一次请求,我们都需要对其服务,对于第小时千万次服务请求来讲,后台IO的压力也是很繁重的,如果一次请求可以减少一次IO读取的话,那么总的结省代价也是很显而易见的。
下面以一个具体示例讨论一下大小表:有一家网游公司存在这样一种手机应用,它为线上游戏提供手机验证码服务、声音验证服务。手机可提供多种子服务,手机验证码服务和声音验证是手机服务的一些子服务。每个手机服务又可绑字多个游戏业务,比如游戏充点,造建筑等。现在逻辑结构也就比较清晰了。
对于上面的应用,我们应该怎么来设计和实现呢?思路是多种多样的。
方案一:大表方案。一个用户有唯一的id,因此数据库可以将该用户相关的所有数据存储在一张表里面的一条记录。如下:
t_mobile_service (
F_user_id UNSIGNED INT PRIMARY KEY, /* 用户id*/
F_mobile_service_flag TYNY INT UNSGINED DEFAULT 1, /* 用户是否开能手机服务,只有开能,才可能有子服务 1: 未开通 2:开通 */
F_mobile_token_service_flag TYNY INT UNSIGNED DEFAULT 1, /* 用户是否开通验证验服务 1:未开通 2:开通*/
F_mobile_sound_flag TYNY INT UNSGINED DETAULT 1, /*用户是否开能声音验证功能服务1:未开通 2:开通*/
F_mobile_token_current VARCHAR(32), /*手机当前产生的验证码*/
F_mobile_sound_fingerprint BLOB, /*声音签名*/
F_mobile_token_create_time DATETIME, /*手机验证码产生时间*/
F_mobile_sound_fingerprint_settime DATETIME, /*声音签名设置时间*/
F_mobile_token_bind_service BIG INT UNSIGNED, /*验证码绑定服务*/
F_mobile_sound_bind_servide BIG INT UNSIGNED, /*声音签名绑定的服务*/
F_create_time [...]








