版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://alek.blogbus.com/logs/5120028.html

有以下几个诀窍:
1、业务主键和数据库物理主键分离
在抽象系统业务模型时,我们都习惯于根据业务的情况定义出一个表的唯一不重复的关键字(主键)。然而,更好的做法,是不论具体业务如何,把所有的表的主键都定义成Generator支持下的自增长整数,作为记录编号(命名为xxx_key),把“业务主键”定义为不可重复的索引(甚至于根本不用定义,如果没有特殊的检索要求的话)。在这种主键设计策略中,隐含着一个很深的道理,那就是“将业务逻辑和物理逻辑脱离开”的原则,实体的业务逻辑并不直接运用到真实的物理逻辑实现上。以单据表作为一个典型的例子,单据往往具备着一个不可重复的“单据编号”,一般它的数据类型是一个几十字节的字符串,它相当于是“单据”这个实体在业务逻辑上体现出来的主键。而在这里的规范中,却并不以这个字符串编号为真正物理上的主键,而是采用一个自增长的KEY取代它成为真正的物理上的主键。以此为基础,表与表之间的关联也同样以一个单独整数字段进行关联,这个字段对于主表,一般就是主表的主键字段。在外键的创建中,一般也尽量避免多字段关联的联合外键。在FireBird数据库中,这种设计方式利用了FireBird特有的生成器(Generator)机制来实现。在创建外键时,一般都将外键的cascade delete打开,利用数据库的级联删除功能达到了自动删除从表记录。
2、 索引的建立
要为可能频繁发生的检索的条件组合建立相应的索引。如果定义了主从表的外键关联,那么系统会自动创建所需的索引。但针对不同的数据类型,索引的执行效率也是不同的。对于复杂的查询,可以通过plan子句告诉服务器采用怎样的索引进行数据检索,格式如下:
Select语句
  PLAN(
    表名1  INDEX(索引名称),
    表名2  INDEX(索引名称)
    )
3、 自增长字段的建立
建立表的时候,在IBExpert中通过打开字段的AutoInc属性设定某字段是自增长字段后,同时建立相应的生成器和触发器;通过调用SQL语句来得到服务器端生成器的值并使之加1:
Select gen_id(AGenerator,1) as id from rdb$database用一个ibquery控件来执行该语句产生永不重复整数序列。
一般情况下,一个表对应着一个生成器。但是在某些情况下,可能多个表共用一个生成器,也可能一个表用多个生成器
4、应尽量避免字符串字段作为关联查询的关联条件。
5、应尽量避免多重字段、字符串字段(特别是常字符串)作为主键、关联查询的关联字段
6、在系统构架方面应该采取划分业务数据生存期的方式,在系统中采用动态创建数据库的机制,使不同的业务区间对应一个单独的数据库文件,比如说,一个会计核算年对应一个GDB文件,到年底核算时,为下年创建一个新的数据库,新数据库中的常量数据从老数据库中继承过来,而动态的业务数据从0开始。划分动态数据库分区的原则就是,把每个数据库文件大约控制在600M左右(更大些也可以,但不太利于备份刻录到光盘上)

 

看了你的经验收益良多.

你在里边提到:
在SQL语句不是很多的情况下,应避免在代码中书写动态SQL语句,特别是对于把数据显示界面相关联的Select语句更不推荐使用动态SQL,而是要将不同的语句放在不同的Query元件中,而且将查询控件的字段实体化
====================================================
这样的话只要用良用到条件查询,就要切换DataSource相关的数据集组件,而且代码中也要用DataSource.DataSet的方式引用数据集来进行同步数据集操作.
TIME: 2006-12-2 14:05:31   IP: Protected
.NET时代的win32英雄

广泛的使用自增长整数作为主键,是不是会在大批量数据的导入时遇到很大的麻烦?
如果两表关联还是用的业务主键相关联 那么逻辑主键似乎没有存在的必要

逻辑主键存在的必要就是提供检索
==============================================
两表用逻辑主键相关联 这样的确很大程度的精简了两表关联的SQL处理
可是会不会造成两表关联的不正确呢?

