SQL编写及其优化培训.doc

上传人:李司机 文档编号:1166059 上传时间:2022-07-12 格式:DOC 页数:14 大小:124.21KB
返回 下载 相关 举报
SQL编写及其优化培训.doc_第1页
第1页 / 共14页
SQL编写及其优化培训.doc_第2页
第2页 / 共14页
SQL编写及其优化培训.doc_第3页
第3页 / 共14页
SQL编写及其优化培训.doc_第4页
第4页 / 共14页
SQL编写及其优化培训.doc_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《SQL编写及其优化培训.doc》由会员分享,可在线阅读,更多相关《SQL编写及其优化培训.doc(14页珍藏版)》请在三一办公上搜索。

1、目录目录本培训包含的内容如下:41.表、索引相关知识与其在数据库内部相关的物理存储 41.1.数据库中最小的物理存储单位:块41.2.表数据在块中的存储以与 RowId 信息 41.3.索引 4索引介绍 62.数据库查询操作的内部处理过程 62.1.数据库的数据读取是以块为单位的 62.2.查询操作内部过程以与索引的作用 62.3.执行计划概念 72.4.排序处理过程以与各种引起排序的操作 72.5.多表 join 操作的内部过程 73.写 SQL 语句时在性能方面的目标 8列表中减少不需要的数据 8列表中去除不需要的表 8条件中应该考虑到索引的使用,避免一些写法 83.3.1.避免过滤字段中

2、套用函数,如果必须,则考虑函数索引 93.3.2.避免把列放入表达式中去比较 93.4.避免不需要的排序 93.5.避免数据类型的隐式转换 93.6.程序代码中的注意点 103.6.1.由多个 SQL 语句完成的一个操作尽可能写成一个 SQL 就完成,避免分解 103.6.2.使用数据库提供的约束来判断某些错误,如唯一性 114.SQL 语句知识 11语句串讲 114.1.1.select f1 from A114.1.2.select f1 from A where f2=v_1114.1.3.select f1 from A order by f2114.1.4.select sum fr

3、om A124.1.5.select f2,sum from A group by f2124.1.6.select a_f2,b_f2 from A,B where A.f1=B.f1124.1.7.Select * from report where SALES_CODE in ;144.1.8.Select * from report where SALES_CODE exists ;144.1.9.in,exists 的选择 144.1.10.select yadfw as t1,kopeew as t2 From A union all select uufger as t1,poe

4、prvcx as t2 from B144.2.几种常见操作或函数 15温有飘温有飘2005 年年 4 月月 28 日日软脑软件软脑软件公司公司4.2.1.比较符 like154.2.2.is null,is not null154.2.3.to_char,to_date,to_number15164.2.5.其他 165.表设计的一些建议 16参考文献 16本培训包含的内容如下:表、索引相关知识与其在数据库内部相关的物理存储;数据库查询操作的内部处理过程;写 SQL 语句时在性能方面的目标;SQL 语句知识;表设计的一些建议下面阐述的内容以 Oracle 为例来讲述的,在排版方面可能有不妥当

5、的地方,或有些内容前后重复,但各种知识应该比较容易理解和接受;1.表、索引相关知识与其在数据库内部相关的物理存储表、索引相关知识与其在数据库内部相关的物理存储1.1. 数据库中最小的物理存储单位:块数据库中最小的物理存储单位:块数据库最小的物理存储单位是块9i 默认是 8k,每个块只能属于一个表;一行数据插入时会占用块中的一些存储,当块不能再容纳新数据时,则将启用新的块存储数据;1.2. 表数据在块中的存储以与表数据在块中的存储以与 RowId 信息信息表的字段除了设计者设计的字段外,还有个字段 Rowid;RowId 是 oracle 为每个表自动增加的一个字段.当表中插入一行记录时,此记录

