学习笔记

 
1 逻辑数据库和表的设计

  数据库的逻辑设计、包括表与表之间的关系是优化关系型数据库性能的核心。一个好的逻辑数据库设计可以为优化数据库和应用程序打下良好的基础。

  标准化的数据库逻辑设计包括用多的、有相互关系的窄表来代替很多列的长数据表。下面是一些使用标准化表的一些好处。

   A: 由于表窄,因此可以使排序和建立索引更为迅速

   B: 由于多表,所以多镞的索引成为可能

   C: 更窄更紧凑的索引

   D: 每个表中可以有少一些的索引,因此可以提高 insert update delete 等的速度,因为这些操作在索引多的情况下会对系统性能产生很大的影响

   E: 更少的空值和更少的多余值,增加了数据库的紧凑性由于标准化,所以会增加了在获取数据时引用表的数目和其间的连接关系的复杂性。太多的表和复杂的连接关系会降低服务器的性能,因此在这两者之间需要综合考虑。

  定义具有相关关系的主键和外来键时应该注意的事项主要是:用于连接多表的主键和参考的键要有相同的数据类型。

   2 索引的设计

   A: 尽量避免表扫描

  检查你的查询语句的 where 子句,因为这是优化器重要关注的地方。包含在 where 里面的每一列( column) 都是可能的侯选索引,为能达到最优的性能,考虑在下面给出的例子:对于在 where 子句中给出了 column1 这个列。

  下面的两个条件可以提高索引的优化查询性能!

  第一:在表中的 column1 列上有一个单索引

  第二:在表中有多索引,但是 column1 是第一个索引的列

  避免定义多索引而 column1 是第二个或后面的索引,这样的索引不能优化服务器性能

  例如:下面的例子用了 pubs 数据库。

   SELECT au_id, au_lname, au_fname FROM authors
   WHERE au_lname = ’White’

  按下面几个列上建立的索引将会是对优化器有用的索引

   ?au_lname
   ?au_lname, au_fname

  而在下面几个列上建立的索引将不会对优化器起到好的作用

   ?au_address
   ?au_fname, au_lname

  考虑使用窄的索引在一个或两个列上,窄索引比多索引和复合索引更能有效。用窄的索引,在每一页上将会有更多的行和更少的索引级别(相对与多索引和复合索引而言),这将推进系统性能。

  对于多列索引, SQL Server 维持一个在所有列的索引上的密度统计(用于联合)和在第一个索引上的 histogram (柱状图)统计。根据统计结果,如果在复合索引上的第一个索引很少被选择使用,那么优化器对很多查询请求将不会使用索引。

  有用的索引会提高 select 语句的性能,包括 insert,uodate,delete

  但是,由于改变一个表的内容,将会影响索引。每一个 insert,update,delete 语句将会使性能下降一些。实验表明,不要在一个单表上用大量的索引,不要在共享的列上(指在多表中用了参考约束)使用重叠的索引。

  在某一列上检查唯一的数据的个数,比较它与表中数据的行数做一个比较。这就是数据的选择性,这比较结果将会帮助你决定是否将某一列作为侯选的索引列,如果需要,建哪一种索引。你可以用下面的查询语句返回某一列的不同值的数目。

   select count(distinct cloumn_name) from table_name
  假设 column_name 是一个 10000 行的表,则看 column_name 返回值来决定是否应该使用,及应该使用什么索引。

   Unique values Index

   5000 Nonclustered index
   20 Clustered index
   3 No index

  镞索引和非镞索引的选择

   <1:> 镞索引是行的物理顺序和索引的顺序是一致的。页级,低层等索引的各个级别上都包含实际的数据页。一个表只能是有一个镞索引。由于 update,delete 语句要求相对多一些的读操作,因此镞索引常常能加速这样的操作。在至少有一个索引的表中,你应该有一个镞索引。

  在下面的几个情况下,你可以考虑用镞索引:

  例如: 某列包括的不同值的个数是有限的(但是不是极少的)

  顾客表的州名列有 50 个左右的不同州名的缩写值,可以使用镞索引。

  例如: 对返回一定范围内值的列可以使用镞索引,比如用 between,>,>=,<,<= 等等来对列进行操作的列上。
   select * from sales where ord_date between ’5/1/93’ and ’6/1/93’
  例如: 对查询时返回大量结果的列可以使用镞索引。
   SELECT * FROM phonebook WHERE last_name = ’Smith’

  当有大量的行正在被插入表中时,要避免在本表一个自然增长(例如, identity 列)的列上建立镞索引。如果你建立了镞的索引,那么 insert 的性能就会大大降低。因为每一个插入的行必须到表的最后,表的最后一个数据页。

  当一个数据正在被插入(这时这个数据页是被锁定的),所有的其他插入行必须等待直到当前的插入已经结束。
 一个索引的叶级页中包括实际的数据页,并且在硬盘上的数据页的次序是跟镞索引的逻辑次序一样的。

   <2:> 一个非镞的索引就是行的物理次序与索引的次序是不同的。一个非镞索引的叶级包含了指向行数据页的指针。

  在一个表中可以有多个非镞索引,你可以在以下几个情况下考虑使用非镞索引。

  在有很多不同值的列上可以考虑使用非镞索引

  例如:一个 part_id 列在一个 part 表中
   select * from employee where emp_id = ’pcm9809f’

  查询语句中用 order by 子句的列上可以考虑使用镞索引

   3 查询语句的设计

   SQL Server 优化器通过分析查询语句,自动对查询进行优化并决定最有效的执行方案。优化器分析查询语句来决定那个子句可以被优化,并针对可以被优化查询的子句来选择有用的索引。最后优化器比较所有可能的执行方案并选择最有效的一个方案出来。

  在执行一个查询时,用一个 where 子句来限制必须处理的行数,除非完全需要,否则应该避免在一个表中无限制地读并处理所有的行。

  例如下面的例子,
   select qty from sales where stor_id=7131

  是很有效的比下面这个无限制的查询

   select qty from sales

  避免给客户的最后数据选择返回大量的结果集。允许 SQL Server 运行满足它目的的函数限制结果集的大小是更有效的。

  这能减少网络 I/O 并能提高多用户的相关并发时的应用程序性能。因为优化器关注的焦点就是 where 子句的查询,以利用有用的索引。在表中的每一个索引都可能成为包括在 where 子句中的侯选索引。为了最好的性能可以遵照下面的用于一个给定列 column1 的索引。

  第一:在表中的 column1 列上有一个单索引

  第二:在表中有多索引,但是 column1 是第一个索引的列不要在 where 子句中使用没有 column1 列索引的查询语句,并避免在 where 子句用一个多索引的非第一个索引的索引。

  这时多索引是没有用的。

   For example, given a multicolumn index on the au_lname, au_fname columns of the authors table in
   the pubs database,
  下面这个 query 语句利用了 au_lname 上的索引
   SELECT au_id, au_lname, au_fname FROM authors
   WHERE au_lname = ’White’
   AND au_fname = ’Johnson’
   SELECT au_id, au_lname, au_fname FROM authors
   WHERE au_lname = ’White’
  下面这个查询没有利用索引,因为他使用了多索引的非第一个索引的索引
   SELECT au_id, au_lname, au_fname FROM authors
   WHERE au_fname = ’Johnson’
 
 
 
操作符优化
     IN 操作符
     IN 写出来的 SQL 的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
     但是用 IN SQL 性能总是比较低的,从 ORACLE 执行的步骤来分析用 IN SQL 与不用 IN SQL 有以下区别:
    ORACLE 试图将其转换成多个表的连接,如果转换不成功则先执行 IN 里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用 IN SQL 至少多了一个转换的过程。一般的 SQL 都可以转换成功,但对于含有分组统计等方面的 SQL 就不能转换了。
     推荐方案:在业务密集的 SQL 当中尽量不采用 IN 操作符。
     NOT IN 操作符
     此操作是强列推荐不使用的,因为它不能应用表的索引。
     推荐方案:用 NOT EXISTS 或(外连接 + 判断为空)方案代替
     <> 操作符(不等于)
     不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。
     推荐方案:用其它相同功能的操作运算代替,如
    a<>0 改为 a>0 or a<0
    a<>’’ 改为 a>’’
     IS NULL IS NOT NULL 操作(判断字段是否为空)
     判断字段是否为空一般是不会应用索引的,因为 B 树索引是不索引空值的。
     推荐方案:
     用其它相同功能的操作运算代替,如
    a is not null 改为 a>0 a>’’ 等。
     不允许字段为空,而用一个缺省值代替空值,如业扩申请中状态字段不允许为空,缺省为申请。
     建立位图索引(有分区的表不能建,位图索引比较难控制,如字段值太多索引会使性能下降,多人更新操作会增加数据块锁的现象)
     > < 操作符(大于或小于操作符)
     大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有 100 万记录,一个数值型字段 A 30 万记录的 A=0 30 万记录的 A=1 39 万记录的 A=2 1 万记录的 A=3 。那么执行 A>2 A>=3 的效果就有很大的区别了,因为 A>2 ORACLE 会先找出为 2 的记录索引再进行比较,而 A>=3 ORACLE 则直接找到 =3 的记录索引。
     LIKE 操作符
    LIKE 操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如 LIKE ‘%5400%’ 这种查询不会引用索引,而 LIKE ‘X5400%’ 则会引用范围索引。一个实际例子:用 YW_YHJBQK 表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成 YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用 YY_BH 的索引进行两个范围的查询,性能肯定大大提高。
 
 