说的非常好。在数据导入过程中,尤其是从逻辑主键的设计升级到物理主键的设计时,两表的关联确实需要一个将逻辑主键关联转化为物理主键关联的过程。处理这种做法,我有两个方法。
其一就是客户端处理,方法是在客户端放一个内存表,预先载入被关联的基础数据表,其中既包含物理主键,又包含逻辑主键(别的字段可以省略),然后进行关联表的导入,导入时,每插入一条记录之前,都通过内存表查一下逻辑主键对应的物理主键的值,把该值放入记录相应的关联字段中,再插入数据库。
第二就是服务器端处理。是在服务器端的触发器中判断如果整数关联字段为空,那么自动通过原始的逻辑主键关联字段查出物理关联字段对应的值,赋值进去。意思差不多。
如果是系统本身就采用了这种物理主键的思想进行设计的情况,那么一切都OK,只不过在数据导入导出过程中需要注意两个问题:
1、尊重已形成的自增长主键的值,也就是,已形成的自增长主键的值不能让它重新生成,是多少就是多少,原样导出,原样倒入,这样就不会错乱。IBExpert生成的触发器因为有判断语句,所以并不会干扰。
2、生成器对象的值也要随着变。特别是,在空数据库倒入历史数据时,一定要把生成器的值也继承过来。
注意了这两点,你就能对我提出的“业务主键和数据库物理主键分离”的思想运用自如,设计出的系统也有很好的性能。

我们公司的会计软件就是这样做的。
一个主数据库,一个模板数据库,然后是一个套帐一个目录,一年一个数据库。
但是,要跨年度查询时,需要同时或逐一连接多个数据库,
备份一个套帐的数据时也要将多个数据库备份并打包。
跨套帐汇总时,更是要逐一连接多个数据库(多的时候有70个套帐)。
一个数据库一年的数据大小为5-10MB。
==============================================
这就是我所提倡的“流水库”机制。这种机制的要点在于,根据业务在时间上的运转周期,将业务划分为一个一个的业务周期,每一个业务周期创建一个新的数据库,以一个个单独的数据库作为数据在业务时间周期的天然分区隔断。数据库分区的划分原则就是使跨数据库查询的操作尽量少,同时兼顾单个数据库数据的大小不要超过700M,最好是一张光盘能容纳的范围。每当系统到达业务时间分区的临界点时,系统将新建一个数据库,新数据库把常量数据从当前数据库中继承过来,当前数据库封顶,新数据库启动。业务分区最常见的就是按照财务年、或财务月分区,各有优点。这样进行系统设计带来了两个巨大的好处。其一就是增加了系统的健壮性。数据在不断的产生中不断的形成新数据库,这样单个数据库不会无限增大,同时也不容易集聚瑕疵,不易崩溃;其二,就是提升了系统的性能。由于久远的历史数据都位于不同的历史业务库中,所以当前活跃的业务库内就没有大量的历史陈旧数据,系统在进行数据检索和查询的时候,直接面对的就是与当前业务直接相关的数据,所以,系统的运行永远象刚投入使用不久那么快。但如果必须需要进行跨库查询的话,那么通过一定的算法也能够解决这个问题。我本人曾经提出过“数据集合并法”专门解决跨N个数据库查询的问题。在采取了强力的优化之后,跨数据库查询的性能也不错。
TIME: 2007-2-13 18:28:21   IP: Protected

 

可以请yangdong兄介绍一下“数据集合并法”吗?
=========================================
其实是用内存表的方法进行数据集记录的合并,原理并不复杂,就是通过循环,在每个数据库中进行某查询,把结果通过一定的规则添加到内存表中。比如说,
1、最简单的合并就是数据集相加,就是用循环把每个数据库的查询结果都放到一个内存表中
2、求和(sum)合并,就是每个查询结构插入内存表中时,先按照主键判断是否已存在记录,如存在,则把特定字段的值加到已有记录的相应字段中(求最大值、最小值道理相同)。
3、平均值合并,需要绕道处理,对总量和总数量分别求和,然后作除法。

第三种情况几乎没有多少实际应用。第一种情况是简单的追加。第二种情况往往是最典型的场景。

方法的关键在于
1、性能:怎样能使跨库查询的速度不低于在同一个数据库中的查询速度?
2、巧妙的封装,使程序员编写跨库查询语句的时候,几乎都不用管切换数据库的细节,不必写过多的冗余代码处理复杂的数据集合并的功能?