6、在块就有一个唯一的物理位置,这个位置信息就保存在此行记录的 RowId 字段;1.3. 索引索引表中记录的存储顺序是以先后插入顺序存储的,在一个数据量很大的表中,如果不引入其他的手段,每次查找小部分记录都是从第一条扫描到最后一条,这样,系统将慢得不能使用;使用索引可以有效解决问题;如图:Report 表RowIdSession_codeSales_codeEmployee_codeAAANslAAQAAA7YTAAh100061000017AAANslAAYAAAAmWAAX10007100015.索引Employee_codeRowId5AAANslAAYAAAAmWAAX17AAANslA

7、AQAAA7YTAAh索引的本质用途是通过它使读取进程在扫描源表时的数据块范围大大减小了,因此性能大幅度提高;一般情况下,当检索的记录与所有记录数比较=4%时,索引是很有效的,当比例更大时,索引反而有可能降低性能,因为即使使用了索引,读取进程还是扫描了大部分的表中的块,如果这样,倒不如不用索引直接扫描源表,因为减少了读取索引的块的开销;当索引建好后,oracle 优化器在执行 sql 时会选择是否使用索引,所以设计表者不用担心此索引会影响检索性能;创建索引的标准是那一列是否经常在 where 条件中出现,否则不应该建立,因为,每次表记录的增加、删除以与修改那个字段值时,还要维护索引,增加了开销

8、;此节讲的索引叫 B_tree 索引,在内部存储中类似树状结构,有枝和叶,枝是 oracle 内部存储的一些连接数据,叶才存储实际的值,如图:表中每条记录只要那个列是非 NULL 值,在索引中都有一个条目entry来存储如上图,类似于表在块中一条条记录存储;1.4. Bitmap 索引介绍索引介绍当表中某列的 distinct 值比较少时,使用 B_tree 索引效率就不高了,因为以此列来做where 条件过滤的话,结果集很可能超过总记录数的 4%,正如前面说过的,超过 4%记录使用 B_tree 索引,效率反而下降.使用 Bitmap 位图索引可以解决这个问题;Bitmap 索引使用一个位图

9、来记录数据情况,举例:商品表 product,有一个字段 color 存储颜色值,在所有商品中最多就 10 种不同的颜色,创建的位图图示如下:其中,Start ROWID 是表中的第一条记录的物理地址,end ROWID 是表中最后一条记录的物理地址,bitmap 是一张位图,存储一连串的 0 或 1;列值为 blue 的 bitmap 中,每个 bit 的位置在源表中都能找到某个位置与它一一对应,它们在各自对象中的相对位置一样.bit 值为 1 时,则源表对应位置那个 rowid 所在的记录的 color 字段值为blue,为 0 时,则非blue值;类似的,Green,Red,Yellow

10、 都有各自的 bitmap;试想,当 where 条件中有过滤条件 A and B,条件 A 可以使用 B_tree 索引,条件 B 可以使用 bitmap 索引,那么从 A 条件中可以得到一个 RowId 的集合,从 B 条件也可以得到RowId 结合,这样,只要从第一个 rowid 集中去除第二个 rowid 集中的值,得到结果集Rowid,我们就可以从源表得到数据了;Bitmap 使用了压缩技术,节约了存储,并且在一个 bitmap 上对某个位 bit 的值是 1 还是 0时速度是非常快的;2.数据库查询操作的内部处理过程数据库查询操作的内部处理过程2.1. 数据库的数据读取是以块为单位

11、的数据库的数据读取是以块为单位的Oracle 读取表中的数据时,是以整个块为单位的,有可能一次读多个块;从索引中得到rowid 的物理位置时,也要把含 rowid 这个位置的块从磁盘中读出,然后才处理个别行;2.2. 查询操作内部过程以与索引的作用查询操作内部过程以与索引的作用举例:select * from personal_function where employee_code= -200 ;上述查询,如果 employee_code 上没有索引,则会把 personal_function 表数据的块全部读入内存中,同时从第一条记录查到最后一条记录,对符合条件的记录返回给用户;如果 em

12、ployee_code 有索引,则使用索引检索出含符合条件的 Rowid 的块读入内存,然后定位到 rowid 指示的位置上把记录返回给用户;2.3. 执行计划概念执行计划概念2.2 节中,如果 employee_code=-200 的记录数在占总记录数超过 4%,则有可能就不会用索引查找,而是直接全表扫描,这是 oracle 的优化器经过各种检测后会自动选择的;Oracle 对已存在数据统计特征会选择不同的执行路径或者全表,或者使用索引等,这就产生了不同的执行计划,使能达到最大的性能.执行计划选择的模式有 RBO 和 CBO 方式,采用 CBO 方式时,sql 语句中 from 后表的先后顺

