XMTD-数据库开发规范及经验技巧(V1.0).docx_第1页
XMTD-数据库开发规范及经验技巧(V1.0).docx_第2页
XMTD-数据库开发规范及经验技巧(V1.0).docx_第3页
XMTD-数据库开发规范及经验技巧(V1.0).docx_第4页
XMTD-数据库开发规范及经验技巧(V1.0).docx_第5页
已阅读5页,还剩45页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

XMTD-数据库开发规范及经验技巧XMTD-数据库开发规范及经验技巧(版本号 V1.00)朗新科技(中国)有限公司二一二年三月朗新科技(中国)有限公司 版权所有2012XMTD-数据库开发规范及经验技巧更改履历版本号修改编号更改时间更改的图表和章节号更改简要描述更改人批准人V1.002012-4-6初稿吴志伟注:更改人除形成初稿,以后每次修改在未批准确认前均需采用修订的方式进行修改。朗新科技(中国)有限公司 版权所有2012XMTD-数据库设计开发规范及经验技巧朗新科技(中国)有限公司 版权所有2012XMTD-数据库设计开发规范及经验技巧1 概述本文描述了厦门开发中心在数据库程序开发的开发规范及经验技巧。为了使代码可读性好,可维护性高,使不同的开发人员维护相同的代码,保持代码的一致性,所有的代码和文档应遵循下面的规则和约定。有些项是强制的,而其他项是可选的。希望所有开发成员都能遵循这些标准,特别是新的代码或需要大幅修改的代码。本文并非最终文档,随着技术的发展应随时进行更新。1.1 编写目的规范数据库程序的开发者和维护人员,共同遵循这些标准。1.2 约定此文档适用于公司各产品系统原型开发及测试环境。1.3 使用范围厦门开发中心数据库开发员、工程实施人员、系统维护人员1.4 参考文献2 数据库开发规范2.1 数据库程序开发规范数据库程序开发在本文档中主要指存贮包、过程、函数、触发器和自定义类等数据库对象的设计开发。2.1.1 开发工具数据库开发工具使用比较通用的PL/SQL DEVELOPER,版本7.0以上,此工具便于应用统一的美化器对程序代码实现统一的格式化;便于使用数据库程序模版创建统一格式的数据程序对象。1)安装PL/SQL DEVELOPER。从“VSS/06.质量/开发规范”目录下载plsql_model.rar后并解压到D区(或者其它区),安装完成。2)安装模版如果按照第一步进行绿色安装,此步忽略。其它安装方式则按第一步下载plsql_model.rar后并解压其中的Template目录并覆盖当前目录。3)安装美化器如果按照第一步进行绿色安装,此步忽略。否则按第一步下载plsql_model.rar后并解压其中主目录中的SGPM.BR文件到PL/SQL DEVELOPER安装主目录下。4)应用美化器2.1.2 程序对象及参数、变量、常量、游标、自定义类等命名规范参考数据库对象命名规范2.1.3 注释编写规范每个数据库程序对象(包、包内过程及函数、触发器、自定义类等)、变量及常量必须使用注释,数据库程序中的说明性注释必须与模板中的注释格式一致。程序对象注释形式一律在对象紧贴上方使用:/*/除存贮包外的对象注释格式如下:/*中文名: 对象名称(功能简述)作者: XXX时间: 2012-01-01 09:00:00说明: 功能详细说明修改记录: (修改时间 修改人 修改原因及内容)输入参数:in_para1参数说明 (格式或取值范围说明)输出参数:out_code 返回代码out_msg 返回信息*/存贮包的对象注释格式如下:/*中文名: 对象名称(功能简述)作者: XXX时间: 2012-01-01 09:00:00说明: 功能详细说明修改记录: (修改时间 修改人 修改原因及修改过程或函数名)*/变量及常量可在上方使用:/*/,或后方使用:-过程中分支需注释,一般使用:-程序段落注释:一般使用:/*/2.1.4 错误处理及反馈信息规范供应用层调用的过程需捕获处理各种异常,并反馈信息给应用层,供应用层进行后续处理。反馈信息 (返回参数:out_code, out_msg)格式如下:CREATE OR REPLACE PACKAGE pkg_bu_demo IS PROCEDURE p_test(in_firstname IN VARCHAR2, in_lastname IN VARCHAR2, . out_code OUT NUMBER, out_msg OUT VARCHAR2);END pkg_bu_demo;Oracle系统异常,事务回滚,反馈系统异常信息:out_code := -1;out_msg := pkg_sp_msg.f_msg(error.general, 操作未完成,详细原因为0, SQLERRM);业务逻辑异常,事务回滚,返回业务逻辑异常信息:out_code := 0;out_msg := pkg_sp_msg.f_msg(msg.bu.personNotExists, 人员01不存在,请检查, in_lastname |$| in_firstname);业务正常完成有消息提示,事务提交,反馈成功信息:out_code := 2;out_msg := pkg_sp_msg.f_msg(msg.bu.personAdded, 成功添加人员01, in_lastname |$| in_firstname);业务正常完成无消息提示,事务提交,无反馈信息:out_code := 1;out_msg := NULL;2.1.5 代码设计规范SQL编写参见SQL编写规范 事务提交1) 事务类过程、函数、触发器的程序代码中不可做任何提交动作,所有事务应在应用Service层进行提交。可在异常处理时,做事务回滚。2) 统计类过程可根据需求在代码中进行提交。3) 自主事务(如:写日志)需明确声明为自主事务()。 集合存贮包数据库中的程序代码统一使用存贮包的形式,不再出现单独的存贮过程或者函数。存贮包超过6000行需另建存贮包。 过程和函数功能单纯及多态封装过程和函数尽量功能单纯,不能大而杂。复杂的过程和函数需拆分为多个功能更单纯的过程或函数,提高代码重用率和可读性。通用工具类过程和函数可封装成多种形态,方便调用,提高代码兼容性。 包变量、常量和类型的声明包头除过程及函数声明外,可声明供外部引用的类型和常量,尽量不声明变量。不需外部引用的类型和常量,一般在包体中声明。 触发器不能处理无关表除非必要,一般不定义触发器。表触发器只能处理有外键关联的表。视图触发器只能处理视图定义的关联表。 动态SQL要求1) 动态SQL执行必须使用USING子句绑定变量。参见动态SQL2) 程序代码内中不可出现DDL语句。-可以删除权限允许的任何对象EXECUTE IMMEDIATE DROP | type | | name;3) 避免存在后门或危险性大的动态SQL。如:-可以删除权限允许的任何表数据EXECUTE IMMEDIATE DELETE | tab_name; 使用FOR ALL语句提高循环处理效率如果一个INSERT、UPDATE或DELETE语句执行在一个循环中且引用某集合成员,可移到一个FORALL语句中。参见使用FOR ALL语句 使用BULK COLLECT子句批量取出结果集如果一个SELECT INTO、FETCH INTO或RETURNING INTO子句引用一个集合,合并使用BULK COLLECT子句。参见结果集批量绑定(Bulk Binds) 其他限制1) 程序代码中不得对数据库系统表做写操作。2.1.6 源代码管理规范由于项目设计资源众多,必须要对其重要文档、源代码、发布程序包等统一管理,规范文件存放位置,定期对文件备份,保证项目开发的顺利进行。以CVS作为产品源代码管理器,以下是对数据库开发CVS管理器的目录进行分解。 一级目录分解结构描述目录目录描述备注database数据库同步脚本、数据库层程序备份和程序部署内容 二级目录分解结构描述目录目录描述备注design数据库对象创建存放表空间、表、用户创建脚本(数据库管理部门使用)develop数据库开发存放数据库程序备份,按数据库模式分类(设计开发部门使用)备份要求:数据库程序对象修改完成后必须立即保存并上传。存贮包必须每天至少保存一次并上传。 三级目录分解结构描述目录目录描述备注amber存放用该用户下各开发人员所创建对象包括视图、包、类、触发器、索引和增删改脚本等文件命名采用PL/SQL Developer保存时的默认文件名mngr存放用该用户下各开发人员所创建对象包括视图、包、类、触发器、索引和增删改脚本等文件命名采用PL/SQL Developer保存时的默认文件名Owf_mgr存放用该用户下各开发人员所创建对象包括视图、包、类、触发器、索引和增删改脚本等文件命名采用PL/SQL Developer保存时的默认文件名Wf_amber存放用该用户下各开发人员所创建对象包括视图、包、类、触发器、索引和增删改脚本等文件命名采用PL/SQL Developer保存时的默认文件名业务方案用户存放用该用户下各开发人员所创建对象包括视图、包、类、触发器、索引和增删改脚本等文件命名采用PL/SQL Developer保存时的默认文件名增删改脚本命名规则:分类前缀_功能说明_年月日(yyyymmdd)_序号(两位数字01、02等),扩展名为“sql”如:ac(21类)_amtcalc_20080408_01.sql。脚本一旦上传就不得再修改,如确需修改则需要重新登记,或者在得到发布组的确认也可以修改文件。 四级目录分解结构描述目录目录描述备注目录目录描述备注design单个SQL脚本或补充说明文档Table_script国网成果所以表与相关对象脚本TableSp_script规范化表空间创建脚本2.2 应用DAO层数据库访问开发规范2.2.1 接口规范 数据库访问使用业务平台统一的DAO层数据库访问接口。用例如下:import java.util.List;import java.util.Map;import epm.core.dao.Config;import epm.core.dao.DaoUtil;public class CoreCommon /* * 根据用户取其供电单位 * param sysUserName * return */public static String getOrgNoFromSysUser(String sysUserName) String sql = select org_no from p_sys_user where sys_user_name = ?;String orgNo = DaoUtil.queryForScalar(Config.SP_CONN, sql, new ObjectsysUserName, org_no);return orgNo; /* * 取下级所有单位 * param orgNo * return */ public static ListMap getPriorOrgNoList (String orgNo) String sql = SELECT org_no FROM o_org WHERE p_org_no = ?; return DaoUtil.queryForMapList(Config.SP_CONN, sql, new ObjectorgNo); /* * 判断人员是否在线 * param sysUserName * return false - */ public static boolean isUserOnline(String sysUserName) String sql = SELECT a.user_name FROM amber.indy_user a WHERE + a.user_name = ? and exists (select 1 + FROM amber.indy_online_user b WHERE a.user_id = b.log_user_id) ; Map map = DaoUtil.queryForMap(Config.SP_CONN, sql, new ObjectsysUserName); if(map = null) return false; else return true; 公共数据查询对常用的公共数据查询,如:取系统参数、标准代码、单位、人员、权限等信息,尽量使用业务平台提供的接口函数。用例如下:import ponent.RequestContext;import epm.core.model.SysUserInfo;import epm.sp.priv.dao.PrivProviderDao;import epm.sp.syspara.dao.SysParaProviderDao;public class CoreCommon /* * 在DAO层获取UserInfo * return */public static SysUserInfo getUserInfo() String userID = RequestContext.getCurrentContext().userID;if (userID.equals() return null;PrivProviderDao dao = new PrivProviderDao();SysUserInfo userInfo = dao.getUserInfo(userID);return userInfo;private static String getOrgno() try return getUserInfo().getOrgNo(); catch (Exception e) return null;/* * 获取系统参数 * param paramName * return */public static String getSysParameter(String paramName)tryreturn new SysParaProviderDao().getSysParaValue(paramName, getOrgno();catch(Exception e)return ;2.2.2 代码设计规范SQL编写参见SQL编写规范1) 尽量使用变量绑定。2) 批量提交事务,应使用平台提供批量提交接口函数(DaoUtil. execBatchUpdate)。3) 复杂的事务可改用数据库过程实现,在DAO层调用数据库过程。4) 应用开发中,严禁对大表做无任何条件的SQL查询,需有默认条件。5) 除特殊情况外,控制返回的记录数不超过2000。2.3 SQL编写规范目标:1、确保业务逻辑正确性,2、提高SQL执行性能,3、提高代码可读性。2.3.1 正确关联确保业务逻辑正确性两表间的关联,必须通过其中一表的主键或唯一索引字段进行关联。有些表没可用的主键或唯一索引必须从业务上确定可用的实际唯一约束的字段。2.3.2 提高SQL效率总则大表查询有效利用索引,防止因字段运算、函数或隐式数据转换而索引失效;尽可能减少扫描纪录数,特别要避免大表的全表扫描;尽可能减少表之间的关联数;尽可能通过主键或唯一索引字段关联;需要的数据尽可能一步查出(关联查询、使用FOR ALL和BULK COLLECT);尽量避免排序或隐式排序(ORDER BY、DISTINCT、UNION、MINUS、INTERSECT、IN、NOT IN)。2.3.3 格式相关规范1)SELECT子句中避免使用*Oracle在解析的过程中, 会将*依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。2)SQL语句中不得出现以下类似的恒真或恒假代码:11、22、A=A 、B=B、12、12、AB等;(恒真)1=2、A=B、12、11、22、AA等;(恒假)在应用DAO层拼条件时,如果有必须条件或关联条件,可先拼必须条件或关联条件;如果条件全部可选,则用变量保存需拼条件(格式: and +),最后截去前导 and。(应用开发中,严禁对大表做无任何条件的SQL查询)3)多表查询,需使用别名(Alias) 当在SQL语句中连接多个表时, 使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。 4)两表多字段比较合并子查询,减少对表的重复查询 在含有子查询的SQL语句中,要特别注意减少对表的查询。例子: SELECT tab_name FROM tables WHERE (tab_name, db_ver) = (SELECT tab_name, db_ver FROM tab_columns WHERE version = 604) 比较:SELECT tab_name FROM tables WHERE tab_name = (SELECT tab_name FROM tab_columns WHERE version = 604) AND db_ver = (SELECT db_ver FROM tab_columns WHERE version = 604)前者逻辑读要少于后者,前者更优。5)使用DECODE函数或CASE子句使用DECODE函数或CASE子句可以避免重复扫描相同记录或重复连接相同的表,来减少处理时间。 SELECT _no, COUNT(decode(busi_type_code, 001, 1) fault_num, COUNT(decode(busi_type_code, 003, 1, 004, 1) query_consult_num, COUNT(decode(busi_type_code, 005, 1, 006, 1) complain_rpt_num FROM s_95598_wkst a WHERE a.handle_time = to_date(20111208, yyyymmdd) AND a.handle_time = to_date(20111208, yyyymmdd) AND a.handle_time = 2500; - 索引idxnum失效Where idxnum = 2500 * 12; - 索引idxnum有效例外,对于函数索引,比较的一侧要跟索引描述的函数格式一致,如:Where upper(name_en) = TOM; -索引upper(name_en)有效2) 在索引列上使用NOT或!=、我们要避免在索引列上使用NOT, NOT会产生在索引列上使用函数相同的影响。当Oracle“遇到”NOT,他就会停止使用索引转而执行全表扫描。典型案例:select * From c_cons where not(cons_no=31374173)3) 在索引列上使用IS NULL和IS NOT NULL避免在索引中使用任何可以为空的列,Oracle将无法使用该索引。对于单列索引,如果列包含空值,索引中将不存在此记录。对于复合索引,如果每个列都为空,索引中同样不存在此记录.如果至少有一个列不为空,则记录存在于索引中。举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , Oracle将不接受下一条具有相同A,B值(123,null)的记录(插入)。 然而如果所有的索引列都为空,Oracle将认为整个键值为空而空不等于空。因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引。 低效: (索引失效) SELECT FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;高效: (索引有效) SELECT FROM DEPARTMENT WHERE DEPT_CODE =0;4) 改变索引列的类型(包括隐式类型转换)当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换。 假设 EMPNO是一个数值类型的索引列:SELECT FROM EMP WHERE EMPNO = 123。 实际上,经过Oracle类型转换, 语句转化为: SELECT FROM EMP WHERE EMPNO = TO_NUMBER(123) 。幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变。现在,假设EMP_TYPE是一个字符类型的索引列:SELECT FROM EMP WHERE EMP_TYPE = 123 。 这个语句被Oracle转换为: SELECT FROM EMP WHERETO_NUMBER(EMP_TYPE)=123。因为内部发生的类型转换, 这个索引将不会被用到! 为了避免Oracle对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来。 5) 没有使用复合索引的第一个列如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引,这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。尽量这样做,从9I开始ORACLE已经可以使用SKIP SCAN,但有很多条件,以防万一,还得这样做。6) 用UNION ALL替换OR (适用于索引列) 通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果。对索引列使用OR将可能造成全表扫描,需要具体情况具体分析。 2.3.5 大表相关规范1) 有效利用索引,尽量缩小查询范围2) 不在嵌套子查询中查询大表,可改写成关联查询3) 批量删除2.3.6 分区SQL条件编写1.查询有分区的表,SQL条件尽量包含分区字段(如果是按字段的函数运算分区,也要有同样的函数运算格式)。如:以ORG_NO做范围分区关键字的分区表的,SQL条件中须加入ORG_NO=xxxxxxx的条件,由于ORG_NO在很多表中表示“供电所”的意思,有的SQL条件中无法明确此值,此类情况须这样编写:ORG_NO LIKE xxxxxxx%,其中“x”表示占位符,每个“x”表示一个阿拉伯数字,7位“x”表示县局(包括县级市)或者分局,5位表示地市局,如果SQL条件无法准确到县局或者分局,至少应该到地市局:ORG_NO LIKE xxxxx%。2.分区表多表关联中也应加入分区字段作为SQL条件。2.3.7 避免不必要排序1)用NOT EXISTS替代NOT IN,用EXISTS替代子查询大的IN在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率。在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS,枚举型例外。 例子: (高效)SELECT * FROM EMP (基础表) WHERE EMPNO 0 AND EXISTS (SELECT X FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = MELB) (低效)SELECT * FROM EMP (基础表) WHERE EMPNO 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = MELB) 2)用EXISTS替换DISTINCT当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT。一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。例子: (低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO (高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT DWHERE EXISTS ( SELECT X FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO); 3)用UNION-ALL 替换UNION ( 如果有可能的话) 当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序。如果用UNION ALL替代UNION, 这样排序就不是必要了。效率就会因此得到提高。需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录。因此各位还是要从业务需求分析使用UNION ALL的可行性。4)避免使用耗费资源的操作带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能。如有可能, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写。2.3.8 其他规范1)用TRUNCATE替代DELETE2)尽量用Where子句替换HAVING子句 避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。where比having快,因为它过滤数据后才进行sum。在单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的, where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。 典型案例:统计某供电所(有索引)每个抄表区的欠费余额SELECT CBQM,SUM(QFJE) FROM C_QFXX GROUP BY DW,GDS,CBQM HAVING DW=0102 AND GDS=4001;应该修改成:SELECT CBQM,SUM(QFJE) FROM C_QFXX Where DW=0102 AND GDS=4001 GROUP BY CBQM3)SQL条件中的自定义函数要求1.条件中尽量少用需要参考其它表的自定义函数;2.如果自定义函数必须参考其它函数须满足主语句和函数内都必须能用上索引且检索数据要少。UPDATE a_rcvbl_flow SET opr_id = 101, status_code = 02 WHERE settle_flag IN (01, 02) AND pay_mode = 05 AND status_code = 01 - AND pkg_ca_common.f_getbank_code(cons_no, org_no) = TRIM(01) AND org_no IN (SELECT org_no FROM o_org START WITH org_no = 1240101 CONNECT BY PRIOR org_no = p_org_no);4)在触发器中少做批量DML操作典型案例:有两个表:电费计算表(中间表)和起止度信息(中间表),后者对前者有外键参考(DFID),为了批量删除同一个传单两表中的数据,前者300条记录,后者1000条记录,可以通过在两表中都对传单编号建索引分别删除同一传单数据,请不要在触发器中通过外键关系删除或者直接创建级联删除的外键来删除数据。5)禁止使用ROWID做为SQL条件因为ROW MOVEMENT ENABLE使用NESTED TABLE的表不能ENABLE ROW MOVEMENT因为其 rely on ROWID2.4 各开发阶段规范2.4.1 设计开发阶段 阶段流程 阶段要求以程序的业务逻辑正确性为主要关注点。数据库存贮包发布前,提交技术部评审。DAO层复杂SQL(设计时可预见),由开发经理整理成模板化SQL,发布前提交技术部评审。(模板化规则待定)模板化规则:2.4.2 上线前调试阶段 阶段流程 阶段要求以程序的性能优化为主要关注点。同时不能忽略正确性。2.4.3 上线后维护阶段 阶段流程 阶段要求程序修改需在注释中写明:修改时间、修改人、修改原因和内容。3 程序开发经验与技巧3.1 避免高耗CPU3.1.1 提高SQL语句效率1) 有效利用索引2) 更新表统计信息3) 执行分析计划EXPLAIN PLAN4) 重写SQL,使用查询提示(hits)。参见附录二 Hint全集5) FORALL语句提高循环处理性能。参见使用FOR ALL语句6) BULK COLLECT子句提高结果集处理性能。参见结果集批量绑定(Bulk Binds)3.1.2 提高函数调用效率1) 函数索引2) 嵌套查询,在外层调用函数,减少函数调用次数3) 使用NOCOPY声明输出参数声明3.1.3 不重写内置string函数不要重写以下数据库函数,如:REPLACE, TRANSLATE, SUBSTR, INSTR, RPAD, LTRIM等。3.1.4 提高循环效率使用FORALL语句提高循环处理性能。使用BULK COLLECT子句提高结果集处理性能。提高循环内处理效率,避免UNION, INTERSECT, MINUS, 和CONNECT BY嵌套子查询,在外层调用函数3.1.5 where条件顺序(无索引情况)代价低条件放前面。如:等式比较、范围比较代价高条件放后面。如:函数调用、带子查询等高定位(同值记录少)条件放前面。3.1.6 使用合适的数据类型1) 减少数据类型转换(包括隐式类型转换),如:DECLARE n NUMBER; c CHAR(5);BEGIN n := n + 15; - 整型转浮点 n := n + 15.0; - 无转换 c := 25; - 整型转字符串 c := 25; - 无转换 IF n = c THEN - 字符转数值NULL; END IF;END;防止因隐式转换导致索引失效2) 使用PLS_INTEGER类型进行整数运算3) 使用BINARY_FLOAT和BINARY_DOUBLE类型进行浮点数运算3.2 避免高耗内存可大方定义VARCHAR2大小集合过程到包中(包也不要太大,占用共享内存)调用DBMS_SHARED_POOL钉住常用包在共享内存关注编译时提示警告,尽量改善减少循环处理或查询,可用FORALL替代对于大数据量的参数传递 ,可以在过程声明部分使用nocopy关键字3.3 避免高数据I/O尽可能减少扫描纪录数,特别要避免大表的全表扫描。关联查询时,选择合适的驱动表(主要查询条件相关的大表),并使用驱动表查询结果集尽量小。不在SELECT子句中包含大表子查询,可改写成大表间关联。3.4 索引使用经验与技巧3.4.1 索引列的顺序关系了解索引的等级,提高索引利用效率。一般情况索引等级如下:1.等式比较比范围比较要高。2.唯一性索引比非唯一性索引要高。3.一般情况下单列索引等级要比复合索引高,但如果where子句中包含所 有复合索引的字段,则复合索引等级高。3.4.2 索引列比较:=比更有效大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A2与A=3的效果就有很大的区别了,因为A2时ORACLE会先找出为2的记录索引再进行比较,而A=3时ORACLE则直接找到=3的记录索引。3.4.3 使用索引来避免排序索引是排好序的,在某些情况下可以使用索引来避免排序。SELECT acc_name, acc_surname FROM account acct ORDER BY 1;SELECT /*+ INDEX_ASC(acct acc_ndx1) */ acc_name,acc_surname FROM account acct;3.5 其他经验与技巧3.5.1 NULL的运算、比较和判断与NULL做任何运算,结果都是NULL与NULL做任何比较(包括NULL=NULL),结果都是FALSE判断是否NULL只能用:IS NULL或IS NOT NULL3.5.2 隐式数据类型转换数值运算表达式(+-*/):字符型自动转数值型字符运算表达式(|):数值型自动转字符型比较表达式(=):一侧为数值型则另一侧字符型自动转数值型过程函数参数:代入值类型自动转参数类型赋值:右侧运算值类型自动转被赋值变量类型3.6 知识点及例子3.6.1 使用游标 例子DECLARE v_jobid employees.job_id%TYPE; v_lastname employees.last_name%TYPE; CURSOR c1 IS SELECT last_name, job_id FROM employees WHERE regexp_like(job_id, SHT_CLERK); v_employees employees%ROWTYPE; CURSOR c2 IS SELECT * FROM employees WHERE regexp_like(job_id, ACADFIMKSA_MANGR);BEGIN OPEN c1; - 在FETCH游标前打开游标 LOOP FETCH c1 INTO v_lastname, v_jobid; - FETCH游标保存记录值到列变量 EXIT WHEN c1%NOTFOUND; dbms_outp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论