对于性能而言,数据集合并的关键在于记录的定位算法要非常快。目前最常用的方法就是使目标数据有一个具有不重复的单个整数字段的主键,暂且称之为rec_key(这也是我热衷于使用自增字段的原因之一),内存表在使用之前需要创建一个针对rec_key的索引。在第二种情况中,在插入记录的时候先对内存表进行Locate,定位成功,则进行字段的相加修改,失败,则把记录追加到内存表中。一般情况,具有单整数字段的索引的性能已经相当的好了,这种情况下,巨大的数据集的合并也有很不错的性能。(然而,有的时候我们如果追求极端的速度,则有可能编写针对数据集的Helper数据结构,来获得比Locate函数更加迅速的定位算法,甚至于根本不用内存表,直接用动态结构数组来盛放数据,用自定义的定位方法来定位数据,这就是后话了,一般根本用不着),如果你的记录集根本没有单整数的主键,只有很长的字符串的主键,或者是好几个字段的联合主键,那这个方法就有相当的效率折损。当然创建索引仍然有巨大的帮助。

在封装性方面,一定要达到把跨库查询机制化,使各种各样的跨库查询都能够很方便的进行,而不是每个查询都得写一大堆代码去进行多数据库循环。那么就需要把跨库查询机制固化到公用DataModule中,成为一种共有功能,把这个功能封装成为一个函数,包含有三部分参数:一个ibQuery控件(或者SQL语句),一个时间范围(该时间范围跨多个数据库),数据集的主键字段名称,该函数在执行中就首先根据SQL把内存表的字段都创建出来,然后创建索引,然后根据时间区域计算出所跨的数据库列表,然后在循环中连接每个数据库,执行SQL语句,把记录集合并到内存表中,最终,内存表中的数据就是成果物。这种方法下,新增一个跨库查询就用不着写一堆代码了。
这里需要提及的就是IBQuery控件的UniDirectional属性应该设定为True,使之成为单向数据集,性能会更好。
在这个机制中,可以利用ibquery的Field对象的Tag来约定告诉跨库查询函数该字段是需要求和呢,还是求最大值,或者是不做任何操作。
TIME: 2007-2-13 18:29:16   IP: Protected

某位仁兄的疑问:

对于采用流水库,我有一个疑问,那就是在建立索引的情况下,查找第一个记录和最后一个记录的时间是一样的,不管其数据量多么庞大,因为记录指针的表示范围是不变的,指针驱动磁盘走向到某个扇区去读取数据,只要不是跨设备读取,就不会什么效率问题出现。因此,采用流水库是不是一个多余的做法?

  说到系统效率慢的问题,我在具有上百万条记录的数据库中读取一个只有几十条记录的表,发现效率并没有受影响,而在读取具有庞大数据量的表时,如果检索不当,会出现网络崩溃的现象,而如果我只运行select top 10 * from table 这样的语句时,并没有受到效率的影响,可想而知,数据库的运行效率并不是记录的增长或者是数据库容量的变大而出现效率低下。

  那么是什么原因导致大数据量而效率低下的问题呢?那应该是设计的缺陷。有以下几点:
  第一:系统分析不够。导致不清楚需求,大量采用如同select * from xxx的语句进行检索,不加业务条件或对业务条件理解不够。
  第二:数据库设计没有效率。在业务需求不清楚的情况下,如果数据库设计还不够稳健,那可是件悲惨的事情,没有效率的数据库在数据量小的情况下一般难以表现出来,而到量级情况下,问题暴露无疑。这不能说是数据库管理系统的问题,而是设计者并没有按照数据库设计规范来做。

  数据库不是一个简单的记录库,我们应该认真研究数据库的设计思想后再做效率优化,不能简单的设计一个表后就算完了。比如业务数据表,我们将企业发生的所有业务都存储与该表内,那么这张表必定会涉及到很多的外键关联,而且数据量也会变的惊人。而我们可以从容应对,因为根据会计和实际需求,我们并不会去把十年到今天的帐一并汇总,因此不会出现大量数据汇总的情况(当然,有人要这么做的话,那也是说明他有问题了,但顶多失去的是十倍的查询时间罢了),那么我们就没有必要担心上述情况发生。
  根据业务实际需求,查询汇总总归是以某段时间内发生的业务统计,因此,为业务时间字段建立索引是必须的。如果业务还需要对某列进行分类统计,那么该列上也要建立索引。建立索引的作用可以参考数据库开发手册,具体数据库引擎怎么使用索引,那我们没有必要去了解,只要知道,要查询的字段,如果是数量级的表,那就必须建立索引,否则等死。
  说了这么多,其实就是一个,为必要的查询字段建立索引,不要去想着去做什么万能查询,那是程序员偷懒不动脑筋的做法,而且用户对这个功能并不会给多少的掌声,还不如按用户的实际需求,做些实实在在的查询来。