13、序以与 where 条件中各个条件的先后顺序变得不是很重要了,如果 RBO 方式则不然;CBO 全称 Cost-based Optimizer,基于代价的优化.2.2 节提到的 SQL 语句,Oracle 是否使用索引,其内部会做各种比较,然后自动做出选择;为了使 Oracle 做出更精确的比较,我们应该周期性地对表进行统计,使 Oracle 了解到真实情况后做出更准确的判断.因为要统计,所以称之为基于代价;RBO 全称 Rule-based Optimizer,基于规则,就是说 Oracle 定义的一套执行先后顺序,如,有索引则一定会用索引,就如 2.2 节的 SQL 语句,但这样有时并不是

14、最好的执行选择.2.4. 排序处理过程以与各种引起排序的操作排序处理过程以与各种引起排序的操作举例:select * from personal_function where employee_code= -200 order by func_name;由 2.2 节可知,如果没有 order by 语句时,oracle 只要检索到一条符合条件的记录就立刻返回给用户,直到所有数据返回完毕.当有 order by 时,情况就不一样了,oracle 会把检索到的每一条记录先保存在一个用于排序的内存中,当所有符合条件的记录在那个区域完成排序后,再返回给用户;通过排序这个操作,oracle 中间多处理

15、了一个步骤.数据量越大,排序时间则更长,当数据量达到所找的内存区域无法容纳时,将使用磁盘做为临时排序区,此时,性能会大大降低,用户将等待更长的时间才能得到返回的结果;因此,在一个 SQL 语句中,如果对返回的记录集没有顺序要求时,应该去除引起排序的语句;引起排序的操作有:order by,distinct,union,group by2.5. 多表多表 join 操作的内部过程操作的内部过程举例说明:Esm 系统中的 3 张表结构如下:Employee:EMPLOYEE_CODE职员代码EMPLOYEE_NAME职员名称EMPLOYEE_KANA职员全称Emp_detialEMPLOYEE_C

16、ODE职员代码DEPART_CODE职员部门代码DepartDepart_CODE部门代码DEPART_NAME部门名称现在要求列出所有职员的名称和其对应的部门名称,SQL 语句如下:select aa.employee_name,cc.depart_name from employee aa,emp_detail bb,depart ccwhere aa.employee_code=bb.employee_codeand bb.depart_code=cc.depart_code;执行时,oracle 可以选择如下的一个执行计划可参考节的流程图:Employe 表数据 emp_detaild

17、epart00001张三00002100200开发 2 部00002李四00003200300开发 3 部00003王五00001300100开发 1 部1)读取 employee 的第一条记录,得到职员代码 A;2)再在 emp_detail 查找职员代码为 A 的第一条记录,得到部门代码 B;3)在表 depart 中查找部门代码为 B 的记录;4)在各个表的记录中中取出需要的信息返回给用户;5).2 步和 1 步是个循环操作,2 步嵌套于 1 步中,直到所有信息返回给用户;Oracle 如果有其他的执行记录更好的话,会选择其他的;3.写写 SQL 语句时在性能方面的目标语句时在性能方面的

18、目标3.1. select 列表中减少不需要的数据列表中减少不需要的数据select 列表需要的信息应该按需索取,不能因为图方便用*把所有字段内容取到客户端,这样,既增加服务器的负荷,又增加网络流量;3.2. from 列表中去除不需要的表列表中去除不需要的表出现在 from 后的表,oracle 都会对它检索并与其他表进行 join 操作,如果把不需要的表不经意间放在了 from 后面,可能会增加几倍甚至几十倍的负荷;如果 where 条件中也没有加上进行 join 的条件,oracle 将对它进行笛卡儿乘积的 join,这种负荷可想而知;3.3. where 条件中应该考虑到索引的使用条件