插入数据
 
     向表中添加一个新记录,你要使用 SQL INSERT 语句。这里有一个如何使用这种语句的例子:
    INSERT mytable (mycolumn) VALUES (‘some data’)
     这个语句把字符串 ’some data’ 插入表 mytable mycolumn 字段中。将要被插入数据的字段的名字在第一个括号中指定,实际的数据在第二个括号中给出。
    INSERT 语句的完整句法如下:
    INSERT [INTO] {table_name|view_name} [(column_list)] {DEFAULT VALUES |
    Values_list | select_statement}
     如果一个表有多个字段,通过把字段名和字段值用逗号隔开,你可以向所有的字段中插入数据。假设表 mytable 有三个字段 first_column,second_column, third_column 。下面的 INSERT 语句添加了一条三个字段都有值的完整记录:
    INSERT mytable (first_column,second_column,third_column)
    VALUES (‘some data’,’some more data’,’yet more data’)
     注意 1
     你可以使用 INSERT 语句向文本型字段中插入数据。但是,如果你需要输入很长的字符串,你应该使用 WRITETEXT 语句。这部分内容对本书来说太高级了,因此不加讨论。要了解更多的信息,请参考 Microsoft SQL Sever 的文档。
     如果你在 INSERT 语句中只指定两个字段和数据会怎么样呢?换句话说,你向一个表中插入一条新记录,但有一个字段没有提供数据。在这种情况下,有下面的四种可能:
     如果该字段有一个缺省值,该值会被使用。例如,假设你插入新记录时没有给字段 third_column 提供数据,而这个字段有一个缺省值 ’some value’ 。在这种情况下,当新记录建立时会插入值 ’some value’
     如果该字段可以接受空值,而且没有缺省值,则会被插入空值。
     如果该字段不能接受空值,而且没有缺省值,就会出现错误。你会收到错误信息:
    The column in table mytable may not be null.
     最后,如果该字段是一个标识字段,那么它会自动产生一个新值。当你向一个有标识字段的表中插入新记录时,只要忽略该字段,标识字段会给自己赋一个新值。
     注意 2
     向一个有标识字段的表中插入新记录后,你可以用 SQL 变量 @@identity 来访问新记录
     的标识字段的值。考虑如下的 SQL 语句:
    INSERT mytable (first_column) VALUES(‘some value’)
    INSERT anothertable(another_first,another_second)
    VALUES(@@identity,’some value’)
     如果表 mytable 有一个标识字段,该字段的值会被插入表 anothertable another_first 字段。这是因为变量 @@identity 总是保存最后一次插入标识字段的值。
     字段 another_first 应该与字段 first_column 有相同的数据类型。但是,字段 another_first 不能是应该标识字段。 Another_first 字段用来保存字段 first_column 的值。
 
 
 
 数据库模型的设计是否合理会极大影响系统的使用性能。笔者依据多年来设计和使用数据库的经验,提出以下一些设计原则,供同仁们参考。
  慎用游标( Cursor

  游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的 * 作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机,笔者在某市 住房公积金管理系统 进行日终账户滚积数计息处理时,对一个 10 万个账户的游标处理时导致程序进入了一个无限期的等待(后经测算需 48 小时才能完成) ( 硬件环境: Alpha/4000 128MB RAM ,SCO Unix ,Sybase 11.0) 。经修改程序并改用 UPDATE 语句后,该处理过程得以在 20 分钟之内完成。示例如下:

   Declare Mycursor cursor for select count—no from COUNT   

   Open Mycursor

   Fetch Mycursor into @vcount—no

   While (@@sqlstatus=0)

   Begin

   If @vcount—no=′   条件 1

*
1

   If @vcount—no=′   条件 2

*
2

...

   Fetch Mycursor into @vcount—no

   End

     ...

  改为

   Update COUNT set * 1 for 条件 1

   Update COUNT set * 2 for 条件 2

...

  在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行 * 作,这样,可使性能得到明显提高。笔者在某地市 电信收费系统 数据库后台程序设计中,对一个表( 3 万行中符合条件的 30 多行数据)进行游标 * ( 硬件环境: PC 服务器, P 266 64MB RAM ,Windows NT4.0 MS SQL Server 6.5)

  示例如下:

Create
tmp / 定义临时表 /

     ( 字段 1

     字段 2

       ... )

   Insert into tmp select from TOTAL where 条件

   Declare Mycursor cursor for select from tmp / *对临时表定义游标* /

     ...

  索引 (Index) 的使用技巧

  创建索引一般有两个目的:维护被索引列的惟一性和提供快速访问表中数据的策略。大型数据库有两种索引,即簇索引和非簇索引,一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的尾部;而建立了簇索引的表,其数据在物理上会按照簇索引键的顺序存储,一个表只允许有一个簇索引,因此,根据 B 树结构,可以理解添加任何一种索引均能提高按索引列查询的速度,但与此同时会降低插入、更新、删除 * 作的性能,尤其是当填充因子( Fill Factor )较大时。所以对索引较多的表进行频繁的插入、更新、删除 * 作时,建表和索引时应设置较小的填充因子,以便在各数据页中留下较多的自由空间,减少页分割及重新组织的工作。

  数据的一致性和完整性

  为了保证数据库的一致性和完整性,设计人员往往会设计过多的表间关联( Relation ),尽可能地降低数据冗余。表间关联是一种强制性措施,建立后,对父表( Parent Table )和子表 (Child Table) 的插入、更新、删除 * 作均要占用系统的开销,另外,最好不要用 Identify 属性字段作为主键与子表关联。如果数据冗余低,数据的完整性容易得到保证,但增加了表间连接查询的 * 作。为了提高系统的响应时间,合理的数据冗余也是必要的。使用规则( Rule )和约束( Check )来防止系统 * 作人员误输入造成数据的错误是,设计人员的另一种常用手段,但是,不必要的规则和约束也会占用系统的不必要开销,需要注意的是,约束对数据的有效性验证要比规则快。所有这些,设计人员在设计阶段应根据系统 * 作的类型、频度加以均衡考虑。

  事务的陷阱

  事务是在一次性完成的一组 * 作。虽然这些 * 作是单个的 * 作, SQL Server 能够保证这组 * 作要么全部都完成,要么一点儿都不做。正是大型数据库的这一特性,使得数据的完整性得到了极大的保证。

  众所周知, SQL Server 为每个独立的 SQL 语句都提供了隐含的事务控制,使得每个 DML 的数据 * 作得以完整提交或回滚,但是 SQL Server 还提供了显式事务控制语句,如:

   BEGIN TRANSACTION 开始一个事务

   COMMIT TRANSACTION 提交一个事务

   ROLLBACK TRANSACTION 回滚一个事务

  事务可以嵌套,可以通过全局变量 @@trancount 检索到连接的事务处理嵌套层次。要特别注意的是,每个显示或隐含的事物开始都使得该变量加 1 ,每个事务的提交使该变量减 1 ,每个事务的回滚都会使得该变量置 0 ,而只有当该变量为 0 时的事务提交(最后一个提交语句时),才把物理数据写入磁盘。

  数据类型的选择

  数据类型的合理选择对于数据库的性能和 * 作具有很大的影响,有关这方面的书籍也有不少的阐述,笔者这里主要介绍几点经验:

   1. Identify 字段不要作为表的主键与其它表关联,这将会影响到该表的数据迁移。

   2. Text Image 字段属指针型数据,主要用来存放二进制大型对象( BLOB )。这类数据的 * 作相比其它数据类型较慢,因此要避开使用。

   3. 日期型字段的优点是有众多的日期函数支持,因此,在日期的大小比较、加减 * 作上非常简单。但是,在按照日期作为条件的查询 * 作也要用函数,相比其它数据类型速度上就慢许多 , 因为用函数作为查询的条件时,服务器无法用先进的性能策略来优化查询而只能进行表扫描遍历每行。
 
 

1 部分 - 设计数据库之前
1.
考察现有环境
在设计一个新数据库时,你不但应该仔细研究业务需求而且还要考察现有的系统。大多数数据库项目都不是从头开始建立的;通常,机构内总会存在用来满足特定需求的现有系统(可能没有实现自动计算)。显然,现有系统并不完美,否则你就不必再建立新系统了。但是对旧系统的研究可以让你发现一些可能会忽略的细微问题。一般来说,考察现有系统对你绝对有好处。
2.
定义标准的对象命名规范
一定要定义数据库对象的命名规范。对数据库表来说,从项目一开始就要确定表名是采用复数还是单数形式。此外还要给表的别名定义简单规则(比方说,如果表名是一个单词,别名就取单词的前 4 个字母;如果表名是两个单词,就各取两个单词的前两个字母组成 4 个字母长的别名;如果表的名字由 3 个单词组成,你不妨从头两个单词中各取一个然后从最后一个单词中再取出两个字母,结果还是组成 4 字母长的别名,其余依次类推)对工作用表来说,表名可以加上前缀 WORK_ 后面附上采用该表的应用程序的名字。表内的列[字段]要针对键采用一整套设计规则。比如,如果键是数字类型,你可以用 _N 作为后缀;如果是字符类型则可以采用 _C 后缀。对列[字段]名应该采用标准的前缀和后缀。再如,假如你的表里有好多“money”字段,你不妨给每个列[字段]增加一个 _M 后缀。还有,日期列[字段]最好以 D_ 作为名字打头。
检查表名、报表名和查询名之间的命名规范。你可能会很快就被这些不同的数据库要素的名称搞糊涂了。假如你坚持统一地命名这些数据库的不同组成部分,至少你应该在这些对象名字的开头用 TableQuery 或者 Report 等前缀加以区别。
如果采用了 Microsoft Access,你可以用 qryrpttbl mod 等符号来标识对象(比如 tbl_Employees)。我在和 SQL Server 打交道的时候还用过 tbl 来索引表,但我用 sp_company (现在用 sp_feft_)标识存储过程,因为在有的时候如果我发现了更好的处理办法往往会保存好几个拷贝。我在实现 SQL Server 2000 时用 udf_ (或者类似的标记)标识我编写的函数。
3.
工欲利其器
采用理想的数据库设计工具,比如:SyBase 公司的 PowerDesign,她支持 PBVBDelphe 等语言,通过 ODBC 可以连接市面上流行的 30 多个数据库,包括 dBaseFoxProVFPSQL Server 等,今后有机会我将着重介绍 PowerDesign 的使用。
4.
获取数据模式资源手册
正在寻求示例模式的人可以阅读《数据模式资源手册》一书,该书由 Len SilverstonW. H. Inmon Kent Graziano 编写,是一本值得拥有的最佳数据建模图书。该书包括的章节涵盖多种数据领域,比如人员、机构和工作效能等。其他的你还可以参考:[1]萨师煊 王珊著 数据库系统概论(第二版)高等教育出版社 1991[2][] Steven M.Bobrowski Oracle 7 与客户/服务器计算技术从入门到精通 刘建元等译 电子工业出版社,1996[3]周中元 信息系统建模方法() 电子与信息化 1999年第3期,1999
5.
畅想未来,但不可忘了过去的教训
我发现询问用户如何看待未来需求变化非常有用。这样做可以达到两个目的:首先,你可以清楚地了解应用设计在哪个地方应该更具灵活性以及如何避免性能瓶颈;其次,你知道发生事先没有确定的需求变更时用户将和你一样感到吃惊。
一定要记住过去的经验教训!我们开发人员还应该通过分享自己的体会和经验互相帮助。即使用户认为他们再也不需要什么支持了,我们也应该对他们进行这方面的教育,我们都曾经面临过这样的时刻当初要是这么做了该多好..”
6.
在物理实践之前进行逻辑设计
在深入物理设计之前要先进行逻辑设计。随着大量的 CASE 工具不断涌现出来,你的设计也可以达到相当高的逻辑水准,你通常可以从整体上更好地了解数据库设计所需要的方方面面。
7.
了解你的业务
在你百分百地确定系统从客户角度满足其需求之前不要在你的 ER(实体关系)模式中加入哪怕一个数据表(怎么,你还没有模式?那请你参看技巧 9)。了解你的企业业务可以在以后的开发阶段节约大量的时间。一旦你明确了业务需求,你就可以自己做出许多决策了。
一旦你认为你已经明确了业务内容,你最好同客户进行一次系统的交流。采用客户的术语并且向他们解释你所想到的和你所听到的。同时还应该用可能、将会和必须等词汇表达出系统的关系基数。这样你就可以让你的客户纠正你自己的理解然后做好下一步的 ER 设计。
8.
创建数据字典和 ER 图表
一定要花点时间创建 ER 图表和数据字典。其中至少应该包含每个字段的数据类型和在每个表内的主外键。创建 ER 图表和数据字典确实有点费时但对其他开发人员要了解整个设计却是完全必要的。越早创建越能有助于避免今后面临的可能混乱,从而可以让任何了解数据库的人都明确如何从数据库中获得数据。
有一份诸如 ER 图表等最新文档其重要性如何强调都不过分,这对表明表之间关系很有用,而数据字典则说明了每个字段的用途以及任何可能存在的别名。对 SQL 表达式的文档化来说这是完全必要的。
9.
创建模式
一张图表胜过千言万语:开发人员不仅要阅读和实现它,而且还要用它来帮助自己和用户对话。模式有助于提高协作效能,这样在先期的数据库设计中几乎不可能出现大的问题。模式不必弄的很复杂;甚至可以简单到手写在一张纸上就可以了。只是要保证其上的逻辑关系今后能产生效益。
10.
从输入输出下手
在定义数据库表和字段需求(输入)时,首先应检查现有的或者已经设计出的报表、查询和视图(输出)以决定为了支持这些输出哪些是必要的表和字段。举个简单的例子:假如客户需要一个报表按照邮政编码排序、分段和求和,你要保证其中包括了单独的邮政编码字段而不要把邮政编码糅进地址字段里。
11.
报表技巧
要了解用户通常是如何报告数据的:批处理还是在线提交报表?时间间隔是每天、每周、每月、每个季度还是每年?如果需要的话还可以考虑创建总结表。系统生成的主键在报表中很难管理。用户在具有系统生成主键的表内用副键进行检索往往会返回许多重复数据。这样的检索性能比较低而且容易引起混乱。
12.
理解客户需求
看起来这应该是显而易见的事,但需求就是来自客户(这里要从内部和外部客户的角度考虑)。不要依赖用户写下来的需求,真正的需求在客户的脑袋里。你要让客户解释其需求,而且随着开发的继续,还要经常询问客户保证其需求仍然在开发的目的之中。一个不变的真理是:只有我看见了我才知道我想要的是什么必然会导致大量的返工,因为数据库没有达到客户从来没有写下来的需求标准。而更糟的是你对他们需求的解释只属于你自己,而且可能是完全错误的。
2 部分 - 设计表和字段
<script language=JavaScript> document.write("");ad_dst = ad_dst+1; </script>
1.
检查各种变化
我在设计数据库的时候会考虑到哪些数据字段将来可能会发生变更。比方说,姓氏就是如此(注意是西方人的姓氏,比如女性结婚后从夫姓等)。所以,在建立系统存储客户信息时,我倾向于在单独的一个数据表里存储姓氏字段,而且还附加起始日和终止日等字段,这样就可以跟踪这一数据条目的变化。
2.
采用有意义的字段名
有一回我参加开发过一个项目,其中有从其他程序员那里继承的程序,那个程序员喜欢用屏幕上显示数据指示用语命名字段,这也不赖,但不幸的是,她还喜欢用一些奇怪的命名法,其命名采用了匈牙利命名和控制序号的组合形式,比如 cbo1txt2txt2_b 等等。
除非你在使用只面向你的缩写字段名的系统,否则请尽可能地把字段描述的清楚些。当然,也别做过头了,比如 Customer_Shipping_Address_Street_Line_1,虽然很富有说明性,但没人愿意键入这么长的名字,具体尺度就在你的把握中。
3.
采用前缀命名
如果多个表里有好多同一类型的字段(比如 FirstName),你不妨用特定表的前缀(比如 CusLastName)来帮助你标识字段。
时效性数据应包括最近更新日期/时间字段。时间标记对查找数据问题的原因、按日期重新处理/重载数据和清除旧数据特别有用。
5.
标准化和数据驱动
数据的标准化不仅方便了自己而且也方便了其他人。比方说,假如你的用户界面要访问外部数据源(文件、XML 文档、其他数据库等),你不妨把相应的连接和路径信息存储在用户界面支持表里。还有,如果用户界面执行工作流之类的任务(发送邮件、打印信笺、修改记录状态等),那么产生工作流的数据也可以存放在数据库里。预先安排总需要付出努力,但如果这些过程采用数据驱动而非硬编码的方式,那么策略变更和维护都会方便得多。事实上,如果过程是数据驱动的,你就可以把相当大的责任推给用户,由用户来维护自己的工作流过程。
6.
标准化不能过头
对那些不熟悉标准化一词(normalization)的人而言,标准化可以保证表内的字段都是最基础的要素,而这一措施有助于消除数据库中的数据冗余。标准化有好几种形式,但 Third Normal Form3NF)通常被认为在性能、扩展性和数据完整性方面达到了最好平衡。简单来说,3NF 规定:
*
表内的每一个值都只能被表达一次。
*
表内的每一行都应该被唯一的标识(有唯一键)。
*
表内不应该存储依赖于其他键的非键信息。
遵守 3NF 标准的数据库具有以下特点:有一组表专门存放通过键连接起来的关联数据。比方说,某个存放客户及其有关定单的 3NF 数据库就可能有两个表:Customer OrderOrder 表不包含定单关联客户的任何信息,但表内会存放一个键值,该键指向 Customer 表里包含该客户信息的那一行。
更高层次的标准化也有,但更标准是否就一定更好呢?答案是不一定。事实上,对某些项目来说,甚至就连 3NF 都可能给数据库引入太高的复杂性。
为了效率的缘故,对表不进行标准化有时也是必要的,这样的例子很多。曾经有个开发餐饮分析软件的活就是用非标准化表把查询时间从平均 40 秒降低到了两秒左右。虽然我不得不这么做,但我绝不把数据表的非标准化当作当然的设计理念。而具体的操作不过是一种派生。所以如果表出了问题重新产生非标准化的表是完全可能的。
7. Microsoft Visual FoxPro
报表技巧
如果你正在使用 Microsoft Visual FoxPro,你可以用对用户友好的字段名来代替编号的名称:比如用 Customer Name 代替 txtCNaM。这样,当你用向导程序 [Wizards,台湾人称为精灵’] 创建表单和报表时,其名字会让那些不是程序员的人更容易阅读。
8.
不活跃或者不采用的指示符
增加一个字段表示所在记录是否在业务中不再活跃挺有用的。不管是客户、员工还是其他什么人,这样做都能有助于再运行查询的时候过滤活跃或者不活跃状态。同时还消除了新用户在采用数据时所面临的一些问题,比如,某些记录可能不再为他们所用,再删除的时候可以起到一定的防范作用。
9.
使用角色实体定义属于某类别的列[字段]
在需要对属于特定类别或者具有特定角色的事物做定义时,可以用角色实体来创建特定的时间关联关系,从而可以实现自我文档化。
这里的含义不是让 PERSON 实体带有 Title 字段,而是说,为什么不用 PERSON 实体和 PERSON_TYPE 实体来描述人员呢?比方说,当 John Smith, Engineer 提升为 John Smith, Director 乃至最后爬到 John Smith, CIO 的高位,而所有你要做的不过是改变两个表 PERSON PERSON_TYPE 之间关系的键值,同时增加一个日期/时间字段来知道变化是何时发生的。这样,你的 PERSON_TYPE 表就包含了所有 PERSON 的可能类型,比如 AssociateEngineerDirectorCIO 或者 CEO 等。
还有个替代办法就是改变 PERSON 记录来反映新头衔的变化,不过这样一来在时间上无法跟踪个人所处位置的具体时间。
10.
采用常用实体命名机构数据
组织数据的最简单办法就是采用常用名字,比如:PERSONORGANIZATIONADDRESS PHONE 等等。当你把这些常用的一般名字组合起来或者创建特定的相应副实体时,你就得到了自己用的特殊版本。开始的时候采用一般术语的主要原因在于所有的具体用户都能对抽象事物具体化。
有了这些抽象表示,你就可以在第 2 级标识中采用自己的特殊名称,比如,PERSON 可能是 EmployeeSpousePatientClientCustomerVendor 或者 Teacher 等。同样的,ORGANIZATION 也可能是 MyCompanyMyDepartmentCompetitorHospitalWarehouseGovernment 等。最后 ADDRESS 可以具体为 SiteLocationHomeWorkClientVendorCorporate FieldOffice 等。
采用一般抽象术语来标识事物的类别可以让你在关联数据以满足业务要求方面获得巨大的灵活性,同时这样做还可以显著降低数据存储所需的冗余量。
11.
用户来自世界各地
在设计用到网络或者具有其他国际特性的数据库时,一定要记住大多数国家都有不同的字段格式,比如邮政编码等,有些国家,比如新西兰就没有邮政编码一说。
12.
数据重复需要采用分立的数据表
如果你发现自己在重复输入数据,请创建新表和新的关系。
13.
每个表中都应该添加的 3 个有用的字段
* dRecordCreationDate
,在 VB 下默认是 Now(),而在 SQL Server 下默认为 GETDATE()
* sRecordCreator
,在 SQL Server 下默认为 NOT NULL DEFAULT USER
* nRecordVersion
,记录的版本标记;有助于准确说明记录中出现 null 数据或者丢失数据的原因
14.
对地址和电话采用多个字段
描述街道地址就短短一行记录是不够的。Address_Line1Address_Line2 Address_Line3 可以提供更大的灵活性。还有,电话号码和邮件地址最好拥有自己的数据表,其间具有自身的类型和标记类别。
过分标准化可要小心,这样做可能会导致性能上出现问题。虽然地址和电话表分离通常可以达到最佳状态,但是如果需要经常访问这类信息,或许在其父表中存放首选信息(比如 Customer 等)更为妥当些。非标准化和加速访问之间的妥协是有一定意义的。
15.
使用多个名称字段
我觉得很吃惊,许多人在数据库里就给 name 留一个字段。我觉得只有刚入门的开发人员才会这么做,但实际上网上这种做法非常普遍。我建议应该把姓氏和名字当作两个字段来处理,然后在查询的时候再把他们组合起来。
我最常用的是在同一表中创建一个计算列[字段],通过它可以自动地连接标准化后的字段,这样数据变动的时候它也跟着变。不过,这样做在采用建模软件时得很机灵才行。总之,采用连接字段的方式可以有效的隔离用户应用和开发人员界面。
6.
提防大小写混用的对象名和特殊字符
过去最令我恼火的事情之一就是数据库里有大小写混用的对象名,比如 CustomerData。这一问题从 Access Oracle 数据库都存在。我不喜欢采用这种大小写混用的对象命名方法,结果还不得不手工修改名字。想想看,这种数据库/应用程序能混到采用更强大数据库的那一天吗?采用全部大写而且包含下划符的名字具有更好的可读性(CUSTOMER_DATA),绝对不要在对象名的字符之间留空格。
17.
小心保留词
要保证你的字段名没有和保留词、数据库系统或者常用访问方法冲突,比如,最近我编写的一个 ODBC 连接程序里有个表,其中就用了 DESC 作为说明字段名。后果可想而知!DESC DESCENDING 缩写后的保留词。表里的一个 SELECT * 语句倒是能用,但我得到的却是一大堆毫无用处的信息。
18.
保持字段名和类型的一致性
在命名字段并为其指定数据类型的时候一定要保证一致性。假如字段在某个表中叫做“agreement_number”,你就别在另一个表里把名字改成“ref1”。假如数据类型在一个表里是整数,那在另一个表里可就别变成字符型了。记住,你干完自己的活了,其他人还要用你的数据库呢。
19.
仔细选择数字类型
SQL 中使用 smallint tinyint 类型要特别小心,比如,假如你想看看月销售总额,你的总额字段类型是 smallint,那么,如果总额超过了 $32,767 你就不能进行计算操作了。
20.
删除标记
在表中包含一个删除标记字段,这样就可以把行标记为删除。在关系数据库里不要单独删除某一行;最好采用清除数据程序而且要仔细维护索引整体性。
21.
避免使用触发器
触发器的功能通常可以用其他方式实现。在调试程序时触发器可能成为干扰。假如你确实需要采用触发器,你最好集中对它文档化。
22.
包含版本机制
建议你在数据库中引入版本控制机制来确定使用中的数据库的版本。无论如何你都要实现这一要求。时间一长,用户的需求总是会改变的。最终可能会要求修改数据库结构。虽然你可以通过检查新字段或者索引来确定数据库结构的版本,但我发现把版本信息直接存放到数据库中不更为方便吗?。
23.
给文本字段留足余量
ID
类型的文本字段,比如客户 ID 或定单号等等都应该设置得比一般想象更大,因为时间不长你多半就会因为要添加额外的字符而难堪不已。比方说,假设你的客户 ID 10 位数长。那你应该把数据库表字段的长度设为 12 或者 13 个字符长。这算浪费空间吗?是有一点,但也没你想象的那么多:一个字段加长 3 个字符在有 1 百万条记录,再加上一点索引的情况下才不过让整个数据库多占据 3MB 的空间。但这额外占据的空间却无需将来重构整个数据库就可以实现数据库规模的增长了。身份证的号码从 15 位变成 18 位就是最好和最惨痛的例子。
24.
[字段]命名技巧
我们发现,假如你给每个表的列[字段]名都采用统一的前缀,那么在编写 SQL 表达式的时候会得到大大的简化。这样做也确实有缺点,比如破坏了自动表连接工具的作用,后者把公共列[字段]名同某些数据库联系起来,不过就连这些工具有时不也连接错误嘛。举个简单的例子,假设有两个表:
Customer
OrderCustomer 表的前缀是 cu_,所以该表内的子段名如下:cu_name_idcu_surnamecu_initials cu_address 等。Order 表的前缀是 or_,所以子段名是:
or_order_id
or_cust_name_idor_quantity or_description 等。
这样从数据库中选出全部数据的 SQL 语句可以写成如下所示:
Select * From Customer, Order Where cu_surname = "MYNAME" ;
and cu_name_id = or_cust_name_id and or_quantity = 1
在没有这些前缀的情况下则写成这个样子(用别名来区分):
Select * From Customer, Order Where Customer.surname = "MYNAME" ;
and Customer.name_id = Order.cust_name_id and Order.quantity = 1
1 SQL 语句没少键入多少字符。但如果查询涉及到 5 个表乃至更多的列[字段]你就知道这个技巧多有用了。

 
 
 
 