TIME: 2007-2-13 18:32:54   IP: Protected

 

对于采用流水库,我有一个疑问,那就是在建立索引的情况下,查找第一个记录和最后一个记录的时间是一样的,不管其数据量多么庞大,因为记录指针的表示范围是不变的,指针驱动磁盘走向到某个扇区去读取数据,只要不是跨设备读取,就不会什么效率问题出现。因此,采用流水库是不是一个多余的做法?
===============================================================
理论上讲是这样的。然而实践中,开发人员却会遇到各种恶劣的环境,超出普通的预料。记得我曾经带领徒弟编写过FireBird数据库的智能卡售饭程序,结果系统被卖到了某农村的中学里面去了,后来得知那个地方不定期停电,且有大功率设备引起的电磁干扰,服务器是低价的赛扬组装机,每次卖饭,将在20分钟内插入2000条数据。过了几个月,那里的FireBird数据库发生了Crash,里面有很多坏页面。在这种限额的条件下,我们发现数据库的强健性是有一定限度的,不是象想象的那么强壮。流水库的想法也是在那段时间产生的。倘若那时采用了这种分库机制,我敢说即使在这种环境下,该系统用几年也不容易出问题。


说到系统效率慢的问题,我在具有上百万条记录的数据库中读取一个只有几十条记录的表,发现效率并没有受影响,而在读取具有庞大数据量的表时,如果检索不当,会出现网络崩溃的现象,而如果我只运行select top 10 * from table 这样的语句时,并没有受到效率的影响,可想而知,数据库的运行效率并不是记录的增长或者是数据库容量的变大而出现效率低下。
================================================================
理论是这样。然而,我如果想按照业务时期对数据进行备份、删除掉,那么流水库不是非常的方便吗?特别是数据的删除更是如此。其实,这其中有很多的设计上的艺术性。
TIME: 2007-2-13 18:50:35   IP: Protected

数据库的崩溃是否与数据库容量密切相关?在其他问题(频繁停电、、电磁干扰和频繁使用等)得不到解决的情况下,一个月或者更短时间建立一个数据库即可解决问题?
========================================================================
动态建库是一个理念变化,也就是说,“系统不依赖于一个固定的永久性库”。动态建库同时能够分化数据风险,将风险分散到数据的子集上。数据库物理存储的瑕疵是有积累效果的。在极限情况下,FireBird数据库对数据库文件的瑕疵产生有一定的容忍能力。我的经验是,具有2、3个簇错误的gdb文件基本上仍能够继续使用,这样,当系统进入新业务时间的时候,数据库瑕疵就被抛弃在老库中了。这样,系统即使不进行修补、备份、恢复,仍能很好的运行,这样,真正就能够实现“无人值守”的数据库系统了。如果是单个数据库,那么数据库文件错误必须被及时发现、修补,否则会导致整个系统的崩溃,乃至于所有的数据都损失掉。

每次卖饭,将在20分钟内插入2000条数据。几个月可以增加多大的数据库容量?
========================================================================
数据量并不算大,一个月只有几十M的数据量。

不过,我却回想起另一个Case来。有一次,公司里的车牌识别系统在现场出现致命的性能问题,症状是,插入数据奇慢无比,老的数据无法删除,删除速度小于插入速度,系统濒临崩溃的边缘,而且此前系统曾经发生过两次数据库Crash,所有数据损失。公司内部召集几位专家进行情况分析,我也过去看了。结果发现,系统设计极不合理:该系统采用sql server,关键部分是两个自关联表,关联字段是guid类型的字段,车牌识别图片保存在Blob中,数据库目前已经达到了200G,数据库执行SQL滚动删除来删除老数据。后来,我提出了若干改进意见:
1、数据保存在多个数据库中,每个数据采集点采用单独的库,取缔中央数据库;
2、采用自增长整数作为关键字和关联字段,并建立索引;
3、图片不要保存在数据库中,而是存在硬盘上;
4、采用按时间创建动态数据库的方法存储,定期直接删除整个数据库,而不是执行delete from语句
后来,有关人员听取了前两条,问题解决了。

