欢迎光临
免费的PDF电子书下载网站

收获,不止Oracle PDF下载

编辑推荐

  颠覆IT技术图书的传统写作方式,在妙趣横生的故事中学到Oracle核心知识与优化方法论,让你摆脱技术束缚,超越技术。

 ;

内容简介

  在《收获,不止Oracle》这本书里读者将会跟随作者一同对Oracle数据库的相关知识进行梳理,最终共同提炼出必须最先掌握的那部分知识,无论你是数据库开发、管理、优化、设计人员,还是从事Java、C的开发人员。接下来作者再将这部分知识中最实用的内容进一步提炼,浓缩出最精华的部分,分享给大家。这是二八现象的一次经典应用。
  这部分知识就是Oracle的物理体系结构、逻辑体系结构、表、索引以及表连接五大部分。通过阅读这些章节,读者将会在最短时间内以一种有史以来最轻松的方式,完成对Oracle数据库的整体认识,不仅能在工作中解决常规问题,还能具备一定的设计和调优能力。相信通过这些章节的学习,会给读者的Oracle学习带来极大的收获。
  然而,作者最希望看到的是:让读者的收获,不止Oracle。
  为达到此目的,作者精心将全书分成了上下两篇,刚才所描述的具体知识点体现在全书的上篇,而在下篇中,读者将通过各种精彩故事、生动案例,体会到该如何学习和如何思考,在意识的天空抛开束缚,无拘无束、尽情飞翔。
  在这里,读者也许会有疑问,前面说的有史以来最轻松的方式是一种什么样的方式呢?还请亲爱的读者自己去揭晓谜底吧。

作者简介

  梁敬彬,网名wabjtam123,任ITPUB版主、ITPUB社区专家、福建富士通公司数据库专家。参与编写过《剑破冰山--Oracle开发艺术》、《DBA手记2》等技术书籍,多年从事电信相关行业工作,负责系统架构设计、优化、培训等工作,有着丰富的数据库管理、设计、开发、培训经验和电信行业经验。

  梁敬弘,清华大学计算机系博士毕业,在计算机领域和金融领域皆有建树,拥有多项计算机相关核心专利技术的同时还拥有金融行业的CFP等高级认证。现就职于华夏银行总行。

收获,不止Oracle PDF下载

目录

上篇 开启惊喜之门--带意识地学Oracle
第1章 意识,少做事从学习开始
1.1 选择先学什么颇有学问
1.1.1 梁老师课堂爆笑开场
1.1.2 看似跑题的手机分类
1.1.3 学什么先了解做什么
1.2 善于规划分类才有效果
1.2.1 分类与角色密切相关
1.2.2 角色自我认识有讲究
1.3 明白学以致用方有意义
第2章 震惊,体验物理体系之旅
2.1 必须提及的系列知识
2.2 物理体系从老余开店慢慢铺开
2.2.1 老余的三个小故事

媒体评论

  岂曰无衣,与子同袍。此书必为IT行业带来一股清新之风,打造出IT书籍的一段传奇佳话,成就一部永不过时的经典力作!我相信,此书将为广大读者开启惊喜之心扉,让读者飞翔在思想的天空、遨游在方法论的海洋、采摘到技术的累累硕果,相信收获远不止Oracle!
  福富软件公司副董事长、总经理:杨林
  作者在书中反复传达的核心观点是:Oracle数据库看似艰深的原理实际上和生活中的基本常识并无二致。理解了这一层意思,就能够克服对于这门技艺的畏惧之心,此后的学习自然就能够顺风顺水。诚然如此,我也经常和朋友们说,对于Oracle的很多艰深算法,如果由我们去深思熟虑,其结果都必然大致相同。类似HASH原理,布隆过滤等算法,理解了你就只觉得巧妙而不觉艰深。现在梁老师就为我们寻找了一系列源于生活、循序渐进的学习路线,如果你能够细心领会,就会觉得这一门技艺实在是趣味横生。
  ——盖国强(eygle)Oracle ACE总监、云和恩墨创始人、ACOUG创始人