19、中应该考虑到索引的使用,避免一些写法避免一些写法3.3.1.避免过滤字段中套用函数避免过滤字段中套用函数,如果必须如果必须,则考虑函数索引则考虑函数索引举例:统计在某天的日报登记个数,其中,某天这个值 V_date 是从程序外面以参数的形式传递进去的字符串,格式如 yyyy-mm-dd;比较两种写法:第一种:Select count from report where to_char=V_date第二种:Select count from report where day=to_date;必须选择第二种,因为如果 day 上有索引,而 day 作为函数 to_char 的参数,oracle 将

20、不使用它的索引,因而进行全表扫描,这样的后果是,也许 2 秒内就能统计出来的结果,却可能要花几十分钟甚至几小时;report 表数据量越大,对比结果就更明显;有些情况确实需要使用函数,如:取出职员名称为 V_name 的职员代码,而 V_name 是从程序外面传进去的参数;由于在最初增加职员记录时,每个存入的职员名称没有做大小写转化,比如,最初登陆了一个ZhanSan的职员,此时 V_name 传进来的是 zhansan,如果用如下语句查询将得不到记录:Select employee_code from employee where employee_name=V_name;可使用如下语句Se

21、lect employee_code from employee where UPPER=UPPER ;此时由于套用了函数 UPPER 而列 employee_code 上的索引将不被使用,可以考虑创建函数索引,就是把UPPER当成一个字段去创建索引,当查询时,则会使用此函数索引;3.3.2.避免把列放入表达式中去比较避免把列放入表达式中去比较请看下面 2 条语句:Select * from A where f1/5300;Select * from A where f1300*5;必须使用第二种,否则,如果 f1 有索引,第一种情况将不使用;3.4. 避免不需要的排序避免不需要的排序2.4

22、节中已说明排序需要额外的负荷,所以,当不需要排序时,应该避免;3.5. 避免数据类型的隐式转换避免数据类型的隐式转换举例:表 A,有一字段 code,varchar2 类型,此字段存储的值都是由数字组成的串;SQL 语句:Select * from A where code=v_number;其中,v_number 是由程序外面传入的数值;因为 v_number 是数值,而 code 是 varchar2 类型,所以,Oracle 会进行类型的隐式转换,把此语句转化成如下形式执行:Select * from A where to_number=v_number;把列嵌套在函数里索引不能使用,这

23、个是我们不期望的,所以正确的做法是我们应该进行显式的转换:Select * from A where code=to_char;3.6. 程序代码中的注意点程序代码中的注意点3.6.1.由多个由多个 SQL 语句完成的一个操作尽可能写成一个语句完成的一个操作尽可能写成一个 SQL 就完成就完成,避免避免分解分解举个例子:需要得到 2004 年中,每个季度的日报个数;第一种方法:比较容易想到的,用 4 个 SQL 语句分别去得到各个季度的统计:Select count from report where day=to_date and day=to_date;Select count from

24、report where day=to_date and day=to_date;Select count from report where day=to_date and day=to_date;Select count from report where day=to_date and day=to_date;第二种方法:一个 SQL 语句完成Select Count=to_date and day=to_dateas one,Count=to_date and day=to_date as second,Count=to_date and day=to_dateas third,Cou

25、nt=to_date and day=to_dateas forth,From report;显然,第二种方法可以提高 4 倍的性能;要达到这种转化,编码人员需要对数据库提供的 SQL 函数有充分的认识;3.6.2.使用数据库提供的约束来判断某些错误使用数据库提供的约束来判断某些错误,如唯一性如唯一性有种情况,应用程序中经常出现,举个例子:有张全国居民身份表 resident,其中有个字段#ID_card,是主键,在登记一个居民时,为了避免发生主键冲突,应用程序往往保存之前用一个 SqL 语句去查此 ID_card 号是否已存在,存在则提示 ID_card 冲突.上述情况完全可以避免使用写 S

