ORACLE数据库应用开发的三十个注意事项


当前第2页 返回上一页

前几年,有个工程割接时为了提升割接速度,当晚一个参与割接的工程师未和任何人商议就将一个重要的访问频繁的大表的并行参数设置调整多倍,割接后也未关闭,导致第二天业务起来后数据库出现了锁、主机CPU全忙,影响业务超过4个小时。经过较长时间定位才发现是该表并行被打开导致的,问题最终解决但造成了不良影响。而那个导致问题的工程师也在华为年底考核中得到了处罚离职走人。

禁忌12:忌SQL语句不使用绑定变量

在应用开发中,SQL语句大多数是动态SQL,这种动态SQL又分为两种,一种是字段取值是变化的,一种是连数据对象名都是动态的。

对于字段取值变化的情况,基本的访问SQL是固定的,针对变化的字段值就需要用绑定变量方式传值,这时数据库才不会重新编译该SQL语句,可以提高执行效率,如果不使用绑定变量,直接将该SQL语句用字符串方式拼接,其实就与数据对象也是不同变换的方式相同,这样SQL语句每回都会被编译,效率会大幅下降。

对于数据对象名都是动态的SQL,不适合通过绑定变量方式传递数据对象名。

禁忌13:忌索引数量过多

一个表的索引是需要单独占用存储空间的,过多的索引会导致表数据发生变化时索引的调整占用过多的时间,会引发数据的增删改性能下降。对于频繁进行插入、删除、更新的数据表,应控制索引的数量,提高效率,一般一个表的索引数控制在5个以内。如果一个表要建5个以上索引,一般说明表和应用的设计是存在问题的。

禁忌14:select for update 要带nowait

select ... for update语句 对于保证事务的完整性很有必要,但在一个并发环境中,使用该语句的应用很可能会导致数据库锁甚至死锁,正确的做法是select ... for update nowait,并且在获取锁失败时要有重新处理的机制。

禁忌15:批量任务要控制好事务提交的频度

在后台进程或存储过程处理大批量数据时,事务提交禁止单条提交或者全部完成后再提交,提交太频繁会产生过多的数据库日志,一次性提交容易导致回滚段不够等问题。建议使用100、500或者1000条提交的频度。

禁忌16:sequence使用注意

对于部分表的内部关键ID字段如流水号等使用sequence是个非常不错的主意,可以有效保障并发环境下这种序列号分配的高效和唯一性。但在应用中使用sequence时要注意几点:

  1. 长度设置要充分考虑业务发展的速度,有效序列在初期增长缓慢,但随着业务发展会迅速增长,因此开发设计时要进行充分的评估,防止出现sequence很快被耗尽;
  2. 对于长期增长的序列号,最后采用时间戳+序列号的方式来作为字段值,防止序列号翻转;
  3. 序列号分配时,由于序列号在不同数据库实例的缓冲机制,可能会出现后面的数据记录序列号比前面插入记录序列号还要小的情况,因此序列号字段的值只能作为唯一键值使用,而不能作为业务排序的依据。

禁忌17:慎用rowid更新数据

rowid是数据库记录的一个内部记录ID,使用rowid访问数据比普通索引还要高效,但如果在一个表的数据频繁插入、删除时,不要使用rowid来进行数据的操作,因为ORACLE的rowid在数据有删除机制时,是有一定几率出现重复的。

禁忌18:慎用子查询

通过子查询方式进行数据的嵌套查询SQL的可读性比较好,但子查询很容易导致全表扫描,且容易导致回滚段或临时表空间使用过高,因此慎用子查询,特别是子查询的结果集也很大时忌用。

禁忌19:忌用SELECT *

在查询SQL语句中,要尽量减少返回的结果行,包括行数和字段列数。返回的结果越大,意味着相应的SQL语句的logical reads 就越大,对服务器的性能影响就越甚。

一个特别不好的设计就是使用SELECT * 返回表的所有数据,除了影响服务器性能外,还可能会由于表结构的调整在编译阶段无法发现,导致运行时错误。

禁忌20:where 子句中慎用!=或<>操作符

使用!=或<>意味着对应字段的访问不会使用索引,因此只有在其他字段使用了索引的基础上才使用!=或<>操作。

禁忌21:where 子句中慎用like