前沿

别出心裁 另出蹊径

                       ——与梁敬彬先生序

 

敬彬的新书就要出版,邀我写一点感受,于是就有了这一段文字。

我和敬彬相识是在2010年,那时我正在编辑《OracleDBA手记》一书,偶然被他发表在ITPUB论坛上的一篇文章所吸引,那篇文章的题目是《DBA 小故事之SQL诊断》,其内容清晰、行文引人,于是就和他约了那篇稿子加入到书中,期间邮件往来再到北京会面,就此熟识。

从当时的一篇文章到今天的一本书,我能够清晰地看到作者一以贯之的思考和叙述方式,这种积累与坚持也正是作者成长和成功的要素之一。

当时那篇文章的感受和今天这本书是类似的,作者能够用曲折的笔触将自己的经历真实生动地再现出来,并且带领读者一起经历一次思维的探索,这是属于他的独特风格。

作者在书中反复传达的核心观点是:Oracle数据库看似艰深的原理实际上和生活中的基本常识并无二致。理解了这一层意思,就能够克服对于这门技艺的畏惧之心,此后的学习自然就能够顺风顺水。

诚然如此,我也经常和朋友们说,对于Oracle的很多艰深算法,如果由我们去深思熟虑,其结果都必然大致相同。类似HASH原理,布隆过滤等算法,理解了你就只觉得巧妙而不觉艰深。

现在梁老师就为我们寻找了一系列源于生活、循序渐进的学习路线,如果你能够细心领会,就会觉得这一门技艺实在是趣味横生。