这一点说明,不同的设计思路体现出来的系统的性能和稳定性会有天壤之别。老天爷可不看你用的是不是名牌数据库。用再好的数据库,如果设计不合理,老天爷很快会向你“发难”。所以好的系统,它的构架设计太关键了。
TIME: 2007-2-18 11:29:06   IP: Protected

 

 

如果那个车牌系统换一个思路,采用我说的Firebird加上流水库的机制,数据库结构设计得当,定期滚动删除动态创建的gdb文件,而且同样是把图片保存到blob中,这样设计,我怀疑,系统用个十来年也出不了什么问题。

从那次经历,我也体验到,考验数据库平台的承受极限还真挺容易,不良的设计即便是对于SQL Server这样精良打造的数据库也能够致命。

 

不知道具体瑕疵是怎么出来的,如果定期备份后清空数据库,瑕疵就不会积累,数据资料也可妥善保存,分批保存的资料都可以调出使用。
===================================================
问题就在这里了。如果要达到无人值守的程度,也就是说将数据库维护“傻瓜化”,在现场没有专门的数据管理员的情况下系统能够健壮的被使用,那么“定期备份后清空数据库”的动作就要求高了。另外,按照时间建立新库的另一个着眼点就是性能方面,由于历史数据永远在以前的数据库中,所以单库的查询速度就完全不会因为历史数据的增加而受影响。
当然,按照“理论”来讲,如果建立了索引,那么数据量增加也不会按照正比的幅度降低系统性能,而分库的做法是完全消除了这种因素。但是毕竟,动态建库的风格并不是为了某个特定的目地而提出的。这种风格的设计带来的是一连串的因素的变化,这一点恐怕得在实际设计和运行中才能真正体会、理解到,其用意不是那么简单、具体。概括的说,分库设计的目地,就是把数据库从“时间积累性因素”中脱出来。“时间积累性因素”会在系统的生命周期中衍生出一系列的消极因素来,降低系统的性能和稳定性。

当然,你所说的类似的方法我还能进一步引申,那就是制作自动备份恢复数据库的服务,定时对数据库进行备份+恢复,每次备份恢复后,gdb文件肯定是很干净、紧缩的库结构,数据不丢失,这样看来,好像是“完美了”,然而,从设计的直觉艺术来看,总是给我感觉隐隐的有些不足,最大一点就是,仍然没有彻底的摆脱“时间积累性因素”的阴影。打个不恰当的比方,就是,我感觉动态建库的思路设计的系统用500年问题不大,而用传统的单库设计我不敢这么保证。当然,这是一个比方。

[该帖子由作者于2007年2月18日 19:45:19最后编辑]

 

 

百度的数据库中存储了数十亿网页,查询的速度很快,而且我从没有感觉到它崩溃过,不知怎么弄的。

 

我解释一下你可能会感觉吃惊:这些搜索引擎ISP使用的存储介质,其实根本不是常规意义的数据库,而是根据关键词的网络结构加上分布式文件存储,是ISP自己实现的存储格式,有点像神经元的原理。从存储上,这些isp采用的分布式,而且存储内容的分布式布局都是为搜索而优化的;从检索索引上来看,搜索引擎索引体现的是特殊的网络状数据结构,并不是像我们所想象的放一个SQL Server,搜索的时候执行select where  content like '%xxx%',比这个复杂很多倍。如果是靠数据库的搜索功能,恐怕10万页面就到秒级速度了。

 