如果在where字句中使用字段A like ‘%xxx' 或字段A like ‘%xxx%'方式匹配结果记录时,该字段不会使用索引,因此只有在其他字段使用了索引的基础上才使用字段A like ‘%xxx' 或字段A like ‘%xxx%'方式,即忌用前置百分号匹配。

禁忌22:where 子句中慎用in和not in

如果in后面的结果数据比较多,很可能会导致全表扫描。因此只能和其他能使用索引的条件组合使用时使用。

禁忌23:where字句中慎用字段函数操作

应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

禁忌24:忌用select count(*)

使用select count(*)的效率不如使用select count(1)。

禁忌25:索引字段访问慎用OR

索引字段用OR的字句容易导致全表扫描,一定要判断多个值可以分解成多个查询,并且通过UNION 连接多个查询。

禁忌26:慎重考虑字符集

在一个应用系统中,涉及应用服务器主机字符集、数据库字符集以及客户端字符集的兼容性问题,要在系统构架时统一考虑,确保从前台到后台到数据库的字符集都是兼容的。

禁忌27、慎用视图嵌套

视图最好建在表上,尽量不要基于视图嵌套建立视图,一方面一般视图嵌套不要超过2个为宜,视图嵌套层级多访问效率会下降,并且可维护性变差。

禁忌28: 忌数据对象名过长

oracle的表名、字段名等对象命名字节个数限制在了30个字节,不能超过30。

禁忌29:谨慎表和索引的inittrans设置

每个块都有一个块首部。这个块首部中有一个事务表。事务表中会建立一些条目来描述哪些事务将块上的哪些行/元素锁定。这个事务表的初始大小由对象的INITRANS 设置指定。对于表,这个值默认为2(索引的INITRANS 也默认为2)。事务表会根据需要动态扩展,最大达到MAXTRANS 个条目(假设块上有足够的自由空间)。所分配的每个事务条目需要占用块首部中的23~24 字节的存储空间。注意,对于Oracle 10g以上版本,MAXTRANS 则会忽略,所有段的MAXTRANS 都是255。

也就是说,如果某个事物锁定了这个块的数据,则会在这个地方记录事务的标识,当然那个事务要先看一下这个地方是不是已经有人占用了,如果有,则去看看那个事务是否为活动状态。如果不活动,比如已经提交或者回滚,则可以覆盖这个地方。如果活动,则需要等待(闩的作用)。

所以,如果有大量的并发访问使用的这个块,则参数不能太小,否则资源竞争将导致系统并发性能下降。

在创建表和索引时,需要根据表数据的访问频度和数据量来评估设置的inittrans值,虽然不够时Oracle会自动增加,但增加的过程需要ORACLE进行评估,且该评估机制是针对所有对象的,需要排队,如果inittrans值设置过小,就会影响系统的并发性能。因此系统设计和部署时需要考虑不同表的inittrans的设置。

禁忌30:数据模型和数据对象的设计必须商DBA确认

一个业务系统,会有大量的数据模型,会创建大量数据对象,在考虑业务需求的同时必须考虑系统运维,因此请DBA参与设计是非常必要的。
在做设计时,要考虑:

  1. 制定数据库对象命名规范;
  2. 数据库表空间的使用规划(包括业务数据表和索引、字典表、临时表空间、回滚段等);
  3. 表和索引的inittrans大小;
  4. 各个表的PCTFREE 和 PCTUSED设置;
  5. 数据维护周期

小结:

本文详细介绍了笔者在二十余年ORACLE应用开发中遇到的三十条开发注意事项(本来想写成三十六忌的,奈何没凑够),这些注意事项是实际工作中的经验和教训总结,好些注意事项是笔者的团队以及华为等合作厂商一些工作两三年的人都容易犯的错,笔者前2年遭遇的一次事件还导致了一个华为工程师的考核离职。

这些注意事项不但可以在和ORACLE有关的应用开发中遇到,大部分也可以在其他关系型数据库有关的应用开发中遇到,甚至部分问题可以在非关系型数据有关的应用开发中遇到。

以上就是ORACLE数据库应用开发的三十个注意事项的详细内容,更多关于ORACLE数据库应用开发的注意事项的资料请关注其它相关文章!


打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...