对于ORACLE数据库的数据存取,主要有四个不同的调整级别,第一级调整是操作系统级包括硬件平台,第二级调整是ORACLE
            RDBMS级的调整,第三级是数据库设计级的调整,最后一个调整级是SQL级。通常依此四级调整级别对数据库进行调整、优化,数据库的整体性能会得到很大的改善。下面从九个不同方面介绍ORACLE数据库优化设计方案。
            一.数据库优化自由结构OFA(Optimal flexible Architecture)
            数据库的逻辑配置对数据库性能有很大的影响,为此,ORACLE公司对表空间设计提出了一种优化结构OFA。使用这种结构进行设计会大大简化物理设计中的数据管理。优化自由结构OFA,简单地讲就是在数据库中可以高效自由地分布逻辑数据对象,因此首先要对数据库中的逻辑对象根据他们的使用方式和物理结构对数据库的影响来进行分类,这种分类包括将系统数据和用户数据分开、一般数据和索引数据分开、低活动表和高活动表分开等等。
            数据库逻辑设计的结果应当符合下面的准则:(1)把以同样方式使用的段类型存储在一起;(2)按照标准使用来设计系统;(3)存在用于例外的分离区域;(4)最小化表空间冲突;(5)将数据字典分离。
            二、充分利用系统全局区域SGA(SYSTEM GLOBAL AREA)
            SGA是oracle数据库的心脏。用户的进程对这个内存区发送事务,并且以这里作为高速缓存读取命中的数据,以实现加速的目的。正确的SGA大小对数据库的性能至关重要。SGA包括以下几个部分:
            1、数据块缓冲区(data block buffer
            cache)是SGA中的一块高速缓存,占整个数据库大小的1%-2%,用来存储从数据库重读取的数据块(表、索引、簇等),因此采用least
            recently used (LRU,最近最少使用)的方法进行空间管理。
            2、字典缓冲区。该缓冲区内的信息包括用户账号数据、数据文件名、段名、盘区位置、表说明和权限,它也采用LRU方式管理。
            3、重做日志缓冲区。该缓冲区保存为数据库恢复过程中用于前滚操作。
            4、SQL共享池。保存执行计划和运行数据库的SQL语句的语法分析树。也采用LRU算法管理。如果设置过小,语句将被连续不断地再装入到库缓存,影响系统性能。
            另外,SGA还包括大池、JAVA池、多缓冲池。但是主要是由上面4种缓冲区构成。对这些内存缓冲区的合理设置,可以大大加快数据查询速度,一个足够大的内存区可以把绝大多数数据存储在内存中,只有那些不怎么频繁使用的数据,才从磁盘读取,这样就可以大大提高内存区的命中率。
            三、规范与反规范设计数据库
            1、规范化
            范式是符合某一级别的关系模式的集合,根据约束条件的不同,一般有1NF、2NF、3NF三种范式。规范化理论是围绕这些范式而建立的。规范化的基本思想是逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”,即采用“一事一地”的模式设计原则,因此,所谓规范化实质上就是概念的单一化。数据库中数据规范化的优点是减少了数据冗余,节约了存储空间,相应逻辑和物理的I/O次数减少,同时加快了增、删、改的速度。但是一个完全规范化的设计并不总能生成最优的性能,因为对数据库查询通常需要更多的连接操作,从而影响到查询的速度。故有时为了提高某些查询或应用的性能而有意破坏规范规则,即反规范化。
            2、反规范化
            ⑴反规范的必要性
            是否规范化的程度越高越好呢?答案是否定的,应根据实际需要来决定,因为“分离”越深,产生的关系越多,结构越复杂。关系越多,连接操作越频繁,而连接操作是最费时间的,在数据库设计中特别对以查询为主的数据库设计来说,频繁的连接会严重影响查询速度。所以,在数据库的设计过程中有时故意保留非规范化约束,或者规范化以后又反规范,这样做通常是为了改进数据库的查询性能,加快数据库系统的响应速度。
            ⑵反规范技术
            在进行反规范设计之前,要充分考虑数据的存取需求,常用表的大小、特殊的计算、数据的物理存储等。常用的反规范技术有合理增加冗余列、派生列,或重新组表几种。反规范化的好处是降低连接操作的需求、降低外码和索引数目,减少表的个数,从而提高查询速度,这对于性能要求相对较高的数据库系统来说,能有效地改善系统的性能,但相应的问题是可能影响数据的完整性,加快查询速度的同时降低修改速度。
            3、数据库设计中的优化策略
            数据应当按两种类别进行组织:频繁访问的数据和频繁修改的数据。对于频繁访问但是不频繁修改的数据,内部设计应当物理不规范化。对于频繁修改但并不频繁访问的数据,内部设计应当物理规范化。比较复杂的方法是将规范化的表作为逻辑数据库设计的基础,然后再根据整个应用系统的需要,物理地非规范化数据。规范与反规范都是建立在实际的操作基础之上的约束,脱离了实际两者都没有意义。只有把两者合理地结合在一起,才能相互补充,发挥各自的优点。
            四、合理设计和管理表
            1、利用表分区
            分区将数据在物理上分隔开,不同分区的数据可以制定保存在处于不同磁盘上的数据文件里。这样,当对这个表进行查询时,只需要在表分区中进行扫描,而不必进行FTS(Full
            Table
            Scan,全表扫描),明显缩短了查询时间,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个精心设置的分区可以将数据传输对磁盘I/O竞争均匀地分散开。
            2、避免出现行连接和行迁移
            在建立表时,由于参数pctfree和pctused不正确的设置,数据块中的数据会出现行链接和行迁移,也就是同一行的数据不保存在同一的数据块中。如果在进行数据查询时遇到了这些数据,那么为了读出这些数据,磁头必须重新定位,这样势必会大大降低数据库执行的速度。因此,在创建表时,就应该充分估计到将来可能出现的数据变化,正确地设置这两个参数,尽量减少数据库中出现行链接和行迁移。
            3、控制碎片
            碎片(fragmentation)是对一组非邻接的数据库对象的描述。碎片意味着在执行数据库的功能时要耗费额外的资源(磁盘I/O,磁盘驱动的循环延迟,动态扩展,链接的块等),并浪费大量磁盘空间。当两个或多个数据对象在相同的表空间中,会发生区间交叉。在动态增长中,对象的区间之间不再相互邻接。为了消除区间交叉将静态的或只有小增长的表放置在一个表空间中,而把动态增长的对象分别放在各自的表空间中。在create
            table、、create index、create tablespace、create
            cluster时,在storage子句中的参数的合理设置,可以减少碎片的产生。
            4、别名的使用
            别名是大型数据库的应用技巧,就是表名、列名在查询中以一个字母为别名,查询速度要比建连接表快1.5倍。
            5、回滚段的交替使用
            由于数据库配置对应用表具有相对静止的数据字典和极高的事务率特点。而且数据库的系统索引段、数据段也具有相对静止,并发现在应用中最高的负荷是回滚段表空间。把回滚段定义为交替引用,这样就达到了循环分配事务对应的回滚段,可以使磁盘负荷很均匀地分布。
            五、索引Index的优化设计
            1、管理组织索引
            索引可以大大加快数据库的查询速度,索引把表中的逻辑值映射到安全的RowID,因此索引能进行快速定位数据的物理地址。但是有些DBA发现,对一个大型表建立的索引,并不能改善数据查询速度,反而会影响整个数据库的性能。这主要是和SGA的数据管理方式有关。ORACLE在进行数据块高速缓存管理时,索引数据比普通数据具有更高的驻留权限,在进行空间竞争时,ORACLE会先移出普通数据。对一个建有索引的大型表的查询时,索引数据可能会用完所有的数据块缓存空间,ORACLE不得不频繁地进行磁盘读写来获取数据,因此在对一个大型表进行分区之后,可以根据相应的分区建立分区索引。如果对这样大型表的数据查询比较频繁,或者干脆不建索引。另外,DBA创建索引时,应尽量保证该索引最可能地被用于where子句中,如果对查询只简单地制定一个索引,并不一定会加快速度,因为索引必须指定一个适合所需的访问路径。2、聚簇的使用
            Oracle提供了另一种方法来提高查询速度,就是聚簇(Cluster)。所谓聚簇,简单地说就是把几个表放在一起,按一定公共属性混合存放。聚簇根据共同码值将多个表的数据存储在同一个Oracle块中,这时检索一组Oracle块就同时得到两个表的数据,这样就可以减少需要存储的Oracle块,从而提高应用程序的性能。
            3、优化设置的索引,就必须充分利用才能加快数据库访问速度。ORACLE要使用一个索引,有一些最基本的条件:1)、where子名中的这个字段,必须是复合索引的第一个字段;2)、where子名中的这个字段,不应该参与任何形式的计算。
            六、多CPU和并行查询PQO(Parallel Query Option)方式的利用
            1、尽量利用多个CPU处理器来执行事务处理和查询
            CPU的快速发展使得ORACLE越来越重视对多CPU的并行技术的应用,一个数据库的访问工作可以用多个CPU相互配合来完成,加上分布式计算已经相当普遍,只要可能,应该将数据库服务器和应用程序的CPU请求分开,或将CPU请求从一个服务器移到另一个服务器。对于多CPU系统尽量采用Parallel
            Query Option(PQO,并行查询选项)方式进行数据库操作。
            2、使用Parallel Query Option(PQO,并行查询选择)方式进行数据查询
            使用PQO方式不仅可以在多个CPU间分配SQL语句的请求处理,当所查询的数据处于不同的磁盘时,一个个独立的进程可以同时进行数据读取。
            3、使用SQL*Loader Direct Path选项进行大量数据装载
            使用该方法进行数据装载时,程序创建格式化数据块直接写入数据文件中,不要求数据库内核的其他I/O。
            七、实施系统资源管理分配计划
            ORACLE提供了Database Resource
            Manager(DRM,数据库资源管理器)来控制用户的资源分配,DBA可以用它分配用户类和作业类的系统资源百分比。在一个OLDP系统中,可给联机用户分配75%的CPU资源,剩下的25%留给批用户。另外,还可以进行CPU的多级分配。除了进行CPU资源分配外,DRM还可以对资源用户组执行并行操作的限制。
            八、使用最优的数据库连接和SQL优化方案
            1、使用直接的OLE DB数据库连接方式。
            通过ADO可以使用两种方式连接数据库,一种是传统的ODBC方式,一种是OLE DB方式。ADO是建立在OLE
            DB技术上的,为了支持ODBC,必须建立相应的OLE DB到ODBC的调用转换,而使用直接的OLE
