<SQL 语言艺术>读书笔记 一到六章

SQL 语言艺术读书笔记

 

第一章  制定计划:为性能而设计

规范化的重要性

想到了一个笑话:

     一天外科医生,水利工程师,土木工程师,IT工程师坐下来讨论谁的职业是最古老的。

 水利工程师说 大禹治水是水利工程史上的一个壮举,所以水利工程是最古老的职业。

 外科医生说:不对,上帝抽下了男人的一条肋骨,做成了女人。这个是最早的外科手术。外科医生才是最古老的职业。

 土木工程师说:盘古利用斧子劈开了混沌。使混乱的空间变得有顺序。这可是伟大的土木工程。

 听到这里IT工程师笑了:那么混乱是谁造成的呢?

 

诚然:混乱是谁造成的呢?笑话的意思就是 混乱是由IT工程师造成的。混乱是怎么产生的呢,是由于我们思考的不充分造成的。任何人的思考都未必是充分的。所谓:智者千虑必有一失。

 

设计时的规范:

1 确保数据的原子性 仁者见仁 智者见智。高度不同,需要的信息也不同。就如总裁不会关系某一个员工。对他来说分公司才是原子。

2 对键的完全依赖性 糟糕的设计,冗余的数据增加了维护的成本。比如在一对多的关系中 一的特性写进了多的表里,那么维护时一的就要修改就要进行多的操作。查询时要去重复记录。

3 检查属性独立性

 

有值,无值,空值

NULL来到你身边,带着嘲笑,带来了无尽的烦恼。关于空的运算规则大家百度一下。各前辈高人都做出了精彩的解释,并举例。这里不在一一复述。(网络的空间也是很贵的嘛。人家免费让我发表东西,但是也是有成本的。这样浪费就不好了,省得钱就给小朋友买点糖好了,就算买不了糖,买点自来水,浇些花花草草的也是好的嘛。 PS以下 哈哈。)

个人觉得:只有在选填内容的时候可以为空。总不能注册个用户还必须回答所有的问题吧。

而做状态标志的时候,就不适合为空了。可以用数字作为标志。使用CHECK约束来约束字典值的取值范围。(可以在开发时使用。待投产后,可以拿掉。约束的校验也是耗费资源的。)

总不能这样写WHERE字句吧 WHERE COLUMN_VALUE IN (NULL,’1’).这样又取不到NULL值记录。并且 IS  NULL 是不能使用索引的。

 

过于灵活的危险性就不讨论了。古之定论,物极必反。

 

历史数据的难题

系统中常常存有历史数据。如何设计这样的表呢?情况不同处理方法也不同。

1 分区。数据量大的表,时间变化有明显的规律性。

2 当前表与历史表相结合 

适用于 数据变化频繁。历史数据很少被调用。

3 存在一张表中,创建起始日期 结束日期字段。 适用于数据变动不频繁。(还是不推荐)。

 

设计与性能

 

   “先把程序写出来,之后让调优专家在生产环境中调优这种想法是错误的。 性能专家只能解决技术上的错误(典型的有 不使用DECODE 重复扫描一个表。)但是逻辑上的调优性能专家是无法解决的。

 

 

第二章 发动战争:高效访问数据库

查询识别

DBMS_APPLICATION_INFO这个包暂时不会用。

 

 

保持数据库连接稳定:

数据库连接是个很重的操作。需要很多资源。

程序与数据库交互也有开销。

战略优先于战术:

这个我没有领悟上去。唉 才疏学浅。战略没有变化,也就是需求没有变化。只不过实现方法变化了。应该是战术问题吧。同样是守住一个地方歼灭敌人(战略),地雷战就可以搞定的事情,使用地道战。(战术)结果当然耗费资源,劳民伤财了。

总结写的还不错: 站的更高,看的更远。(个人认为 写尿的更远也是可以的。站在高处只能看么)

先定义问题,再解决问题

总结写的不错。先打好基础,再摆弄新技术。连表连接都不会的人, 怎么创建基于多表的视图呢。

 

保持数据库模式稳定

不要在存储过程中适用DDL语言(TRUNCATE TABLE 除外)。临时表可以单独建立。

 

直接操作实际数据

尽量少使用临时表。特殊情况除外。临时表内容请参见后续文章。

 

SQL处理集合

SQL基于集合来处理数据。不要使滥用COMMIT.这样会生成更多的重做日志,UNDO信息,并且出错后的处理更加浪费资源。

 

充分利用每次数据库访问

一次查询得到尽可能多的结果。避免多次访问数据库。

 

接近DBMS核心

代码的执行越接近DBMS核心,执行速度越快。尽量使用oracle提供的函数。

 

只做必须做的