26、QL 语句的方法去查,因为 oracle 的每个错误都有一个唯一的错误号,只要在程序中去捕捉违例,然后进行对比是否是主键冲突即可;有些时候非主键的字段也要保持唯一性,则可以使用唯一索引.当发生唯一性冲突时,也有一个错误号;Oracle 在自身版本升级的时候,错误号的含义是向后兼容的;4.SQL 语句知识语句知识4.1. SQL 语句串讲语句串讲4.1.1. select f1 from A这是一个最简单的 SqL 语句,想象一下 A 表的块读入内存,然后从第 1 条记录扫描到最后一条记录且每次立刻把 f1 字段值返回给用户,这个过程是全表扫描;Sql 语句中,有列别名和表别名,对很长表名或列名

27、可以简化操作,如:表别名:Select aa.STATUS from REGULAR_REPORT_CONTENTS aa;表别名前不应该使用as ,SQL SERVER 支持,但 Oracle 里不支持;列别名:Select MODIFIED_STATUS_CODE_OUT as mod from TIMEBOOK_LOG;程序代码中引用的时候就可以使用 mod,而非长串;如果在连接表中有同名表的时候,别名是必须的;4.1.2. select f1 from A where f2=v_1如果 f2 无索引,则第 411 节中每次扫描到一条记录时会根据条件进行过滤,符合条件则立即返回给用户,否

28、则扫描下一条;F2 有索引且使用时,则从索引开始扫描,扫描时不象表一样从第一条目扫描到最后一条,oracle 会根据内部算法很快定位到符合条件的条目,读取 Rowid 后根据物理地址定位到源表的记录上立即返回给用户,然后再在索引中定位到第二个符合条件的条目,直到全部;4.1.3. select f1 from A order by f2在节中讲到的每扫描的记录立即返回给用户,而当有排序时,则先发送到一个排序区中进行排序,等所有记录扫描完后,再把排序区中的数据集返回给用户;当 select 后带 distinct 时,内部处理也有排序操作,更靠近 distinct 的字段就更先排序,同时在排序过

29、程发现有各个字段信息完全相同的行时,只留一条记录,废除其他相同的;排序完成后,再把排序区中的数据集返回给用户;4.1.4. select sum from Aoracle 处理时类似这样:使用一个变量 V,初始值 0,每次扫描一个记录时,v=v+f1,直到扫描到最后,把 v 返回给用户;类似的,函数 avg,max,min,count 原理差不多,如果 f1 有索引时,可能会扫描索引而不扫描表,因为索引的块更少,而且包含了需要的全部信息;4.1.5. select f2,sum from A group by f2上节中是把 f1 值加如到一个变量中,这里多了一个字段,可以这样理解:每扫描一条

30、记录时,如果 f2 值未出现过,则定义一个数组变量 A,A1=f1,A2=f2;如果 f2 值以前出现过,则把当前 f1 值增加到对应的数组变量中,这样,直到表扫描完毕,按 f2 字段分组的各个统计值都记录在了一堆的数组中,最后,oracle 把数组的各个值按记录的方式返回个用户;Oracle 在处理每当一个新的 f2 的值出现时,对应 f2 的数组变量都会按 f2 值由小到大排序,因此,排序结果集中是按 f2 排序的,用户无须再排序;分组语法中,在 select 列表中出现的非统计字段,都要在 group by 后出现;有时候需要对统计的结果进行过滤,例如 select f2,sum fro

31、m A group by f2 中,用户只需要 sum10000 的组的统计,这时用 having 过滤条件,如下:select f2,sum from A group by f2 having sum10000where 条件是针对记录的过滤,被过滤掉的数据不参与统计.having 是针对统计完成后,统计结果返回给用户时的过滤;4.1.6. select a_f2,b_f2 from A,B where A.f1=B.f1oracle 对连接 join 的操作的内部处理过程,可以参考下图:上图的流程只是执行计划当中的一种,但可以借助于理解,当多于 2 张表时,情形是一样的;上述的连接也称内连