DB方式则不需转换,从而提高处理速度。
            2、使用Connection Pool机制
            在数据库处理中,资源花销最大的是建立数据库连接,而且用户还会有一个较长的连接等待时间。解决的办法就是复用现有的Connection,也就是使用Connection
            Pool对象机制。
            Connection
            Pool的原理是:IIS+ASP体系中维持了一个连接缓冲池,这样,当下一个用户访问时,直接在连接缓冲池中取得一个数据库连接,而不需重新连接数据库,因此可以大大地提高系统的响应速度。
            3、高效地进行SQL语句设计
            通常情况下,可以采用下面的方法优化SQL对数据操作的表现:
            (1)减少对数据库的查询次数,即减少对系统资源的请求,使用快照和显形图等分布式数据库对象可以减少对数据库的查询次数。
            (2)尽量使用相同的或非常类似的SQL语句进行查询,这样不仅充分利用SQL共享池中的已经分析的语法树,要查询的数据在SGA中命中的可能性也会大大增加。
            (3)限制动态SQL的使用,虽然动态SQL很好用,但是即使在SQL共享池中有一个完全相同的查询值,动态SQL也会重新进行语法分析。
            (4)避免不带任何条件的SQL语句的执行。没有任何条件的SQL语句在执行时,通常要进行FTS,数据库先定位一个数据块,然后按顺序依次查找其它数据,对于大型表这将是一个漫长的过程。
            (5)如果对有些表中的数据有约束,最好在建表的SQL语句用描述完整性来实现,而不是用SQL程序中实现。
            (6)可以通过取消自动提交模式,将SQL语句汇集一组执行后集中提交,程序还可以通过显式地用COMMIT和ROLLBACL进行提交和回滚该事务。
            (7)检索大量数据时费时很长,设置行预取数则能改善系统的工作表现,设置一个最大值,当SQL语句返回行超过该值,数值库暂时停止执行,除非用户发出新的指令,开始组织并显示数据,而不是让用户继续等待。
            九、充分利用数据的后台处理方案减少网络流量
            1、合理创建临时表或视图
            所谓创建临时表或视图,就是根据需要在数据库基础上创建新表或视图,对于多表关联后再查询信息的可建新表,对于单表查询的可创建视图,这样可充分利用数据库的容量大、可扩充性强等特点,所有条件的判断、数值计算统计均可在数据库服务器后台统一处理后追加到临时表中,形成数据结果的过程可用数据库的过程或函数来实现。
            2、数据库打包技术的充分利用
            利用数据库描述语言编写数据库的过程或函数,然后把过程或函数打成包在数据库后台统一运行包即可。
            3、数据复制、快照、视图,远程过程调用技术的运用
            数据复制,即将数据一次复制到本地,这样以后的查询就使用本地数据,但是只适合那些变化不大的数据。使用快照也可以在分布式数据库之间动态复制数据,定义快照的自动刷新时间或手工刷新,以保证数据的引用参照完整性。调用远程过程也会大大减少因频繁的SQL语句调用而带来的网络拥挤。
            总之,对所有的性能问题,没有一个统一的解决方法,但ORACLE提供了丰富的选择环境,可以从ORACLE数据库的体系结构、软件结构、模式对象以及具体的业务和技术实现出发,进行统筹考虑。提高系统性能需要一种系统的整体的方法,在对数据库进行优化时,应对应用程序、I/O子系统和操作系统(OS)进行相应的优化。优化是有目的地更改系统的一个或多个组件,使其满足一个或多个目标的过程。对Oracle来说,优化是进行有目的的调整组件级以改善性能,即增加吞吐量,减少响应时间。如果DBA能从上述九个方面综合考虑优化方案,相信多数ORACLE应用可以做到按最优的方式来存取数据。
         
 
 