中学食堂刷卡用的计算机不可能总是开的,通常情况应该是使用前打开,用完后关闭,关闭计算机前做些维护工作应该并不困难。有些农村地区电压波动很大,瑕疵估计主要是由于电压波动和停电所致。一些精密的仪器往往需要稳压电源,以前买计算机也要配稳压电源的,不应该随着计算机的价格下降就随便降低它的使用条件。
=========================================================
“关闭计算机前做些维护工作应该并不困难”,那是对咱们不困难。可是某些用户却恨不得点一个按钮什么事情都干了,或者恨不得把机器打开,系统就能用,点一个按钮就出报表,剩下的他们什么都不管。对于开发人员来说, 备份数据库司空见惯。然而对于某类用户来说, “做些维护工作”和“免维护”差别太大了。当然,如果是大规模的外企,一般都有专门的DBA,那么你不给他找点事儿他反而无聊。但如果不是这么实力雄厚的企业用户,可就不一定不在乎“做些维护工作”了。
当然,这是一个极端的比方。该买各种设备的当然还得买。只怕UPS、屏蔽罩买了,它又会出现其它意料外事情。用户现场可能会出现各种开发人员意想不到的状况,会造成这类按理说永远不该发生的情况。
负责前台机器维护的是售货员或基层管理人员,而收集的数据需要送到财务部门和管理部门,这些数据将用来核查帐目、财务管理和监督。前台收集来的数据不能随便改动,前台机器的操作必须非常简单,而且操作不能影响数据库中已有的内容。维护数据库的工作由财务部门和管理部门负责,受过中等教育的人不难对数据库进行例行的备份工作,在前台机器与后台数据库之间可设一个开关。
==========================================================
emote 你说的是理想状态。在实际中,你的客户可能就一个主要部门,只有一个操作员兼财务主管。通常这种规模的企业用户是无法划拨专门的数据库管理员的,几十人的小型企业很难有那么分明的部门,他们最希望的就是所用软件系统的简单和透明,不喜欢任何莫名其妙的东西。所以说,我提倡一个概念,就是“数据库系统工具化”、“数据库文档化”,也就是说,数据库系统要做的象Office那样让人一用就会,创建、维护数据库就像操作一个office文档那么容易和轻松。其实Access从易用性上已经基本达到这个程度了。只不过我想让Client/Server数据库也达到这样的效果,在网络环境中创建数据库就像创建一个文档一样容易,在系统的功能设计中,屏蔽任何与业务无关的技术成分。FireBird/Interbase在这方面恰恰有利于实现这个目标,特别是2个重要因素:1、单文件数据库;2、小脚印(客户端只要一个动态库文件)。

受过中等教育的人不难对数据库进行例行的备份工作
==========================================================
你不能老用程序员的思路去揣测用户啊!你觉得“不难”不代表用户也这么认为。我作为开发人员有8年多的开发经历了,还觉得用IBExpert备份、恢复某个GDB库很麻烦呢,光鼠标键盘联合操作就一大串子,更何况用户乎?某些场合,让用户多点一下鼠标,用户都觉得很烦。任何一个操作环节都是可能出现问题的源头。系统能够做到免去这一环节就一定有它的意义和价值,当然不是说不应该提供备份恢复功能,可以把这一功能进行一定的封装,使其自动化。我们可以提供一次性点击鼠标完成备份恢复,但这个和流水库机制是两个领域的东西,谈不上谁替代谁。

[该帖子由作者于2007年2月19日 14:32:02最后编辑]
关于数据库瑕疵方面,不一定是停电和电压不稳才能造成。在某些情况下,例如用户的数据操作引起数据库服务进程死锁、太大的Transaction、数据库服务进程崩溃、栈溢出、操作系统蓝屏都会带来数据库的坏簇。
有那些清理数据库中瑕疵的办法?
==================================
你所说的备份/恢复的方法就是清理数据库瑕疵的最典型的方法。事实上InterBase/FireBird数据库就提倡经常对数据库进行备份恢复,不仅能发现和修正坏的簇,而且还能清理冗余页面。这种维护活动对于基于访问单个库的系统尤为重要。所有的数据库都提供了备份恢复以及数据导入导出功能。

那些数据库容错能力强?数据库崩溃后怎么处理?
===============================================
这些个数据库的容错能力都差不多的。4大数据库:SQL Server, Oracle,  InterBase, FireBird的数据库崩溃我都经历过。数据库崩溃是一件非常麻烦的事情,一般几种数据库都提供一定程度的数据库修复功能,例如IB/FB的gfix工具。对于数据库崩溃的对策主要是对系统的合理配置。硬件上采用硬盘RAID阵列是很好的巩固措施,能够从硬件上强化IO的可靠性。UPS当然必不可少,这是作为数据库服务器所必备的。服务器尽量不要同时用作工作电脑。同时,要经常对数据库进行检测,及时发现错误。一般数据库如果存在的瑕疵不很多的话,数据库往往仍能运行,这时候如果及时地发现和处理、修补,就能有效的避免灾难的发生。很多时候都是数据库的瑕疵滚雪球增多之后,数据库才真正走向彻底崩溃。对于FB/IB数据库而言,有一个非常有用的特性值得一提,就是shadow功能,就是同步镜像数据库,也就是说,数据库文件有多个副本,进行同步IO,当发生崩溃时,可以选择镜像中问题最少的库恢复系统,故障时通常多个Shadow中能找到一个好的副本。
TIME: 2007-2-19 21:32:10   IP: Protected