盖国强(eygle

Oracle ACE总监

云和恩墨创始人

ACOUG创始人

免费在线读

  2.3.2  单车到飞船的经典之旅
  “刚才老师回答了不少同学的疑问,说明了学习体系结构还是有意义的。看来只要善于思考,善于联系,我们就能很容易地应用所学的知识解决遇到的问题。
  现在我给大家讲一个具体的案例,通过执行系列等价SQL语句的性能差异,来分析其中的原因所在。
  2.3.2.1  未优化前,单车速度
  首先构造环境,保证下列语句执行过了,t表已经存在:
  
  sqlplus ljb/ljb
  drop table t purge;
  create table t ( x int );
  --将共享池清空
  alter system flush shared_pool;
  脚本2-29  单车到飞船试验前的准备工作
  有一个开发人员写了类似如下的一个简单存储过程,实现了将1到10万的值插入t表的需求,具体如下:
  
  create or replace procedure proc1
  as
  begin
      for i in 1 .. 100000
      loop
          executeimmediate
          insert into t values( ||i||);
      commit;
      end loop;
  end;
  /
  ----这里要记得先预先执行一遍,将过程创建起来!
  脚本2-30  单车到飞船试验前构造proc1
  该语句从需求实现上没有任何问题,我们执行如下:
  
  SQL> connect ljb/ljb
  已连接。
  SQL> drop table t purge;
  表已删除。
  SQL> create table t ( x int );
  表已创建。
  SQL> alter system flush shared_pool;
  系统已更改。
  SQL> set timing on
  SQL> exec proc1 ;
  PL/SQL 过程已成功完成。
  已用时间:  00: 00: 42.87
  SQL> select count(*) from t;
    COUNT(*)
  ------------------------
    100000
  脚本2-31  首次试验42秒完成,仅是单车速度
  该语句用42秒时间完成10万条记录的插入,大家觉得速度快吗?”
  “1秒钟插入2千多条记录,速度好快啊!”小莲在数学上的反应还是很敏捷。
  “哦,你希望还能更快一点吗?”梁老师问。
  “哦,当然希望了,肯定是越快越好了。”小莲回答得不假思索。
  “其实这个简单的过程如果想更快,靠的就是对体系结构的理解,下面大家跟我查询一下该过程执行中,数据库共享池中的相关情况。
  共享池中缓存下来的SQL语句以及HASH出来的唯一值,都可以在v$sql中对应的SQL_TEXT和SQL_ID字段中查询到,而解析的次数和执行的次数分别可以从PARSE_CALL和EXECUTIONS字段中获取。
  由于这个过程PROC1执行的是insert into t的系列插入,于是我们执行如下语句来查询PROC1在数据库共享池中执行的情况,具体如下:
  
  select t.sql_text, t.sql_id,t.PARSE_CALLS, t.EXECUTIONS
    from v$sql t
   where sql_text like \%insert into t values%;
  脚本2-32  原来是因为未用绑定变量
  为了让SQL语句及展现结果看起来更美观,我将上述SQL在PL/SQLDEVELOPER工具中查询(这个工具有着很友好的界面,尤其适合数据库开发人员使用,因此除了介绍先前的sqlplus工具外,这里也顺道提一下这个PL/SQLDEVELOPER工具),发现共享池中有大量的类似SQL语句,而SQL_ID各自不同,每个语句都只是解析1次,执行1次,解析了10万次了,怪不得速度如此之慢,如图2-26所示。
  
  图2-26  绑定变量
  2.3.2.2  绑定变量,摩托速度
  此时我们这么想,要是insert into t values (99898)、insert into t values(99762) 等这10万条语句如果都能合并成一种写法,比如用变量代替具体值,成为insert into t values (:X),那岂不是这10万条语句可以被HASH成一个SQL_ID值,不就可以做到解析1次,执行10万次了?这就大大减少了解析时间。
  这就是数据库的一个典型优化,绑定变量优化!
  接下来我们将proc1改进为proc2,具体写法如下:
  
  create or replace procedure proc2
  as
  begin
      for i in 1 .. 100000
      loop
          executeimmediate
        insert into t values ( 😡 )using i; 
    commit;
      end loop;
  end;
  /
  ----这里要记得先预先执行一遍,将过程创建起来!
  脚本2-33  第2次改进,将proc1改造成有绑定变量的proc2
  接下来我们继续执行测试proc2过程(注意表重建的目的是为了公平,测试都在无记录的空表上进行,并且共享池都清空):
  
  SQL> drop table t purge;
  表已删除。
  SQL> create table t ( x int );
  表已创建。
  SQL> alter system flush shared_pool;
  系统已更改。
  SQL> set timing on
  已用时间:  00: 00: 00.00
  SQL> exec proc2;
  PL/SQL 过程已成功完成。
  已用时间:  00: 00: 08.41
  SQL> select count(*) from t;
          COUNT(*)
  -----------------
  100000
  脚本2-34  第2次改进后8秒完成,单车变摩托
  这次我们惊奇地发现,速度从原来的42.87秒缩减为8.41秒,大幅度提升了,每秒插入记录数达到1万多条,大大超过之前的每秒插入2千多条的速度,为什么会这么神奇呢?”梁老师停下来问大家。
  “因为语句被绑定变量了,解析次数变少了!”梁老师的话同学们记得很牢。
  “很好,那我们一起看看吧,看看有啥变化(如图2-27所示):
  
  图2-27  解析与执行次数
  虽然插入的语句值各不相同,但是都被绑定为:x,所以被HASH成唯一一个HASH值,名称为dxz576128adaw,很明显可以看出解析1次,执行10万次,这就是速度大幅度提升的原因了。
  这下大家对这个速度满意了吧。”
  小莲这下才发现,原来简单的体系结构后面还真有不少玄机啊,也不只是上堂课梁老师说的加大减少共享池这么简单,小莲觉得今天的课太值了。
  2.3.2.3  静态改写,汽车速度
  “大家还想不想再快一点?”梁老师这次开口吓了大家一跳。
  “梁老师您太贪心了吧!”晶晶打趣地说道,看来课堂上同学们还真是被梁老师带动得无拘无束了,什么话都敢说啊。
  “其实真的是还能再快的,你们看看这两个过程,是否觉得哪里写得有点别扭?”梁老师提醒大家认真看proc1和proc2。
  “梁老师,这个execute immediate和双引号是啥意思啊,为什么不直接写成insert into t values(i)啊?”刚才开玩笑的曾祥也提问了。
  “不错!终于看出来了,executeimmediate是一种动态SQL的写法,常用于表名字段名是变量、入参的情况,由于表名都不知道,所以当然不能直接写SQL语句了,所以要靠动态SQL语句根据传入的表名参数,来拼成一条SQL语句,由executeimmediate调用执行。但是这里显然不需要多此一举,因为insert into t values(i)完全可以满足需求,表名就是t啊。
  我们来改写成proc3,如下:
  
  create or replace procedure proc3
  as
  begin
      for i in 1 .. 100000
      loop
       insert into t values (i); 
    commit;
      end loop;
  end;
  /
  ----这里要记得先预先执行一遍,将过程创建起来!
  脚本2-35  第3次改进,将proc2改造成静态SQL的proc3
  接下来我们继续测试proc3的性能,也是在公平的环境下操作的,如下:
  
  SQL> drop table t purge;
  表已删除。
  SQL> create table t ( x int );
  表已创建。
  SQL> alter system flush shared_pool;
  系统已更改。
  SQL> set timing on
  SQL> exec proc3;
  PL/SQL 过程已成功完成。
  已用时间:  00: 00: 06.25
  SQL> select count(*) from t;
    COUNT(*)
  ------------------
      100000
  脚本2-36  第3次改进后6秒完成,摩托变汽车
  大家看看,现在是什么情况?” 梁老师笑着说。
  “哇,又快了!”晶晶惊叫起来,引来了一片笑声。
  “为什么会快了,我们分析分析,这个语句肯定有用到绑定变量,一般来说,静态SQL会自动使用绑定变量,我们来查看查看(如图2-28所示)。
  
  图2-28  静态SQL解析与执行次数
  果然如此,proc3也实现了绑定变量,而且动态SQL的特点是执行过程中再解析,而静态SQL的特点是编译的过程就解析好了。这点差别就是速度再度提升的原因。现在大家对这个速度满意了吧。”
  台下纷纷点头。
  2.3.2.4  批量提交,动车速度
  “还能再快一点吗?”梁老师再次发问引发台下一片大笑,因为大家这时都认为老师是在开玩笑。
  “别笑,我可不是开玩笑哦,同学们再执行这个proc3,看看有啥新发现。”
  “梁老师,我看到commit了,我觉得应该放在循环的外面而不是里面。放在里面意味着每插入1条,就要提交1次,那放在循环里就要提交10万次,而放在循环外就是全部插入完后提交1次,我觉得少提交更好。”细心的小莲发现了commit位置的不同。
  “说得非常好,commit触发LGWR将REDO BUFFER写出到REDOBUFFER中,并且将回滚段的活动事务标记为不活动,同时让回滚段中记录对应前镜像记录的所在位置标记为可以重写,切记commit可不是写数据的动作哦,写数据将数据从DATABUFFER刷出磁盘是由CKPT决定的,前面大家应该有印象。
  所以commit做的事情开销并不大,单次提交可能需要0.001秒即可完成。另外不管多大批量操作后的提交,仅针对commit而言,也是做这三件事,所花费的总时间不可能超过1秒。打个比方,批量100万条更新执行后完成commit的提交可能也就需要0.8秒,但是100万×0.001的时间可是远大于1×0.8的时间了。
  下面我们来做做试验,将proc3改写为proc4,具体如下:
  
  create or replace procedure proc4
  as
  begin
      for i in 1 .. 100000
      loop
       insert into t values (i); 
  end loop;
    commit;
  end;
  /
  ----这里要记得先预先执行一遍,将过程创建起来!
  脚本2-37  第4次改进,将proc3改造成提交在循环外的proc4
  接下来我们继续测试proc4的性能,也是在公平的环境下操作的,如下:
  
  SQL> drop table t purge;
  表已删除。
  SQL> create table t ( x int );
  表已创建。
  SQL> alter system flush shared_pool;
  系统已更改。
  SQL> set timing on
  SQL> exec proc4;
  PL/SQL 过程已成功完成。
  已用时间:  00: 00: 02.18
  SQL> select count(*) from t;
    COUNT(*)
  -----------------
      100000
  脚本2-38  第4次改进后2秒完成,汽车变动车
  速度是多少?”梁老师回头看着大家。
  “哇,2秒就完成了!”还是晶晶的惊叫声。
  “等同于每秒5万条记录,原先可是每秒2千多条啊,不可思议!”小莲数学换算总是最快。
  2.3.2.5  集合写法,飞机速度
  “还能更快吗?”梁老师没完没了啊。
  “不可能!”这下同学肆无忌惮地大笑了,他们知道梁老师这回肯定是故意的了。
  “不可能?看来你们又认为老师在开玩笑了,如果老师能让插入该表的动作更快,你们请老师吃饭,否则老师请你们吃饭?”
  “没问题!”同学们应答得好干脆啊,他们其实心里也知道,这请客的说法一定是开玩笑,课堂的气氛被调到了最高潮了。
  “好吧,同学们,大家看这条SQL语句的写法,如下:
  
  insert into t select rownum from dual connect bylevel<=100000;
  
  表示我从1到10万依次插入到t表中,完全满足刚才的需求,不过这种写法大家可能略感陌生,结果却是对的。现在我们执行如下:
  
  SQL> drop table t purge;
  表已删除。
  SQL> create table t ( x int );
  表已创建。
  SQL> alter system flush shared_pool;
  系统已更改。
  SQL> set timing on
  SQL> insert into t select rownum from dual connect bylevel<=100000;
  已创建100000行。
  已用时间:  00: 00: 00.25
  SQL> commit;
  提交完成。
  已用时间:  00: 00: 00.00
  SQL> select count(*) from t;
    COUNT(*)
  -----------------
    100000
  脚本2-39  第5次用集合写法后0.22秒完成,动车变飞机
  大家认真看看完成的时间吧。”梁老师得意地回过头望着大家。
  “0.25秒!”这次不再是晶晶一人的声音了,是全部同学一起喊起来了。
  “每秒插入40万条,太快了吧!”小莲再次喊出声来。
  “为什么会快这么多呢?其实是因为原先的过程变成了SQL,一条一条插入的语句变成了一个集合的概念,变成了一整批地写进DATABUFFER区里,好比你要运砖头到目的地,一种是一块砖头拿到目的地,再返回拿第二块,直到拿完全部。而另一种是全部放在板车一起推至目的地,只是这里的目的地是DATABUFFER区而已。
  听明白了吗?”
  “听明白了!”大家都很激动,梁老师真像一个魔术师。
  “听明白就好,现在你们该好好想想请老师晚上去哪里吃饭了。”
  同学们都乐了,大家心里都知道梁老师是在开玩笑。
  2.3.2.6  直接路径,火箭速度
  “没声音啊,看来大家怕花钱啊,要不老师再给同学们一个机会,如果我还能让这个插入语句更快,大家就请客,否则老师请客,如何?”
  梁老师有完没完啊,都每秒钟40万条的速度了,还想快,疯了吧。同学们议论纷纷。
  “那我开始了,因为前面完成时间都已经到零点几秒了,太小会有误差,所以我准备把数据量放大100倍,10万条改为插入1000万条,前面飞机速度的语句变成如下:
  
  SQL> connect ljb/ljb
  已连接。
  SQL> drop table t purge;
  表已删除。
  SQL> create table t ( x int );
  表已创建。
  SQL> alter system flush shared_pool;
  系统已更改。
  SQL> set timing on
  SQL> insert into t select rownum from dual connect bylevel<=10000000;
  已创建10000000行。
  已用时间:  00: 00: 23.22
  SQL> commit;
  脚本2-40  试验准备,将集合写法的试验数据量放大100倍
  发现插入1000万条记录完成的时间是23秒多,大致为每秒钟43万条记录,和插入10万条记录时的速度每秒40万条大体接近,下面我们改用createtable 的直接路径方式来新建t表,看看这样的方法速度能否有提升。
  
  SQL> drop table t purge;
  表已删除。
  已用时间:  00: 00: 11.07
  SQL> alter system flush shared_pool;
  系统已更改。
  已用时间:  00: 00: 00.02
  SQL> set timing on
  SQL> create table t as select rownum x from dual connect bylevel<=10000000;
  表已创建。
  已用时间:  00: 00: 10.14
  脚本2-41  第6次改进,直接路径让飞机变火箭
  测试结果是,速度又有了2倍多的提升,只需要10秒即可完成,等同于插入速度为每秒钟100万条,要不是亲眼所见,还真不敢相信吧。
  同学们知道这是为什么吗?真正的原因在于,insert into t select ……的方式是将数据先写到DATABUFFER中,然后再刷到磁盘中。而create table t的方式却是跳过了数据缓存区,直接写进磁盘中,这种方式又称之为直接路径读写方式,因为原本是数据先到内存,再到磁盘,更改为直接到磁盘,少了一个步骤,因而速度提升了许多。
  直接路径读写方式的缺点在于由于数据不经过数据缓存区,所以在数据缓存区中一定读不到这些数据,因此一定会有物理读。但是在很多时候,尤其是海量数据需要迁移插入时,快速插入才是真正的第一目的,该表一般记录巨大,DATABUFFER甚至还装不下其十分之一、百分之一,这些共享的数据意义也不大,这时,我们一般会选择直接路径读写的方式来完成海量数据的插入。
  同学们,听明白了没,现在大家甘心请客了吧?”梁老师时刻不忘调侃。
  台下都听呆住了,梁老师这堂课真是神了,大家半天没回过神来。
  2.3.2.7  并行设置,飞船速度
  “大家这次请客是请定了,具体时间老师通知哦。”
  台下哈哈大笑,大家还是回过神来了,今天这堂课给梁老师弄得一愣一愣的。
  “同学们,插入语句还能再快吗?”
  这下台下同学们都不敢应答了,梁老师没完没了,却每次都能不断加速,而且用到的知识又和体系知识息息相关,让自己一听就明白了。可以看出梁老师这个经典案例的例子是精心构造的,真可以说是经典中的经典。
  “看来是被我给忽悠住了,大家都不敢应了。”梁老师笑着说道,“其实遇到性能好的机器,还是可以大幅度提升性能的,大家看如下语句,我设置日志关闭nologging,并且设置parallel16 表示用到机器的16个CPU,结果在笔记本环境收效不是很明显,因为我的环境是单核的机器。
  后来我把如下SQL运行在强劲的服务器上,有16个CPU,下面的语句仅仅在4秒不到的时间内就完成了,速度相对于前面的火箭速度而言,快多了,几乎是每秒钟300万条的插入速度,具体如下:
  
  drop table t purge;
  alter system flush shared_pool;
  set timing on
  create table t nologging parallel 64
  as select rownum x from dual connect by level<=10000000;
  脚本2-42  第7次改进,并行原理让火箭变飞船
  不过并行最大的特点就是占用了大多数CPU的资源,如果是一个并发环境,很多应用在跑,因为这个影响了别的应用,导致别的应用资源不足,将引发很多严重问题,所以需要三思而后行,了解清楚该机器是否允许你这样占用全部的资源。
  好了,今天我以一条最简单的插入顺序数字进某表的SQL语句为例,方法从存储过程实现到仅用单条SQL完成;速度从原先的每秒2千多条提升到每秒300万条,这中间都做了哪些改进呢,是否都和体系结构有关呢?
  希望大家好好复习这一节的经典案例,回忆一下速度的6次飞跃之旅,好好感受一下灵活应用知识的无限魅力。”

收获,不止Oracle pdf下载声明

本pdf资料下载仅供个人学习和研究使用,不能用于商业用途,请在下载后24小时内删除。如果喜欢,请购买正版

pdf下载地址

版权归出版社和作者所有,下载链接已删除。如果喜欢,请购买正版!

链接地址:收获,不止Oracle