Loadrunner
Memory: 内存使用情况可能是系统性能中最重要的因素。如果系统 页交换 频繁,说明内存不足。 页交换 是使用称为 页面 的单位,将固定大小的代码和数据块从 RAM 移动到磁盘的过程,其目的是为了释放内存空间。尽管某些页交换使 Windows 2000 能够使用比实际更多的内存,也是可以接受的,但频繁的页交换将降低系统性能。减少页交换将显著提高系统响应速度。要监视内存不足的状况,请从以下的对象计数器开始:
Available Mbytes:
可用物理内存数 . 如果 Available Mbytes 的值很小( 4 MB 或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。

page/sec:
表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放工作集空间的页面数。一般如果 pages/sec 持续高于几百,那么您应该进一步研究页交换活动。有可能需要增加内存,以减少换页的需求(你可以把这个数字乘以 4k 就得到由此引起的硬盘数据流量)。 Pages/sec 的值很大不一定表明内存有问题,而可能是运行使用内存映射文件的程序所致。

page read/sec:
页的硬故障, page/sec 的子集,为了解析对内存的引用,必须读取页文件的次数。阈值为 >5. 越低越好。大数值表示磁盘读而不是缓存读。
由于过多的页交换要使用大量的硬盘空间,因此有可能将导致将页交换内存不足与导致页交换的磁盘瓶径混淆。因此,在研究内存不足不太明显的页交换的原因时,您必须跟踪如下的磁盘使用情况计数器和内存计数器:
Physical Disk/ % Disk Time
Physical Disk/ Avg.Disk Queue Length
例如,包括 Page Reads/sec % Disk Time Avg.Disk Queue Length 。如果页面读取操作速率很低,同时 % Disk Time Avg.Disk Queue Length 的值很高,则可能有磁盘瓶径。但是,如果队列长度增加的同时页面读取速率并未降低,则内存不足。
要确定过多的页交换对磁盘活动的影响,请将 Physical Disk/ Avg.Disk sec/Transfer Memory/ Pages/sec 计数器的值增大数倍。如果这些计数器的计数结果超过了 0.1 ,那么页交换将花费百分之十以上的磁盘访问时间。如果长时间发生这种情况,那么您可能需要更多的内存。

Page Faults/sec:
每秒软性页面失效的数目(包括有些可以直接在内存中满足而有些需要从硬盘读取)较 page/sec 只表明数据不能在内存的指定工作集中立即使用。
Cache Bytes
:文件系统缓存( File System Cache ),默认情况下为 50% 的可用物理内存。如 IIS5.0 运行内存不够时,它会自动整理缓存。需要关注该计数器的趋势变化
如果您怀疑有内存泄露,请监视 Memory/ Available Bytes Memory/ Committed Bytes ,以观察内存行为,并监视您认为可能在泄露内存的进程的 Process/Private Bytes Process/Working Set Process/Handle Count 。如果您怀疑是内核模式进程导致了泄露,则还应该监视 Memory/Pool Nonpaged Bytes Memory/ Pool Nonpaged Allocs Process(process_name)/ Pool Nonpaged Bytes

Pages per second :
每秒钟检索的页数。该数字应少于每秒一页。
Process
%Processor Time:
被处理器消耗的处理器时间数量。如果服务器专用于 sql server, 可接受的最大上限是 80-85%
Page Faults/sec:
将进程产生的页故障与系统产生的相比较,以判断这个进程对系统页故障产生的影响。
Work set:
处理线程最近使用的内存页,反映了每一个进程使用的内存页的数量。如果服务器有足够的空闲内存,页就会被留在工作集中,当自由内存少于一个特定的阈值时,页就会被清除出工作集。
Inetinfo:Private Bytes:
此进程所分配的无法与其它进程共享的当前字节数量。如果系统性能随着时间而降低,则此计数器可以是内存泄漏的最佳指示器。
Processor :监视 处理器 系统 对象计数器可以提供关于处理器使用的有价值的信息,帮助您决定是否存在瓶颈。
%Processor Time:
如果该值持续超过 95% ,表明瓶颈是 CPU 。可以考虑增加一个处理器或换一个更快的处理器。
%User Time:
表示耗费 CPU 的数据库操作,如排序,执行 aggregate functions 等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。
%Privileged Time
:( CPU 内核时间)是在特权模式下处理线程执行代码所花时间的百分比。如果该参数值和 "Physical Disk" 参数值一直很高,表明 I/O 有问题。可考虑更换更快的硬盘系统。另外设置 Tempdb in RAM ,减低 "max async IO" "max lazy writer IO" 等措施都会降低该值。
此外,跟踪计算机的服务器工作队列当前长度的 Server Work Queues/ Queue Length 计数器会显示出处理器瓶颈。队列长度持续大于 4 则表示可能出现处理器拥塞。此计数器是特定时间的值,而不是一段时间的平均值。
% DPC Time:
越低越好。在多处理器系统中,如果这个值大于 50% 并且 Processor:% Processor Time 非常高,加入一个网卡可能会提高性能,提供的网络已经不饱和。
Thread
ContextSwitches/sec: (
实例化 inetinfo dllhost 进程 ) 如果你决定要增加线程字节池的大小,你应该监视这三个计数器(包括上面的一个)。增加线程数可能会增加上下文切换次数,这样性能不会上升反而会下降。如果十个实例的上下文切换值非常高,就应该减小线程字节池的大小。
Physical Disk:
%Disk Time %:
指所选磁盘驱动器忙于为读或写入请求提供服务所用的时间的百分比。如果三个计数器都比较大,那么硬盘不是瓶颈。如果只有 %Disk Time 比较大,另外两个都比较适中,硬盘可能会是瓶颈。在记录该计数器之前,请在 Windows 2000 的命令行窗口中运行 diskperf -yD 。若数值持续超过 80% ,则可能是内存泄漏。
Avg.Disk Queue Length:
指读取和写入请求 ( 为所选磁盘在实例间隔中列队的 ) 的平均数。该值应不超过磁盘数的 1.5~2 倍。要提高性能,可增加磁盘。注意:一个 Raid Disk 实际有多个磁盘。
Average Disk Read/Write Queue Length:
指读取 ( 写入 ) 请求 ( 列队 ) 的平均数。
Disk Reads(Writes)/s:
物理磁盘上每秒钟磁盘读、写的次数。两者相加,应小于磁盘设备最大容量。
Average Disksec/Read:
指以秒计算的在此盘上读取数据的所需平均时间。
Average Disk sec/Transfer:
指以秒计算的在此盘上写入数据的所需平均时间。
Network Interface

Bytes Total/sec :
为发送和接收字节的速率,包括帧字符在内。判断网络连接速度是否是瓶颈,可以用该计数器的值和目前网络的带宽比较
SQLServer 性能计数器:
Access Methods(
访问方法 ) 用于监视访问数据库中的逻辑页的方法。
. Full Scans/sec(
全表扫描 / ) 每秒不受限的完全扫描数。可以是基本表扫描或全索引扫描。如果这个计数器显示的值比 1 2 高,应该分析你的查询以确定是否确实需要全表扫描,以及 S Q L 查询是否可以被优化。
. Page splits/sec(
页分割 / ) 由于数据更新操作引起的每秒页分割的数量。
Buffer Manager(
缓冲器管理器 ) :监视 Microsoft&reg; SQL Server? 如何使用: 内存存储数据页、内部数据结构和过程高速缓存;计数器在 SQL Server 从磁盘读取数据库页和将数据库页写入磁盘时监视物理 I/O 监视 SQL Server 所使用的内存和计数器有助于确定: 是否由于缺少可用物理内存存储高速缓存中经常访问的数据而导致瓶颈存在。如果是这样, SQL Server 必须从磁盘检索数据。 是否可通过添加更多内存或使更多内存可用于数据高速缓存或 SQL Server 内部结构来提高查询性能。
SQL Server
需要从磁盘读取数据的频率。与其它操作相比,例如内存访问,物理 I/O 会耗费大量时间。尽可能减少物理 I/O 可以提高查询性能。
.Page Reads/sec
:每秒发出的物理数据库页读取数。这一统计信息显示的是在所有数据库间的物理页读取总数。由于物理 I/O 的开销大,可以通过使用更大的数据高速缓存、智能索引、更高效的查询或者改变数据库设计等方法,使开销减到最小。
.Page Writes/sec (.
写的页 / ) 每秒执行的物理数据库写的页数。
.Buffer Cache Hit Ratio.
缓冲池 Buffer Cache/Buffer Pool )中没有被读过的页占整个缓冲池中所有页的比率。可在高速缓存中找到而不需要从磁盘中读取的页的百分比。这一比率是高速缓存命中总数除以自 SQL Server 实例启动后对高速缓存的查找总数。经过很长时间后,这一比率的变化很小。由于从高速缓存中读数据比从磁盘中读数据的开销要小得多,一般希望这一数值高一些。通常,可以通过增加 SQL Server 可用的内存数量来提高高速缓存命中率。计数器值依应用程序而定,但比率最好为 90% 或更高。增加内存直到这一数值持续高于 90% ,表示 90% 以上的数据请求可以从数据缓冲区中获得所需数据。
. Lazy Writes/sec(
惰性写 / ) 惰性写进程每秒写的缓冲区的数量。值最好为 0
Cache Manager(
高速缓存管理器 ) 对象提供计数器,用于监视 Microsoft&reg; SQL Server? 如何使用内存存储对象,如存储过程、特殊和准备好的 Transact-SQL 语句以及触发器。
. Cache Hit Ratio(
高速缓存命中率,所有 Cache” 的命中率。在 SQL Server 中, Cache 可以包括 Log Cache Buffer Cache 以及 Procedure Cache ,是一个总体的比率。 ) 高速缓存命中次数和查找次数的比率。对于查看 SQL Server 高速缓存对于你的系统如何有效,这是一个非常好的计数器。如果这个值很低,持续低于 80% ,就需要增加更多的内存。
Latches(
) 用于监视称为闩锁的内部 SQL Server 资源锁。监视闩锁以明确用户活动和资源使用情况,有助于查明性能瓶颈。
. Average Latch Wait Ti m e ( m s ) (
平均闩等待时间 ( 毫秒 )) 一个 SQL Server 线程必须等待一个闩的平均时间,以毫秒为单位。如果这个值很高,你可能正经历严重的竞争问题。
. Latch Waits/sec (
闩等待 / ) 在闩上每秒的等待数量。如果这个值很高,表明你正经历对资源的大量竞争。
Locks(
) 提供有关个别资源类型上的 SQL Server 锁的信息。锁加在 SQL Server 资源上(如在一个事务中进行的行读取或修改),以防止多个事务并发使用资源。例如,如果一个排它 (X) 锁被一个事务加在某一表的某一行上,在这个锁被释放前,其它事务都不可以修改这一行。尽可能少使用锁可提高并发性,从而改善性能。可以同时监视 Locks 对象的多个实例,每个实例代表一个资源类型上的一个锁。
. Number of Deadlocks/sec(
死锁的数量 / ) 导致死锁的锁请求的数量
. Average Wait Time(ms) (
平均等待时间 ( 毫秒 )) 线程等待某种类型的锁的平均等待时间
. Lock Requests/sec(
锁请求 / ) 每秒钟某种类型的锁请求的数量。
Memory manager:
用于监视总体的服务器内存使用情况,以估计用户活动和资源使用,有助于查明性能瓶颈。监视 SQL Server 实例所使用的内存有助于确定:
是否由于缺少可用物理内存存储高速缓存中经常访问的数据而导致瓶颈存在。如果是这样, SQL Server 必须从磁盘检索数据。
是否可以通过添加更多内存或使更多内存可用于数据高速缓存或 SQL Server 内部结构来提高查询性能。
Lock blocks:
服务器上锁定块的数量,锁是在页、行或者表这样的资源上。不希望看到一个增长的值。
Total server memory
sql server 服务器当前正在使用的动态内存总量 .
监视 IIS 需要的一些计数器
Internet Information Services Global:
File Cache Hits %
File CacheFlushes File Cache Hits
File Cache Hits %
是全部缓存请求中缓存命中次数所占的比例,反映了 IIS 的文件缓存设置的工作情况。对于一个大部分是静态网页组成的网站,该值应该保持在 80% 左右。而 File Cache Hits 是文件缓存命中的具体值, File CacheFlushes 是自服务器启动之后文件缓存刷新次数,如果刷新太慢,会浪费内存;如果刷新太快,缓存中的对象会太频繁的丢弃生成,起不到缓存的作用。通过比较 File Cache Hits File Cache Flushes 可得出缓存命中率对缓存清空率的比率。通过观察它两个的值,可以得到一个适当的刷新值(参考 IIS 的设置 ObjectTTL MemCacheSize MaxCacheFileSize
Web Service:
Bytes Total/sec:
显示 Web 服务器发送和接受的总字节数。低数值表明该 IIS 正在以较低的速度进行数据传输。
Connection Refused
:数值越低越好。高数值表明网络适配器或处理器存在瓶颈。
Not Found Errors
:显示由于被请求文件无法找到而无法由服务器满足的请求数( HTTP 状态代码 404
CVS 使用经验谈
2005-04-20 , 12.12, jiangliu215 | 3931 x 阅读
来自: UML 工程组织 作者:龚天乙 [2004/11/22]
CVS Concurrent Version System (并行版本系统)的缩写,用于版本管理。在多人团队开发中的作用更加明显。 CVS 的基本工作思路是这样的:在一台服务器上建立一个仓库,仓库里可以存放许多不同项目的源程序。由仓库管理员统一管理这些源程序。这样,就好象只有一个人在修改文件一样。避免了冲突。每个用户在使用仓库之前,首先要把仓库里的项目文件下载到本地。用户做的任何修改首先都是在本地进行,然后用 cvs 命令进行提交,由 cvs 仓库管理员统一 修改。这样就可以做到跟踪文件变化,冲突控制等等。
  由于 CVS 是建立在在原先 Unix 体系里很成熟的 SCCS RCS 的基础上,所以 CVS 多是 Linux UNIX )系统中所使用,本文中服务器端设置也是以 Linux 为例。
  一、 CVS 服务器的安装
  首先确认系统中是否安装 CVS 服务:
   [root@localhost /]# rpm -qa|grep cvs
cvs-1.11.2-cvshome.7x.1
  如果命令输出类似于上面的输出则说明系统已经安装有 cvs ,否则就需要从安装光盘中安装 cvs rpm 包,或者到 http://www.cvshome.org 下载。
   1 、建立 CVSROOT
  目录,因为这里涉及到用户对 CVSROOT 里的文件读写的权限问题,所以比较简单的方法是建立一个组,然后再建立一个属于该组的帐户,而且以后有读写权限的用户都要属于该组。假设我们建一个组叫 cvs ,用户名是 cvsroot 。建组和用户的命令如下
#groupadd cvs
#adduser cvsroot
  生成的用户宿主目录在 /home/cvsroot (根据自己的系统调整)
   2 、用 cvsroot 用户登陆,修改 /home/cvsroot CVSROOT )的权限,赋与同组人有读写的权限: 
   $chmod 771 . (或者 770 应该也可以)
  注意:这一部分工作是按照文档说明做的,是否一定需要这样没有试验,我会在做试验后在以后版本的教程说得仔细一点。如果您有这方面的经验请提供给我,谢谢。
   3 、建立 CVS 仓库,(仍然是 cvsroot 用户),用下面命令:
   $cvs -d /home/cvsroot init
   4 、以 root 身份登陆,修改 /etc/inetd.conf (使用 xinetd 的系统没有此文件)和 /etc/services
  如果用的是 inetd 的系统,在 /etc/inetd.conf 里加入:
  
   cvsserver   stream tcp nowait root /usr/bin/cvs cvs -f --allow-root=/home/cvsroot pserver
  说明:上面的行是单独一整行, /usr/bin/cvs 应该是你的 cvs 版本的命令路径,请根据自己的系统调整. /home/cvsroot 是你建立的 CVSROOT 的路径,也请根据上面建立目录的部分的内容做调整。
  如果是使用 xinetd 的系统,需要在 /etc/xinetd.d/ 目录下创建文件 cvspserver (此名字可以自己定义),内容如下:
   # default: on
   # description: The cvs server sessions;
   service cvsserver
   {
   socket_type = stream
   wait = no
   user = root
   server = /usr/bin/cvs
   server_args = -f --allow-root=/cvsroot pserver
   log_on_failure += USERID
   only_from = 192.168.0.0/24
   }
  其中 only_from 是用来限制访问的,可以根据实际情况不要或者修改。修改该文件权限:
   # chmod 644 cvspserver
  在 /etc/services 里加入:
   cvsserver 2401/tcp
  说明: cvsserver 是任意的名称,但是不能和已有的服务重名,也要和上面修改 /etc/inetd.conf 那行的第一项一致。
   5 、添加可以使用 CVS 服务的用户到 cvs 组:
  以 root 身份修改 /etc/group ,把需要使用 CVS 的用户名加到 cvs 组里,比如我想让用户 laser gumpwu 能够使用 CVS 服务,那么修改以后的 /etc/group 应该有下面这样一行:
   cvs:x:105:laser,gumpwu
  在你的系统上 GID 可能不是 105 ,没有关系。主要是要把 laser gumpwu 用逗号分隔开写在最后一个冒号后面。当然,象 RedHat 等分发版有类似 linuxconf 这样的工具的话,用工具做这件事会更简单些。
   6 、重起 inetd 使修改生效:
   #killall -HUP inetd
  如果使用的是 xinetd 的系统:
   # /etc/rc.d/init.d/xined restart