对于如下需求 存在某些记录,则修改这些记录。无需先校验这些记录是否存在。对于那些想返回修改了多少记录的需求 则可以如下:

 出于数据保护的考虑 ,后续还会用到这些数据。实际上等于没有修改其工资。

 

DECLARE

  v_count NUMBER;

BEGIN

  UPDATE emp t SET sal = sal + 0 WHERE t.deptno = 20;

  v_count := SQL%ROWCOUNT;

  dbms_output.put_line('一共修改了' || v_count);

  COMMIT;

EXCEPTION

  WHEN OTHERS THEN

    dbms_output.put_line(SQLERRM);

    ROLLBACK;

 

END;

 

 

慎用自定义函数

据说优化器不会打开函数内的查询。这个个人任务 函数可以包含过程语句。这种函数优化器是无法解析的。

 

 

进攻式编程

假设大部分数据都是合理的(大部分前台也会控制的吧)。再进行操作。如果无被操作数据,那么找出无被操作数据的原因。(很可能是参数不正确。)

 

第三章 战略部署:建立索引

找到‘切入点’

您必须了解用户常用的搜索条件。这个是根据业务逻辑来制定的。正所谓庖丁解牛,游刃有余。知道了需求,再在选择性高的列上建立索引,可以是数据库很快的找到需要查找,处理的纪录。  如果索引制定的策略,与需求严重不符的话,增加索引反而适得其反。

 

原因就是,维护索引比维护记录还要耗费资源。据书中所述,插入一条记录需要100个单位的时间,维护这条记录涉及的一个索引,就要占用100-250个单位的时间。资源包含存储的资源与计算的资源。在目前存储设备的价格越来越低的情况下,存储资源空间的浪费也许不会是太大的问题。但是对计算资源的浪费却是不可忽略的。B_TREE索引的维护是很耗费资源的。这是由索引的结构决定的。另外,索引常常连同数据被一同备份。那么在恢复时,索引的恢复也要耗费相当的资源。

 

但是这些都不是不使用索引的理由。对于少量数据的查找与处理,使用索引那是‘相当’的快。

