本文介绍一些关于提高系统性能方面的知识,列分割,行分割,实例分割,物理存储分割等技术。
这篇主要讲解一下数据库的设计,因为一个好的数据结构,对整体系统的运作太重要了,请看看本文的内容。
提到程序性能,大家都知道时间复杂度的公式O(f(n))。在提高性能的这个迷局中,很多人都会想尽办法降低算法函数f的复杂度,或者是提高函数f的运行 速度。但是这些都是没有办法的办法,是舍本求末的办法。如果基数n巨大,这类方法都不会有很好的效果,因为问题的本身在于基数 n。千方百计减少基数n的数量才能获取质的提高。
如何才能达到降低基数n的效果呢?假设你一个杂货店的老板,你有一个杂志货柜。可是杂志的种类越来越多,货柜放不下了,这时你会怎么做?是延长货柜的长度 还是把杂志分类后,再增加一个货柜?我更愿意增加一个货柜,而不是无限制的延长原来的货柜。从杂货店货柜的启示,我觉得降低基数 n的数量的有效办法是分而治之:
一、 列分割
通常,随着开发过程的推进,系统中主表的字段数会越来越多。但是一个表的字段个数,是受数据库规范和性能限制的。例如,SQL Server 数据库中一个表最多可以包含1024个字段,而实际应用中一般不能超过246个字段,每行数据可以存储8060字节。(参见 http://msdn.microsoft.com/zh-cn/library/ms143432.aspx)
另外,对于大数据表来说,列的数量直接影响存取速度。数据的存储结构对行的存取更加优化,而不是列的存取。下面,提出几种分割存储列的情形。
1、 列数太多时。
我在2004年曾经做过一个失败的项目。在设计一个5年的采购计划表时,我把每个月的采购计划设计成列,这样表的列说增加了60 列,这张表最终达到120个列。这种设计导致的结果是,当表有100万条记录时,采购计划的计算要花费2.5小时。改进方案是把列改成行存储,增加一个计 划年份字段,这样,总的列数减少了近40%,表的行数增加了增加到了500万条,但是存取速度提高了很多,使采购计划的计算时间降低到0.5小时。
所以,我给出的意见是
l 表的列数最好不要超过80个
l 行存储比列存储的存取速度更快
2、 表中列的数据相对较大或不经常用到时
表中存在下面的字段时需要隔离出去:
l 图片对象
l 附件(文件等)
l 大量的备注信息
l 几乎不被查询的列
3、 表中的字段,可以按照业务逻辑分类时。
按照数据库的设计规范,一个同一个对象的属性应该属于一张表。可是,实际情况是,如果按照业务逻辑来划分表,能获得更好的性能。
二、行分割
对于记录行数巨大的表来说,最好的办法是按分类进行行分割,让数据存储在多个表内。自然界有一个放之四海皆准的“二八”定律,把它应用到数据上,就可以这样解释:在所有的数据中有20%的数据是可以满足我们80%的需求的。“
根据这个原理,通常有两种分类方法:
1、 按时间分类
如果数据的时效性很强,我们可以认为所有数据中,20%近期更新的数据能够满足业务80%的需求。例如,如果我们有5年的历史数据,那么就可以认为 其中在1年内(20%)更新过的数据(也可以是1年内创建的数据),能满足80%的业务需求;所以我们可以把这张表拆成两个表,分别存储20%和80%的 数据,以达到提高效率的目的。如果两张表仍然没有有效的提高性能,还可以利用“二八”定律再次分割。
实效性数据量和使用量关系:
2、 按索引分类
当数据的时效性不明显时,可以按索引分类数据。所谓索引可以是任何可以用于分类的字段,比如部门编号,员工编号,工艺编号等等。我们可以这样假设, 表中存储了所有零件的信息,但是在80%的情况下,1号生产车间只会存取自己部门用到的零件。于是,我们可以按照部门编号,把表分成多个。
三、数据库实例分割
一般情况下,开发人员习惯于给每个项目配置一个数据库。但是实际上我们可以给一个应用程序更多的数据库实例。比如,在一个网络游戏服务器中,经常会 有账户数据库(用于认证)、存储数据库(用于存储状态)、日志数据库(用于存储监控状态)、地图数据库(用于存储地图状态)等等。类比到ERP系统中,我 们可以把许多项目共同的部分抽象出来,分别存储在不同的数据库实例中。例如,用户信息、部门信息、系统日志信息等可以定制成通用的数据库,每个软件项目都 可以去使用。
四、数据库实例物理部署的分割
表分割、数据库实例的分割,为物理部署带来了灵活性。例如,我们对物料表按照不同的品目,进行了表分割;又对这些表部署在了不同的数据库实例中;这 样我们就有条件把这些数据库实例分别部署在不同的物理数据库服务器上。这种部署给我们带来的好处是,物料计算时,我们可以指令所有的数据库服务器分布式计 算,大大提高运算速度。