然后察看 cvs 服务器是否已经运行:
[root@localhost /]# netstat -lnp|grep 2401
   tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 1041/xinetd
则说明 cvs 服务器已经运行。

  二、管理 CVS 服务器
  服务器可以用了,现在大家最关心的就是如何管理服务器,比如,我想让一些人有读和 / 或写 CVS 仓库的权限,但是不想给它系统权限怎么办呢?
  不难,在 cvs 管理员用户(在我这里是 cvsroot 用户)的家目录里有一个 CVSROOT 目录,这个目录里有三个配置文件, passwd, readers, writers ,我们可以通过设置这三个文件来配置 CVS 服务器,下面分别介绍这几个文件的作用:
   passwd cvs 用户的用户列表文件,它的格式很象 shadow 文件:
   {cvs 用户名 }:[ 加密的口令 ]:[ 等效系统用户名 ]
  如果你希望一个用户只是 cvs 用户,而不是系统用户,那么你就要设置这个文件,刚刚安装完之后这个文件可能不存在,你需要以 cvs 管理员用户手工创建,当然要按照上面格式,第二个字段是该用户的加密口令,就是用 crypt (3) 加密的,你可以自己写一个程序来做加密,也可以用我介绍的偷懒的方法:先创建一个系统用户,名字和 cvs 用户一样,口令就是准备给它的 cvs 用户口令,创建完之后从 /etc/shadow 把该用户第二个字段拷贝过来,然后再把这个用户删除。这个方法对付数量少的用户比较方便,人一多就不合适了,而且还有冲突条件 (race condition) 的安全隐患,还要 root 权限,实在不怎么样。不过权益之计而已。写一个小程序并不难,可以到 linuxforum 的编程版搜索一下,有个朋友已经写了一个贴在上面了。
