SQL编写及其优化培训.doc
《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;把列嵌套在函数里索引不能使用,这
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SQL 编写 及其 优化 培训
链接地址:https://www.desk33.com/p-21548.html