(感谢IT PUBCCTV, WORLD_TV,将来没准还要感谢 宇宙TV

赋诗一首:

  索引阿,不和你说再见。

没有你的世界,查询何其可怜。

今天的服务器难道崩溃的噩运。

已经运行了一天地全表扫描,怎么还没完。

 

 (谢谢,想学写诗的,跟我联系。暑期优惠,一万包教包会。)

 

 

索引仍然是数据库不可分割的一部分。就像台湾与中国一样。(扯得有点远。但是一提到不可分割就想到台湾了。)

 

此节最后有云:对于通用目的,与事务处理型数据库而言,大部分表不需要增加索引。也许如此吧。不过我目前做的项目还是很依赖索引的。可能是交易量太大的原因吧。

 

             

索引与目录

索引是到具体某句话的。目录是到个个章节的。他们的粒度是不一样的。

 

让索引发挥作用

 

讨论了检索比率。很古老的话题了。不应该局限于一个定数。数据库在变,硬件设备也在变,数据量也在变。要看一共需要处理的数据有多少。

 

又讨论了大容量缓存的现代磁盘系统起的作用。这个涉及到Oracle系统数据的缓存方式。这里不在这里复述了。大家可以参看 Oracle编程的艺术:深入了解体系结构。

 

函数和类型的转换对索引的影响

函数使索引失效的原因。索引的树形结构决定了索引是按照顺序排列的。对索引使用函数无法保障使用函数之后的结果,与索引的顺序相同。比如对’abc’,’cba’两个字符串取第三位。就会得到与 索引顺序完全相反的结果。

至于书中所言 对字段讨使用函数,就意味着数据不符合业务需求。此时连1NF都不符合。有些时候可以转换成符合范式的办法。但是有些时候,由于业务逻辑所限。还是没有办法的。比如当一组编号的后几位为校验位时(比如身份证的后四位),就需要对前面的信息截串。

 

 

隐式转换看不见的性能杀手

 

Where deptno=20.这条语句的意思大家都明白。查询部门编号为20的数据。但是部门编号并非数字,因为部门编号不具数学运算意义。所以oracle会进行隐式转换。把varchar2转换位number

说明了 Oracle 执行的语句等价为:to_number(deptno)=’20’。使用了函数,索引失效了。

 

 

基于函数的索引 Oracle提供一种基于函数的索引。但是函数索引的维护,更加的消耗资源。每当索引列修改,要计算其使用函数后的值。然后存到索引中去。

 

第四章 机动灵活:思考SQL语句。

SQL语言与数据库

大部分都是概念类的描述。大家可以去china-pub上下载一下试读章节。

SQL中的关系操作:关系理论的适用范围。关系理论只是被用来通过关系(关联)根据条件找到合适的数据。

 

SQL中的非关系操作。

找到结果集之后的操作就不在属于关系操作。如order by ,group by, having

但是SQL依然支持这些非关系操作。因为这些操作有着重要的实用性。

 

SQL与优化器

SQL语言是声明性语言

 

select *

from emp t1,dept t2

where t1.deptno= t2.deptno

 

这条语句声明了 要取这两张表的数据。数据通过t1.deptno= t2.deptno这个关系相关联.但是如何取,全表扫描,还是利用索引,使用哪种连接方式. Hash join,merge join, nested loops这个又优化器决定。虽然我们可以通过使用提示来干预。但是这种干预并非强制性的,只是我们指导优化器采用我们指定的连接方式。

 

 

书中的讲解非常的好,请各位仔细阅读下。

 

优化器的有效范围

优化器借助在数据库中找到的信息。

 

能够进行数学意义上的等价变换,优化效果才最佳。

 

优化器考虑整体的响应时间

优化器会估算语句的执行时间。如执行时间较长,则会花费长些的时间来改善性能。但是如果涉及表过多,优化器规定的时间内未必来得及找到最优的执行路径。那么它就会挑一个可能是最优的。请注意是‘可能’。

 

优化器改善的是独立的查询

这个不清楚作者说得是什么意思。

 

是通过临时表传递数据,还是通过内联视图。 不过根据Oracle的文档,优化器会将某些内联视图拆开。

掌握SQL艺术的五大要素

获得结果集所需访问的数据量

 

对于几十条的利用索引还不如全表扫描的快。全表扫描会并行的读多块的数据。

 

定义结果集所需的查询条件

条件的选择性越高,结果集在总数据量中所占的比例越小。

 

结果集的大小

结果集的大小决定着用户愿意等待的时间。当用户知道他查询得到的结果很多时 他们甘愿多等一段时间。但如果他们确定,他们查询的结果只是少量数据的时候,他们所能等待的时间就会很短。我们可以利用提示 first_rows来指导优化器尽快返回前几条记录。

 

表的数量

 

参见优化器考虑整体的响应时间所述

 

复杂查询与复杂视图

 

From子句中包含的对象未必都是表,也可能是视图。视图可能包含非关系操作的内容。这样的视图会独立执行,而不会被拆开。当视图返回的数据远多于我们所需,或视图中包含我们不需要的,不希望看到的非关系操作时,我们应该放弃使用该视图。

 

并发用户数

并发的用户造成资源的争用。还可能造成死锁。

过滤

此节内容非常精彩。无归纳补充。应通篇阅读。

 

第五章 了如指掌:理解物理实现

 

物理结构类型

固定型

必须使用现存的数据库结构,无论他造成性能不佳的可能性有多大。(这个不会是冲着SQL SERVER去的吧?)

 

进化形

有一定灵活性,可以更改数据的物理布局。但是这样做是有风险的。但是可能是最后的希望。

 

冲突的目标

读写总是存在免不了的冲突。

 

为了尽快地读到数据,建立了索引。

但是,写入数据时却要花费好几倍的资源维护索引

 

 

为了增大读的效率,设置db_block_size很大

但是,当不同用户分别要对一个块内的数据修改时,发生了资源争用。

 

 

为了增加写入的效率,避免资源征用,人们把数据分散的写入到不同的位置

但是在读入的时候,却不得不读入更多的块,增加i/o资源的消耗。

 

把索引当成数据仓库

读后觉得数中的意思是把索引当成表。并且还提及了索引组织表。索引组织表,Oracle高效设计中有详细的描述。

 

当我们查询的列都在索引之内,并且过滤条件排在复合索引的首位的时候。数据库只需从索引中取出所需信息就可以了。

由于以后要写关于索引的文章,所以在这里就不再复述了。

 

记录强制排序

记录强制排序可以通过建立聚集索引来实现。插入时开销很高。但是扫描时,效率更高。可以用于基于时间范围查询的应用中。

 

数据自动分组

循环分区:如oracle表空间可以由多个处于不同磁盘上的数据文件构成。

数据驱动分区: 就是我们传统意义上的分区了。根据数据的特点进行分区。

多数表非常的大,是因为包含了历史数据。

个人认为:应当建立适当的清理机制。大多出事务系统中的数据过一段时间(3个月,半年,一年。。。)既不再被关心。分别建立正式表,与历史表。去除过程中的数据。比如数据开始录入是A,中间几经修改B,C,D..最后变成了F 那么在历史表中保留F就可以了。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12474069/viewspace-432941/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12474069/viewspace-432941/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值