第三个字段就是等效系统用户名,实际上就是赋与一个 cvs 用户一个等效的系统用户的权限,看下面的例子你就明白它的功能了。
readers
:有 cvs 读权限的用户列表文件。就是一个一维列表。在这个文件中的用户对 cvs 只有读权限。
writers
:有 cvs 写权限的用户的列表文件。和 readers 一样,是一个一维列表。在这个文件中的用户对 cvs 有写权限。
上面三个文件在缺省安装的时候可能都不存在,需要我们自己创建,好吧,现在还是让我们用一个例子来教学吧。假设我们有下面几个用户需要使用 cvs
laser, gumpwu, henry, betty, anonymous

其中 laser gumpwu 是系统用户,而 henry, betty, anonymous 我们都不想给系统用户权限,并且 betty anonymous 都是只读用户,而且 anonymous 更是连口令都没有。那么好,我们先做一些准备工作,先创建一个 cvspub 用户,这个用户的责任是代表所有非系统用户的 cvs 用户读写 cvs 仓库。
#adduser
...
然后编辑 /etc/group ,令 cvspub 用户在 cvs 组里,同时把其它有系统用户权限的用户加到 cvs 组里。(见上文)
然后编辑 cvs 管理员家目录里 CVSROOT/passwd 文件,加入下面几行:
laser:$xxefajfka;faffa33:cvspub
gumpwu:$ajfaal;323r0ofeeanv:cvspub
henry:$fajkdpaieje:cvspub
betty:fjkal;ffjieinfn/:cvspub
anonymous::cvspub
注意:上面的第二个字段(分隔符为 : )是密文口令,你要用程序或者用我的土办法生成。
编辑 readers 文件,加入下面几行:
anonymous
betty
编辑 writers 文件,加入下面几行:
laser
gumpwu
henry
注意: writers 中的用户不能在 readers 中,要不然不能上传更新文件。

对于使用 CVS 的用户要修改它的环境变量,例如 laser 用户的环境变量,打开 /home/laser laser 的宿主目录)下的 .bash_profile 文件,加入
CVSROOT=/home/cvsroot
export CVSROOT
laser 登陆就可以建立 CVS 项目,如果要 root 使用,可以修改 /etc/profile 文件。