32、接,其他连接还有左连接,右连接和全表连接的方式;左连接:select a_f2,b_f2 from A,B where A.f1=B.f1+,必须首先扫描 A 表以驱动B 扫描.此时,A 标示的地方,如果针对 A 表的一条记录,在 B 表中 1 条也没有找到符合条件的记录,则会把 A.f1 值和以 NULL 值作为 B.f1 的值返回给用户;这样,A 表中的所有记录的且在 select 列表中的信息都会返回给用户;右连接:select a_f2,b_f2 from A,B where A.f1+=B.f1,首先扫描 B 表以驱动 A 扫描,其他操作可参考左连接;全连接:select a_f2,

33、b_f2 from A full outer join B on A.f1=B.f1;它的记录集是 select a_f2,b_f2 from A,B where A.f1=B.f1 的结果集加上A 表中有,但在 B 表中未找到符合条件的记录的集合B 表中的信息是以 Null 值返回,再加上B 表中有,但 A表中未找到符合条件的记录的集合A 表中的信息是以 Null 值返回 ;各种连接通用写法是:如果 f1 字段有索引,可能会使用索引方式检索A内连接:select a_f2,b_f2 from A,B where A.f1=B.f1 或 select a_f2,b_f2 from A inne

34、r join B onA.f1=B.f1左连接:select a_f2,b_f2 from A left outer join B on A.f1=B.f1右连接:select a_f2,b_f2 from A right outer join B on A.f1=B.f1全连接:select a_f2,b_f2 from A full outer join B on A.f1=B.f1;在 symfoware 中不支持4.1.7. Select* from report where SALES_CODEin;上节讲的所有的表都在 from 后的列表中,数据源都是直接的表,不含子查询,而这条是

35、典型的含子查询的语句,内部执行时,可以有这种方式:首先,执行子查询语句,把结果集临时保存,作为外层查询的一个数据源;其次,类似节中的流程图,先检索 report 表第一条记录,然后再检索上一个步骤得到的数据源,如果包含 sales_code 值,则返回 report 当前检索到的记录,如果没有,则 report继续扫描下一条记录,重复上步操作,直到表的结尾;很多含子查询的语句 oracle 内部处理的时候会先转换成等价的不含子查询的语句去执行,如:Select A.f1,B.f1 from A, B where A.f2=B.f2;转换成:Select A.f1,B.f1 from A,C w

36、here A.f2=C.f2 and C.f3=V_1;4.1.8. Select* from report where SALES_CODEexists ;Oracle 先扫描 report 的一个记录,然后去执行里层子查询里的语句,只要能检索到一条记录,则立即返回给外层一个 true 的值,report 的当前记录就可以返回给用户,扫描一下一条记录;如果子查询执行完毕都还没有检索到一条记录,则返回 false 给外层,则表示 report 当前记录不符合条件,则继续扫描下一条记录,直到结尾;4.1.9. in,exists 的选择的选择一般情况下,in 的子查询都可以写成 exists 的

37、子查询,以下两种选择可以优化性能:1) 当内层子查询的过滤条件有很强的过滤作用时,考虑使用 in,因为内层子查询返回的数据源比较少;2) 当外层查询的过滤条件有很强的过滤作用时,且内存查询可以使用索引快速定位,则考虑使用 exists;4.1.10. select yadfw as t1,kopeew as t2 From A union all select uufger as t1,poeprvcx as t2 from Bunion all 前后是两个独立的查询,它的作用是合并 2 个记录集.内部处理时,oracle 先执行 union all 之前的查询返回记录给用户,执行完毕后,接着

38、执行 union all 后面的查询,把查询结果返回给用户;应用程序中,有很多报表或网格显示的上下行内容来自于互不相干的表,但由于使用绑定数据源的方式,显示数据只能由一次 SQL 语句检索得到,此时 union all 就派上用场了;Union all 两端查询的字段个数以与对应的数据类型要一致;Union 也有把多个查询的记录集合并的功能,但它与 union all 的不同之处是,当 oracle检索到的每条记录时不会马上返回给用户,会把它送到一个排序区中进行排序,排序中以字段在 select 列表中更靠前的则先排序,当不同记录中各个字段信息全部相同时,oracle 只留下一条记录,废除其他