我觉得数据库中的瑕疵主要来自卖饭时数据的录入过程,如果将卖饭时录入的数据先存于一个公文包中,在检查无误后再将数据转存数据库中,可达到减少数据库中瑕疵的效果。

 

不是录入,是接工业总线,接收从售饭机里面发出的数据包,进行数据库验证查询,然后将消费记录存入数据库。
确实是这样。用公文包也能解决问题,相当于把数据暂存起来。但是又出现一个新的问题,那就是无法在多个监听服务实例运行时验证余额,防止透支,这样的话,那么要么只能有一个服务,要么可以允许多个监听服务,但不验证余额透支。我举这个例子是从数据库的角度来看这种问题,怎样通过加固数据库来加固系统。而针对这个具体案例来说,解决方案很多,不一定是以数据库为出发点,比如果,做一个以共享内存为基础的监听服务即可。
你举那个例子是为了说明“流水数据库”,大概意思是编写一个程序使数据库在容量满了以后,自动创建一个新的数据库,避免在一个数据库中积累过多的瑕疵,是这个意思吧?这个想法看起来不错,这样一来数据库用起来方便、放心。
版主我不太相信你说的,要是数据库发生改动那升级所有的库就会是一个很复杂而且很费时的一个过程,如果通用产品使用这种结构,那维护成本不是高得吓人吗?
请版主详细说明一下,谢谢!

 

应该设定一个数据库版本号,版本号存放到一个生成器中,程序的功能集运行之前应该先查询数据库版本号。另外,数据库每当做一次更改,就把相应的ddl记录下来,放入程序。当程序检查版本号是老版本,那么就执行该DDL。或者也可开发一个累积性数据库升级工具,根据不同的数据库版本执行相应的升级ddl语句。
版主,实不相瞒,我们公司现在做的进销存产品,遇到了一个严重的问题,我们有一个客户使用了我们的产品6年,现在数据库长到了20G,现在作任何操作都比较慢,但是原来数据库里某产品的库存,客户的往来帐款,基本所有的实时数据都是统计原始数据来生成的,客户也不愿意投资升级硬件,看了版主的这个贴子后,我有了一些想法,但是又不知道如何下手,版主有没有一些例子能看一下呢?
你的情况是典型的流水库机制。不过单纯为了提高性能,不一定用流水库。可以用“超前计算法”,在触发器里面直接动态计算统计结果,保存到辅助表中,相当于数据一录入,就已经把结果算出,查询的时候,直接取中间表的值即可。他的原理就是,把计算任务直接分摊到录入的时候。例子没有太合适的。你自己试试看。我记得我的一些帖子曾详细的描述了这种方法,你仔细找找。
如果用流水库,配合中间辅助表,那么系统就会更健壮,性能更好。因为按照业务区间分库的话,统计表的查询条件都可以不要了,直接针对当前业务区间。

 

高手救救我,我按照你的说法做了一个例子,果然很强,但是我想到一个问题,我每次插入数据重新计算临时库中的数据,这些操作都是事务级别的操作,而且我们的客户都是做批发的,每次销售产品都是一箩筐一箩筐的,终端也很多,会不会造成数据插入上的瓶颈,高手你能不能加我QQ

 

没有什么瓶颈。但是这种情况下,还是我曾经说的那个原则,那就是,使Transaction尽量短促,是短小生命周期的Transaction。如果是IB/FB数据库的话,发生锁定冲突的时候,会抛出异常,在程序设计的时候,一定要应对这种异常,提供N次重试机制,N可设定。要把太大的Transaction切割成为小的Transaction。

我有MSN: clxbase@hotmail.com

 

谢谢了,以后还得多多向您请教!

 

 

 

 

posted on 2010-06-09 09:38  A.wei  阅读(706)  评论(0编辑  收藏  举报