现在我们各项都设置好了,那么怎么用呢,我在这里写一个最简单的(估计也是最常用的)命令介绍:
首先,建立一个新的 CVS 项目,一般我们都已经有一些项目文件了,这样我们可以用下面步骤生成一个新的 CVS 项目:
进入到你的已有项目的目录,比如叫 cvstest
$cd cvstest
运行命令:
$cvs import -m "this is a cvstest project" cvstest v_0_0_1 start
说明: import cvs 的命令之一,表示向 cvs 仓库输入项目文件。 -m 参数后面的字串是描述文本,随便写些有意义的东西,如果不加 -m
数,那么 cvs 会自动运行一个编辑器(一般是 vi ,但是可以通过修改环境变量 EDITOR 来改成你喜欢用的编辑器。)让你输入信息, cvstest 是项目名称(实际上是仓库名,在 CVS 服务器上会存储在以这个名字命名的仓库里。)
v_0_0_1
是这个分支的总标记。没啥用(或曰不常用。)
start
是每次 import 标识文件的输入层次的标记,没啥用。
这样我们就建立了一个 CVS 仓库了。
建立 CVS 仓库的文件夹应该是 干净 的文件夹,即只包括源码文件和描述的文件加,而不应该包括编译过的文件代码等!
三、使用 CVS
winCVS
是一个很好的 CVS 客户端软件,在 http://cnpack.cosoft.org.cn/down/wincvsdailyguide.pdf 可以下载到这个软件的使用手册。这里不在赘述了。
四、用 CVS 管理项目
本人正在一加公司从事该公司 ERP 项目的开发,在没有使用 CVS 的时候,多次出现了由于不同的开发人员修改同一程序,而导致程序错误,解决版本控制问题迫在眉睫。
由于这个项目采用 Linux 平台下 JAVA 开发,使用的开发工具 Jbulider 是支持 CVS 进行项目管理的,作为主程序员,我决定采用 CVS 进行版本控制,首先参照上文在 Linux 服务器上建立了 CVS 服务,然后我把我本地的工程文件传至服务器。
例如:我的工程文件在 F:/ERP 下,我把 ERP 下的 erp.jpx 文件、 defaultroot 文件夹和 src 文件夹上传至服务器 /usr/local/erp 下,然后登陆 Linux 服务器,登陆的用户是 CVS 的用户,其环境变量要正确(我的用户名为 admin
#cd /usr/local/erp
#cvs import -m "this is a ERP project" erp v_0_0_1 start
这样名为 erp CVS 仓库就建立了。
之后开发小组的成员可以用 winCVS 把该项目下载到本地:
打开 winCVS
点击工具栏 Create -> Create a new repository... 弹出窗口
Grenral
Enter the CVSROOT
填写 admin@192.168.1.9:/home/cvsroot 其中 admin cvs 的用户,在本例中 admin 也是 linux 的系统用户, 192.168.1.9 是服务器的地址, /home/cvsroot CVS 的主目录,参考上文。
Authentication
中选择 "passwd file on the cvs server"
Use version
中选择 cvs 1.10 (Standard)
其它项默认即可。
确认后,点工具栏 Admin --> Login... 会提示输入密码,输入密码后,看看 winCvs 的状态栏。如果提示
*****CVS exited normally with code 0*****
表示登录正常。
点击工具栏 Create --> Checkout module... 弹出对话框,其中的 Checkout settings 项中
Enter the module name and path on the server
填写 erp ,即我们建立的名为 erp CVS 仓库
Local folder to checkout to
选择要下载到本地的目录,我选了 F:/myerp
其它项目可以默认,确定后就可以下载到本地了,在 F:/myerp/ 下会有一个 erp 文件夹,其文件结构和 F:/erp 下的文件结构是一样的。
Jbulider 打开 F:/myerp/erp/ 下的 erp.jpx 文件,这个工程文件就可以使用了。
Jbuilder 的工具栏 Team --> Select Project VCS 弹出对话框,选择 CVS
对于你要进行修改的文件,在 Project View 中点中该文件,然后点右键,探出快捷菜单,选择 CVS --> CVS Edit "xxxx.java (文件名) "
第一次使用可能会提示 CVS 服务器的密码。
在修改之前还要选择 CVS --> Update "xxxx.java (文件名) "
修改之后选择 CVS --> Commit "xxxx.java (文件名) "
这样,修改的文件就保存到 CVS 服务器了, Update 的目的是下载、比较文件。每次在修改之前都 Update ,保持最新版本。
CVS
在项目管理使用中确实起到了良好的效果,仔细研究 CVS 的命令,可以更好的发挥 CVS 在版本控制上的能力。
 
 
( 一)、用例之间的关系
1、扩展关系:插入基用例所未知的附加行为,只有基用例能实例化。
2、概括关系:一般化关系,特殊用例继承和增加了基用例的特征。
3、包含关系:用例可以简单的合并其他的用例,将其作为自身行为的片段。
分类和聚集是表达主体一部分关系的关联
( 二)、uml中的各种视图和图
1、试图
用例视图(use case view),强调从用户的角度看到的或需要的系统功能,是被称为参与者的外部用户所能观察到的系统功能的模型图;
逻辑视图(logical view),展现系统的静态或结构组成及特征,也称为结构模型视图(structural model view)或静态视图(static view);
并发视图(concurrent view),体现了系统的动态或行为特征,也称为行为模型视图(behavioral model view)、动态视图(dynamic view);
组件视图(component view),体现了系统实现的结构和行为特征,也称为实现模型视图(implementation model view) ;
配置视图(deployment view),体现了系统实现环境的结构和行为特征,也称为环境模型视图(environment model view)或物理视图(physical view)。
2 、九种图
用例图use case diagram,描述系统功能
类图class diagram,描述系统的静态结构
对象图object diagram,描述系统在某个时刻的静态结构
序列图sequence diagram,按时间顺序描述系统元素间的交互
协作图Collaboration diagram,按照时间和空间顺序描述系统元素间的交互和它们之间的关系
状态图state diagram,描述了系统元素的状态条件和响应
活动图activity diagram,描述了系统元素的活动
组件图component diagram,描述了实现系统的元素的组织
配置图deployment diagram,描述了环境元素的配置,并把实现系统的元素映射到配置上
3 、视图和图的关系
用户模型视图:用例图
结构模型视图:类图、对象图
行为模型视图:序列图、协作图、状态图、活动图(动态图)
实现模型视图:组件图
环境模型视图:配置图
4 、模型和图的关系
用例模型--用用例图、顺序图、协作图、状态图和活 动图描述。
分析、设计模型--用类图和对象图、顺序图、协作图、状态图和活动图描述。
实现模型--可用组件图、顺序图和协作图描述。
实施模型--配置图
测试模型--测试模型引用了所有其他模型,所以它使用他们对应的所有图。
5 、序列图和协作图是同构的,它们相互之间可以转化而不损失信息。
 
 
( 一)、有关需求
1、业务需求反映了组织机构或客户对系统、产品高层次的目标要求,通常在项目定义与范围文档中予以说明。
2、用户需求描述了用户使用产品必须要完成的任务,应在使用实例或方案脚本中予以说明。
3、功能需求定义了开发人员必须实现的软件功能,使用户利用系统能够完成他们的任务,从而满足业务需求。
4、非功能性的需求描述了系统展现给用户的行为和执行的操作等,它包括产品必须遵从的标准、规范和约束,操作界面的具体细节和构造上的限制等。
5、需求分析报告所说明的功能需求充分描述了软件系统所应具有的外部行为,在开发、测试、质量保证、项目管理以及相关项目功能中起着重要作用。
( 二)、有关测试
单元测试(模块测试):针对每个模块进行的测试,可从程序的内部结构出发设计测试用例,多个模块可以平行地对立地测试。通常在编码阶段进行,必要的时候要制作驱动模块和桩模块。
集成测试:在单元测试的基础上,将所有模块按照设计要求组装成为系统,必须精心计划,应提交集成测试计划、集成测试规格说明和集成测试分析报告。
确认测试:验证软件的功能和性能及其它特性是否与用户的要求一致。
系统测试:将软件放在整个计算机环境下,包括软硬件平台、某些支持软件、数据和人员等,在实际运行环境下进行一系列的测试。
回归测试:即全部或部分地重复已做过的测试。
黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检测每个功能是否都能正常使用,在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数锯而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性。黑盒测试方法主要有等价类划分、边值分析、因—果图、错误推测等,主要用于软件确认测试。 “黑盒”法着眼于程序外部结构、不考虑内部逻辑结构、针对软件界面和软件功能进行测试。“黑盒”法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。实际上测试情况有无穷多个,人们不仅要测试所有合法的输入,而且还要对那些不合法但是可能的输入进行测试。
白盒测试也称结构测试或逻辑驱动测试,它是知道产品内部工作过程,可通过测试来检测产品内部动作是否按照规格说明书的规定正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都有能按预定要求正确工作,而不顾它的功能,白盒测试的主要方法有逻辑驱动、基路测试等,主要用于软件验证。“白盒”法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。“白盒”法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。贯穿程序的独立路径数是天文数字。但即使每条路径都测试了仍然可能有错误。第一,穷举路径测试决不能查出程序违反了设计规范,即程序本身是个错误的程序。第二,穷举路径测试不可能查出程序中因遗漏路径而出错。第三,穷举路径测试可能发现不了一些与数据相关的错误
 
 
二、有关知识点:unix shell的变量
$HOME 使用者自己的目录
$PATH 执行命令时所搜寻的目录
$TZ 时区
$MAILCHECK 每隔多少秒检查是否有新的信件
$PS1 在命令列时的提示号
$PS2 当命令尚未打完时,Shell 要求再输入时的提示号
$MANPATH man 指令的搜寻路径
$0 这个程式的执行名字
$n 这个程式的第n个参数值,n=1..9 $* 这个程式的所有参数
$# 这个程式的参数个数
$$ 这个程式的PID $! 执行上一个背景指令的PID
$? 执行上一个指令的返回值
 
 
WAVE 音效合成与 MIDI 音乐的合成是声卡最主要的功能。其中 WAVE 音效合成是由声卡的 ADC 模数转换器和 DAC 数模转换器来完成的。模拟音频信号经 ADC 转换后为数字音频后,以文件形式存放在磁盘等介质上,就成为声音文件。这类文件我们称之为 wave form 文件,通常以 .wav 为扩展名,因此也称为 wav 文件。 WAVE 音效可以逼真地模拟出自然界的各种声音效果,如风雨声、枪炮声、人声等等。可惜的是 wav 文件需要占用很大的贮存空间,以一首使用 16bit 44.1Khz 采样精度录制的《 My heart will go on 》为例, 5 10 秒的长度需要占用近 55M 的空间(计算公式:文件长度 = 采样位数×采样频率×时间×声道数)。为了节省存贮空间,人们使用各种算法对 wav 文件进行压缩,时下极为流行 MPEG Leyer-3 就是一种高压缩比低失真的压缩算法。同样以上述的歌曲为例,压缩为 MP3 文件后,长度仅为 5M 左右。
   MIDI
,即乐器数字化接口,是一种用于计算机与电子乐器之间进行数据交换的通信标准。 MIDI 文件(通常以 .mid 为文件扩展名)记录了用于合成 MIDI 音乐的各种控制指令,包括发声乐器、所用通道、音量大小等。由于 MIDI 文件本身不包含任何数字音频信号,因而所占的贮存空间比 wav 文件要小得多。 MIDI 文件回放需要通过声卡的 MIDI 合成器合成为不同的声音,而合成的方式有 FM (调频)与 Wave table (波表)两种。
  
早期的声卡及目前大多数廉价的声卡都采用的 FM 合成方式。 FM 合成是通过振荡器产生正弦波,然后再叠加成各种乐器的波形。由于振荡器成本较高,即使是 OPL3 这类高档的 FM 合成器也只提供了 4 个振荡器,仅能产生 20 种复音。因此 MIDI 音乐听起来生硬呆板,带有明显的人工合成色彩,即所谓的电子声。为了使 MIDI 合成
  
FM 合成不同,波表合成是采用真实的声音样本进行回放。声音样本记录了各种真实乐器的波形采样,并保存在声卡上的 ROM RAM 中。因此,要分辨一块声卡是否波表声卡,只需看卡上有没有 ROM RAM 存储器即可。创通的 Sound Blaster AWE32 是第一块广为流行的波表声卡。该卡采用了 EMU8000 波表处理芯片,提供 16 MIDI 通道和 32 位的复音效果。板上自带 2M ROM ,并可通过增购波表子卡扩充至 28M ,其 MIDI 回放效果绝非 SB16 可比。无可否认,通过波表合成的声音比 FM 合成的声音更为丰富和真实,但由于需要额外的存储器贮存音色库,因此成本也较高。而且音色库越大,所需的存储器就越多,相应地成本也就越高。那么,对于购买普通的 FM 声卡的朋友,能否体会到波表合成的美妙音色呢?可以!如果你的声卡上有波表接口的话,如“同维二号”等,你可以通过购买专用的波表子卡实现波表合成。如果没有子卡接口,你也可以使用“软波表”这类模拟软件,在 FM 声卡上实现波表回放效果。
   WinGroov
VSC-88 YXG-50 是时下最为流行的软波表,其原理跟硬波表一样,都是采用了真实的声音样本进行回放。只是硬波表的音色库是存放在声卡的 ROM RAM 中,而软波表的音色库则以文件的形式存放在硬盘里,需要时再通过 CPU 进行调用。由于软波表是通过 CPU 的实时运算来回放 MIDI 音效,因此软波表对系统要求较高,通常要在 Pentium 133/16M RAM 以上才能获得较为满意的效果。
1 .确定建立数据库的目的和收集数据
   
数据库设计过程的第一个阶段是确定建立数据库的目的和收集数据。通常,我们也把确定建立数据库的目的称为需求分析。需求分析的任务就是通过详细调查要处理的对象来明确用户的各种需求。并且通过调查、收集和分析信息,以了解在数据库中需要存储哪些数据,要完成什么样的数据处理功能。这一过程是数据库设计的起点,它将直接影响到后面各个阶段的设计,并影响到设计结果是否合理和实用。
   
确定目的之后就需要根据目的收集有用的数据。在着手收集数据之前最重要的就是要调查用户的实际需求,然后分析与表达这些需求。调查用户需求的方法有很多,如查阅记录、访谈、开调查会、设计调查表请用户填写或回答相关问题等。其中比较有效的方法是访谈,我们可以借助一些设计合理的调查表来与用户直接交流。通过充分交流,可以了解他们平时是如何使用数据库的,以及对当前信息的要求,进而设计满足用户需求的字段,并根据设计的字段收集数据。
2
.建立概念模型
   
确定建立数据库的目的以及完成数据收集后,就进入数据库设计过程的第二阶段 —— 建立概念模型。这一阶段是整个数据库设计的关键。设计时,一般先根据应用的需求,画出能反映每个应用需求的 E-R 图,其中包括确定实体、属性和联系的类型。然后优化初始的 E-R 图,消除冗余和可能存在的矛盾。概念模型是对用户需求的客观反映,并不涉及具体的计算机软、硬件环境。因此,在这一阶段中我们必须将注意力集中在怎样表达出用户对信息的需求,而不考虑具体实现问题。
3
.建立数据模型
   
完成上一阶段后,我们得到了一个与具体计算机软、硬件无关的概念模型。接着我们就可以着手建立数据库模型了,这是数据库设计过程的第三个阶段。在这一阶段中我们要将概念模型中得到的 E-R 图转换成具体的数据模型。通过前面的学习,我们已经了解到数据模型一般分为层次、网状、关系和面向对象模型等。目前比较常用的是关系数据模型,我们通常将 E-R 图转换成关系数据模型,实际上就是要将实体、实体的属性和实体之间的联系转换为关系模式。
4
.实施与维护数据库
   
最后一个阶段是实施与维护数据库。完成数据模型的建立后,我们就必须对字段进行命名,确定字段的类型和宽度,并利用数据库管理系统或数据库语言创建数据库结构、输入数据和运行等,因此数据库的实施是数据库设计过程的 最终实现 。如果数据库运行很成功,则表明数据库设计任务基本结束,以后的重点就是数据库的维护工作,包括做好备份工作、数据库的安全性和完整性调整、改善数据库性能等。
   
数据库的设计在数据库应用系统的开发中占有很重要的地位。只有设计出合理的数据库,才能为建立在数据库上的应用提供方便。不过数据库的设计过程从来都不会有真正的结束,因为随着用户需求和具体应用的变化和扩大,数据库的结构也可能会随之变化。

数据库基本的功能:
信息浏览和查询;
信息的修改、添加和删除;
信息的统计、汇总等。

设计数据库时要注意保留以下内容:
设计文档、内容操作说明,实例数据库、帮助及过程性文件(如下载的资源、工作日志)等。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值