39、相同记录;所以,当不需要排序且允许相同记录存在时,使用 union all 性能比 union 好;4.2. 几种常见操作或函数几种常见操作或函数4.2.1.比较符比较符 like这是一个模糊查询操作的字符串比较符,如 where A like ww%,通配任意字符的符号%,如果单个字符通配是_.作比较的串中,如果%或_放于最前面,oracle 将不用索引;4.2.2.is null,is not null当比较一个字段是否为 null 或非 null 时,应该使用 where f1 is null 或 where f1 is not null,而不能用=或比较符;任何值与 Null 做=,比

40、较时,都返回 false;任何值与 null 进行+-*/数字运算操作时,得到的还是 null;字符串与 null 值使用|连接还是那个字符串值;4.2.3.to_char,to_date,to_numberto_char 可以把一个数字值转换成字符串,这个简单,不多讲;to_char 把日期型转换成字符串时,最通用的格式yyyy-mm-dd hh24:mi:ss,其中yyyy 是 4 字符年份,mm 是 2 字符月份,dd 是 2 字符日期,hh24 是 24 小时制的时间,如果 12 小时制则用 hh,mi 是 2 字符分钟,ss 是 2 字符秒数.格式可以灵活使用,如取得日报的年份:se

41、lect to_char from report;to_date 是把字符串转换成日期,最通用格式与 to_char 一样,如:to_date;to_number 就是把只含数字的字符转换成数字;在写 SQL 语句时,如果条件中有类型不一致的比较,应该使用函数来显式转换他们,而不要让 oracle 自动转换导致有些索引不能使用;4.2.4.nvlnvl:如果值 v_1 为 null,则返回值为 v_2,否则返回 v_1;4.2.5.其他其他Decode,case when 函数比较有用,具体用法参考其他书籍;5.表设计的一些建议表设计的一些建议1) 避免多种不同类型的数据放在同一张表中如 ep

42、m 中的 anken 表,可根据 distinguish 种类设计成多张表存储.目前情况放在一起的缺点是,项目,任务,风险都放在一起保存,当要查一个项目时,oracle 内部扫描表会扫描非常多的有关任务,风险等类型的记录,这些任务或风险信息越多,查找到某个项目的时间就越长;类似的,查找任务或风险时也有这个问题;上述情况就应该把不同的业务类型数据用不同的表保存;目前的设计,如果 Anken 表数据量很大时,可考虑使用分区技术去优化,这是 oracle 数据仓库经常使用的技术,可参考相关资料;2) 表的拆分表字段越少,一个块中能存储表的记录数就更多,查询肯定就更快了;当表的字段非常多时,而有些字段

43、信息偶偶才使用,可以考虑把表分成 2 个表,经常用的字段在一个表中,不常用的字段在另外一个表中;这可以理解为数据的纵向分离;拆分的缺点是当 2 个表中的信息都需要时就必须有 2 个表的 join 操作,这个操作耗费大,同时应用程序的编码可能会更复杂些.所以在利弊当中去权衡使用;举例:Report 表中有 381 个字段,我认为经常使用的可能不到 10%,因此有些字段是可以分离的,可以提高性能;例如,定制字段就有 270 个,我们可以把最常用的每种类型的前 5 个根据需要确定个数保留在 report 表中,其他的分离到 report_2 表中;3) 适当的冗余举个例子,医院管理系统中有病人信息表

44、 patient,医嘱表 doctor_advide,这 2 个表在系统运行 2 年后数据量将会很大,因此设计表时,医嘱表除了有病人代码这个字段,同时需要把病人名称也冗余进去,否则每当打印病人的医嘱时,将要从 patient 去获取病人名称,耗费巨大.更坏的是,有时为了获得病人的名字信息而把这两个表 join 起来,这样就很费时;冗余的缺点就是每当你维护病人信息表时,如果名称有更改,则其他表中有冗余这个信息的字段值都要更改,以达到数据一致性;所以,对于相对静止的数据的容余是可以的,数据仓库就是这样;参考文献Oracle 9i SQL ReferenceORACLE9i Performance Tuning1.pdfORACLE9i Performance Tuning2.pdfDatabase Performance Tuning Guide and ReferenceDatabase Reference releaseOracle 9i Data Warehousing Guide

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号