分享

海量数据库解决方案

 筠珑枫绦 2011-05-07
2011年04月03日
《海量数据库解决方案》
作者: (韩国)李华植
译者: 郑保卫 盖国强
审校: 张乐奕崔华(2011年01月第1版第1次)
电子工业出版社 Publishing House of Electronics Industry
http://www.
北京市海淀区万寿路173信箱(100036)

作者简介

李华植
代表韩国的数据库技术先驱
集基于EA(Enterprise Architecture)的数据架构(Data Architecture)
方法论之大成
在韩国最早提出了数据专家顾问的概念
现任EN-CORE CONSULTING总经理及代表顾问
曾在韩国Oracle公司担任200多家企业的技术顾问
论文:《构建海量数据系统时的RDB Performance问题解决方案》
书籍:《Data Modeling&Database Design》(1995)
《Oracle Server Tuning}(1995)
《海量数据库解决方案》(1996)
《海量数据库解决方案Ⅱ》(1998)
《数据架构解决方案I》(2003)

译者简介:
郑保卫,于韩国国立釜庆大学信息工学系获得工学博士,现任职于韩国最权威的数据库公司EN-CORE CONSULTING,并兼任企业研究所研究员及数据库电子商务研究所主要研究员。研究方向包括数据模型设计、海量数据库解决方案、数据架构、基于数据库技术的专家智能系统、ITA/EA(Infomation Technology Architecture/Enterprise Architecture)。

盖国强(网名Eygle),Oracle ACE总监,恩墨科技创始人,ITPUB论坛超级版主,远程DBA服务的倡导者和实践者,致力于以技术服务客户。著有《深入解析Orade》、《循序渐进Oracle》、《深入浅出Oracle》等书:从2010年开始,致力于《OracleDBA手记》的撰写与编辑工作,并与张乐奕共同创立了ACOUG用户组,在国内推进公益自由的Oracle技术交流活动。

张乐奕(网名Kamus),恩墨科技技术总监,Oracle ACE,ITPUB数据库管理版版主。他曾先后于北京某大型软件公司、外资电信企业、咨询公司任首席DBA。后任职于北京甲骨文软件系统有限公司,高级顾问。他热切关注Oracle数据库及其他相关技术,对于Oracle数据库RAC及高可用解决方案具有丰富的实践经验,长于数据库故障诊断、数据库性能调优。他还是各类技术会议的热心分享者,2010年3月创建ACOUG用户组。

崔华(网名Dbsnake),2004年开始从事DBA工作,在Oracle的安装、升级、开发、性能调整、故障处理方面有丰富的经验,对Oracle的体系结构具有深入了解:深入理解Oracle的内存结构、物理存储(各种块格式)、锁机制、优化机制等:深入了解Oracle的备份恢复机制,熟悉Oracle的各种备份方法,能够处理各种情况下的复杂数据恢复情况。崔华也是热心的技术分享者,多次在ACOUG的活动上与技术爱好者分享技术心得。

内容简介
本书是一本全面反映过去10年迅速发展的商用DBMS最新数据库应用技术、强化数据库技术灵活运用原理及系统化具体应用准则的高水平的经典书籍。
本书曾在韩国和日本同时出版发行。在日本最权威的数据库专业出版社(株)翔泳社出版局出版发行本书的同时,也将韩国先进的数据库技术传播到了日本。此次在发行中文版的同时,也希望本书中所涵盖的技术能够对中国的广大读者有所帮助。本书中所涉及的普遍性原理适合于任何DBMS,只要对语法稍加调整便可在所有DBMS中得到有效使用。为了便于读者对关系数据库的概念、优化器的灵活运用原理、适用于多样化实际业务中的明确应用准则有一个充分的理解,在本书中通过举例对这些内容进行了详细说明。
本书将整体内容分为两部分,在第1部分中以影响数据读取效率的所有要素为类别,对其各自的概念、原理、特征、应用准则,以及表的结构特征、多样化的索引类型、优化器的内部作用、优化器为各种结果制定的执行计划予以详细说明,并以对优化器的正确理解为基础,提出对执行计划和执行速度产生最大影响的索引构建战略方案;在第2部分中主要介绍提高数据读取效率的具体战略方案,在这部分中介绍与数据读取效率相关的局部范围扫描的原理和具体应用方法,以及对被认为是提高数据库使用效率基础的表连接的所有类型予以详细说明。
《海量数据库解决方案》系列丛书深受广大读者的喜爱已经长达10年之久,在被誉为“圣经”的同时,它已经变成了数据库用户不可或缺的必读书籍。作者竭力探求能够让IT工作者在实际工作中轻松应用并掌控的巧妙方法,提供事半功倍的海量数据库解决之道。

P4,总体而言,数据的存储方式可以被分为固定存储方式和随机存储方式。固定存储方式是指数据被存储在预先指定的磁盘位置上;而随机存储方式则按照输入的顺序,数据被存储在磁盘的任意位置上。

P5,所谓的表和索引分离型的存储结构就是堆表,即用来存储数据的表和为了快速查找特定数据而使用的索引完全作为不同的对象来存储。

P7,ORACLE堆表存储:表空间,可以由一个或者多个物理文件构成,同时分成了很多个“数据库BLOCK”,每个BLOCK又由一个或者多个SLOT组成。所以ROWID是由“对象号+数据文件号+数据库号+SLOT号”等部分组成。
如果预先设置的空余空间过小,ORACLE就会频繁要求执行空间再分配操作。所以设置充足的空余空间(PCTFREE)可以被认为是提高数据处理效率的重要技术手段之一。

P8,当某个变长的行无法存储在当前的数据块时,就需要使用其他数据块来弥补剩余空间的不足,ORACLE为了保证原来的ROWID不变,就把行的新地址存储在行移动之前的旧地址中,这种方式叫做“行迁移”。当某个行所需的存储空间大小超过一个数据块空间大小时,就必须利用多个连接在一起的数据块来存储同一行的数据,这种方式叫做“行链接”。

P11,聚族因子是指按照索引列值进行了排序的索引行序和对应表中数据行序的相似程度。在索引中是按照索引列和ROWID进行排序的。

P15,小型表,创建主键即可,如果是在关键访问路径上,则可以考虑索引组织表或者聚族表。中型表,主要通过创建索引来提高读取效率。大型表,日志表(没有太多的读取类型,可以考虑分区);顾客表(随机读为主,堆表比较合适);销售表(写也多,随机读取类型也多,创建索引为主),为了提高聚族因子,可以定期对表执行重构操作。

P19,B-Tree索引是最一般也是最常用的索引,它由“索引列+ROWID”构成。第一次逻辑读取是指索引段的读取,第二次逻辑读取是指利用索引ROWID来进行行数据段的读取。所谓索引组织表是指把索引和一般数据列全部存储在相同位置上的表结构。
如果大部分的查询语句都是要求对主键进行扫描,且主键的长度在整个行的长度中所占的比例比较大,则索引组织表是最佳选择。

堆表与索引组织表的比较
  

P23,适用索引组织表的情况:
电子分类或者关键字查询表
代码信息表
索引表
空间信息管理表
大部分使用主键查询的表
OLAP的维度表
记录的长度较短,且插入操作不频繁的表

P25,索引组织表的所有列(溢出区中的列除外)被存储在索引段中,溢出区中的列被存储在表段中。这种存储方式和堆表有点相像,索引被存储在索引段中,而表被存储在表段中。
CREATE TABLE documents(
  doc_id varchar(5),
  contents varchar(20),
  status varchar(2),
  CONSTRAINT pk_docid PRIMARY KEY(doc_id))
ORGANIZATION INDEX
TABLESPACE data01
PCTTHRESHOLD 20
INCLUDING contents
OVERFLOW TABLESPACE idx01;

P27,就像表是索引的上级概念,聚族则是表的上级概念。虽然各自都是相互独立的对象,但在概念上却有一定的从属关系。利用聚族索引来查找数据的聚族类型称为索引聚族,而利用哈希函数来查找数据的聚族类型称为哈希聚族。聚族表与一般表相比唯一不同之处就在于它按照特定的列(聚族列/键)把数据聚族在一起,从而在一定程度上提高了聚族因子。

P28,所谓的聚族就是指以某个指定的列为基准,把拥有相同聚族键值的所有行都存储在相同位置上的物理存储方法。把多个表中拥有相同聚族键值的行集中存储在连续位置上的做法意味着把需要执行表连接的行提前集中存储在一起,从而能够降低表连接时的数据运输单价。同理,把同一个表中拥有相同聚族键值的行集中存储在连续位置上的做法能够降低读取海量数据时的运输单价。
聚族具有基于聚族列所创建的聚族索引,与一般索引唯一不同的是一般索引中的每一个索引行与表中的每个数据行一一对应;而聚族索引的每一个索引行与聚族列中的每一个值一一对应。

P31,按照离散程度比较差的列来创建单表聚族反倒有利于提高数据的读取效率。

P44,关系型数据库中常用的索引包括B-Tree索引、位图索引、B-Tree聚族索引、哈希聚族索引、反向键索引、位图连接索引、函数索引。

P53,位图索引是指使用计算机中的最小单位BIT来存储列值,并使用它来自动生成ROWID的一种索引结构。直接将列值转换为位来存储不仅节约了存储空间,而且通过各种位运算还可以解决现有索引所不能解决的很多问题。
只有基于离散度较低且相同值反复出现的列创建位图索引时,才能在很大程度上节约空间。同时使用位图索引时使用=比较符才能达到目的。

P61,基于自定义的函数索引是基于函数或者公式的运算结果而创建的一种B-Tree索引或者位图索引。

P64,基于自定义函数索引的灵活应用
1、解决表设计上存在的问题
•列值中间部分的查询 CREATE INDEX a ON t (SUBSTR(ship_id,5,3));
•连接条件列不相互对应问题 CREATE INDEX a ON t (f1||f2||f3);
•日期分割问题 CREATE INDEX a ON t (y||m||d);
•连接列数据类型不同的问题 CREATE INDEX a ON t (TO_NUMBER(ship_id));
•连接列随着具体情况不同而不同的表连接问题 CREATE INDEX a ON t (CASE WHEN x=1 THEN y ELSE z END);
•结合父表的列创建组合索引的问题 CREATE INDEX a ON t (sdfunc (ship_id));
2、错误数据查询的问题
•大小写和空格相互混合存在于列值中的问题CREATE INDEX a ON t (UPPER(x));
•替换NULL值的查询问题CREATE INDEX a ON t (NVL(x,’2001-01-29’));
•填充前缀查询问题 DECODE(SUBSTR(x,1,3), ’130’ , ’135’ , ’138’)||x
3、加工处理结果查询问题
•复杂运算结果的查询 price-nvl(discount,0)*count
•末日、价格、率的查询 LAST_DAY(date)
•期间、列长查询 expire_date-start_date
4、对象类型的索引查询问题
•比如,六面体的体积
5、排他关系的索引查询问题
•排他关系的唯一性保障
•排他关系的组合索引

P75,为所有SQL制定最优化执行计划的最佳方法就是战略性地构建优化因子,为了具备此能力,首先应当培养以下三种能力:判断优化因子的能力、编写有效SQL语句的能力、控制执行计划的能力,判断力、编写力、统治力。对选择最优查询路径影响最大的只有列的离散程度和聚族因子。

P80,优化器可以分为2类:基于规则的优化器RBO和基于成本的优化器CBO,两者的最大区别就是为了选择最优查询以何种方法来判断依据进行评价。

P95,选择优化器模式的标准,在OLTP中设置为FIRST_ROWS 或者FIRST_ROWS_N;在OLAP中,则设置为ALL_ROWS。参数设置:
1、CURSOR_SHARING:FORCE, SIMILAR, EXACT(default)
2、DB_FILE_MULTIBLOCK_READ_COUNT,一次I/O读取的数据块个数
3、OPTIMIZER_INDEX_CACHING:通过索引反复从表中随机读取数据时索引快被缓存的概率
4、OPTIMIZER_INDEX_COST_ADJ:索引读取比重,默认为100,表示正常,如果为10,表示以1/10来计算索引读取的成本

P107,优化器由查询转换器(Query Transformer)、成本估算器(Estimator)、执行计划生成器(Plan Generator)构成。
1、查询转换器
•视图合并,将定义视图时所使用的查询语句(视图查询语句)放入到实际执行读取数据的查询语句(读取查询语句)中。
•谓词推进,将读取查询语句的查询条件附加到视图查询语句中去,以实现查询语句转换的目的。
•子查询非嵌套化,解除构成子查询的查询语句与主查询语句的嵌套关系或者通过表连接的方式替代子查询,以获得良好的执行效率。
•物化视图查询重构,物化视图是存储着物理性数据的视图,通过重构用户要求执行的查询语句来确保优化器优先处理物化视图,以实现大幅度改善执行效率的目的。
•OR条件展开,在OR查询条件既是驱动查询条件又在其上有索引的情况下,将该查询语句分割为多个单位查询语句,且通过UNION ALL来实现对各个单位查询语句的结合。
•绑定变量窥探(Peeking),当用户在查询条件中指定了绑定变量时,将第一次获取的值作为常量进行判断后面的执行计划。
2、成本估算器
•选择度(Selectivity),是指满足条件的行在查询的结果集中所占的比例。在列的直方图信息不存在时使用平均值计算,否则使用离散度来计算选择度。
•基数(Cardinality),就是选择度与整体行数的乘积。
•成本(Cost),表示执行时间的预测值。

P112,在执行含有绑定变量的查询语句时,完成解释和最优化操作后才对绑定变量进行绑定,这就意味着在实现最优化操作时无法使用绑定变量列的统计信息。
_OPTIM_PEEK_USER_BINGS
TRUE,使用最初变量值
FLASE,使用平均离散度方法

P126,执行计划的类型
1、扫描的执行类型
•全表扫描(FULL),损益分界点,表示使用索引扫描从表中读取某比例的数据,与直接全表扫描来读取数据相当时,这个比例值就是损益分界点。
•ROWID扫描(BY INDEX ROWID)
•索引扫描(索引唯一扫描INDEX UNIQUE、索引范围扫描INDEX RANGE、索引降序范围扫描INDEX RANGE SCAN DESCENDING、索引跳跃式扫描INDEX SKIP SCAN、索引全扫描FULL SCAN、索引快速全扫描FULL FAST INDEX SCAN)在查询语句中所涉及的所有列都存在于索引中的话,索引快速全扫描有可能被选择执行,同样也应该满足索引列中至少存在一个NOTNULL列。索引快速全扫描每次I/O读取的是多个数据块,这也是该方式与索引全扫描之间的主要区别。
•B-TREE聚族读取(CLUSTER ACCESS)
•哈希聚族读取(HASH CLUSTER ACCESS)
•采样表扫描(SAMPLE TABLE SCAN)SAMPLE BLOCK表示读取指定比例的数据块;而SAMPLE表示从每个数据块中读取指定比例的行SLOT,Sample Percent取值范围0.000001-99.999999,只有CBO才支持此功能。应用于数据挖掘(Data Mining)、数据清洗查找错误、创建数据样本测试系统。
2、表连接的执行计划
•嵌套循环连接(NESTED LOOPS JOIN)
•排序合并连接(SORT MERGE JOIN)
•哈希连接(HASH JOIN)
•半连接(SEMI JOIN)子查询与主查询之间的表连接
•笛卡尔连接(CARTESIAN JOIN)无条件连接,两集合的乘积
•外连接(OUTER JOIN)返回基准表所有行的一种连接方式(嵌套循环、哈希、排序合并)
•全外连接(FULL OUTER JOIN),以两个表为基准表的外连接方式,返回最小公倍数集合,即返回两个表共有的行和只存在于某一个表中行的集合。
•索引连接,是指在某个查询语句中所使用到的某个列存在一个以上的索引时,按照哈希连接的方式将这些索引连接起来的方法,也就是说不是通过读取索引在读取表的方式,而是只通过索引连接来实现数据查询的方法。
3、其他运算方式的执行计划
•IN-LIST迭代执行计划,IN 查询
•连锁执行计划(CONCATENATION)OR查询
•远程执行计划
•排序操作执行计划(SORT(UNIQUE)把输出结果变成唯一集合的过程:DISTINCT、子查询以提供者角色;SORT(AGGREGATE)在没有GROUP BY前提下使用SUM,COUNT,MIN,MAX,AVG等统计函数时对全部对象进行运算;SORT(GROUP BY)在使用了GROUP BY时将数据行向不同分组中聚集的过程;SORT(JOIN)排序合并连接;SONR(ORDER BY) 使用了ORDER BY时将数据行排序)
•集合操作执行计划(并集(UNION UNION ALL)由于UNION求的是两个集合的最小公倍数集合,所以合并之后还需要再次执行排序操作SORT(UNIQUE);但如果使用了UNION ALL,就不再需要排序操作了,但是当两个集合中有共同的行存在时必须使用UNION;差集(MINUS)是指从一个基准集合中除去属于另一个集合中的元素后所得的集合,不允许重复元素;交集(INTERSECTION)是指同时存在于两个集合中的共同元素的集合,即两边集合的最大公约数,不允许重复元素。)
•COUNT(STOPKEY)执行计划,在查询语句中的查询条件中使用了ROWNUM时所显示出来的执行计划。

附加:having与where的区别
1.用的地方不一样
 where可以用于select、update、delete和insert...into语句中。
 having只能用于select语句中
 2.执行的顺序不一样
 where的搜索条件是在执行语句进行分组之前应用
 having的搜索条件是在分组条件后执行的
 即如果where和having一起用时,where会先执行,having后执行
 3.子句有区别
 where子句中的条件表达式having都可以跟,而having子句中的有些表达式where不可以跟;having子句可以用集合函数(sum、count、avg、max和min),而where子句不可以。

P206,使用提示实现最优化目标
ALL_ROWS,为实现查询语句整体结果最优化。select /*+ ALL_ROWS */ …
CHOOSE,根据统计信息是否存在决定使用RBO还是CBO,在CHOOSE模式下,如果可以参考统计信息,则按照ALL_ROWS方式执行
FIRST_ROWS,为获得最佳响应时间而引导 select /*+ FIRST_ROWS(10) */ …
RULE,使用基于规则的优化器

P207,使用提示改变表连接顺序
ORDERED,按照FROM中所描述的表的顺序执行连接,如果和LEADING一起使用,则LEADING被忽略
LEADING,使用LEANDING指定的表作为连接顺序中的第一个表select /*+ LEADING(b,c) */ … FROM A a, B b, C c WHERE …

P208,表连接方式选择的提示
USE_NL,使用嵌套循环连接
NO_USE_NL,不要使用嵌套循环连接
USE_NL_WITH_INDEX,为外侧循环指定需要使用的索引
USE_HASH、NO_USE_HASH、USE_MERGE、NO_USE_MERGE

P211,数据读取方法选择的提示
FULL、HASH、CLUSTER、INDEX、NO_INDEX、INDEX_ASC、INDEX_DESC、INDEX_COMBINE、INDEX_FFS、INDEX_JOIN、INDEX_SS、INDEX_SS_ASC、INDEX_SS_DESC

P214,查询转换过程的提示
USE_CONCAT,将含有多个OR或者IN的运算符所连接起来的查询语句分解为多个单一查询语句,并为每个单一查询语句选择最优化查询路径,然后再将这些最优化查询路径结合在一起,以实现整体查询语句的最优化目的。只有在驱动查询条件中包含OR的时候,才可以使用该提示,否则影响执行速度。
USE_EXPAND,不要为使用OR或者IN的运算符的条件制定相互结合的执行计划,与USE-CONCAT相反。
REWRITE,当表连接的对象是数据量较大的表或者需要获得使用统计函数处理过的结果时,为了提高执行速度可以预先创建物化视图。当用户要求执行某个查询语句时,优化器会在表中或者物化视图中读取数据的两种方法中选择一个更有效的方法来读取数据,这叫做查询重写。
NOREWRITE、MERGE、NO_MERGE、STAR_TRANSFORMATION、FACT、UNNEST

P223,不同类型表的索引应用准则
1、拥有数据量较少的小型表:主键创建的索引,或者使用索引组织表
2、参考作用的大中型表:创建合适的索引
3、管理具体业务行为的大中型表:战略性索引,或者考虑位图索引
4、存储用的大型表:索引、聚族等。

P227、离散度在不超过全表的10%-15%的前提下索引才可以显示其所具有的价值,换言之,索引列的离散度为10%-15%的深层次含义为,当离散度超过该值的情况下全表扫描可能反倒比索引扫描更有效。所以,我们最求的目标是创建全表扫描所无法比拟的有效索引。

P229,通过为索引分配任务可以在很大程度上提高索引的灵活度,其一,对具有较好离散度的列单独创建索引,可以提高索引的使用弹性;其二,对离散度较差的列通过对多列进行合理的组合来创建组合索引。虽然降低了各列的使用弹性,但可以返回多列的综合效应。

P229,索引合并
SELECT * FROM TABLE1 WHERE COL1=’ABD’ AND COL2=123
假设创建了2个缩影COL1 和 COL2.
1、按照随机的方式从COL1的索引中查找到第一行ABC和从COL2的索引中查找到第一行123
2、从2个中ROWID较小的一侧按次序向下扫描,同时与COL1中的ROWID(值15)进行比较,直到比15大的ROWID(值32)出现
3、以右侧的32为基准,按照次序对左边的COL1索引进行向下扫描,如果找到相同的ROWID则从表中读取改行,然后继续扫描直到比32大的ROWID(值67)出现为止
4、然后再次对右侧的索引COL2进行扫描,如果出现比67大的值则停止右侧扫描而开始左侧扫描。
5、左侧扫描之后发现列值并非ABC则终止索引合并操作。
结论:只有当合并的索引具有相似的离散度时索引合并才比较有效。因此,优化器不会为行数悬殊的索引选择索引合并的执行计划,在这种情况下,通常只使用其中较好的一个索引来负责数据读取,而另外的索引只负责检验。或者为离散度较差的列创建组合索引,比索引合并有更好的读取速度,只是降低了列的使用弹性,同时,组合索引只有在查询条件中对索引列使用了=等值比较符时组合索引才能够有突出的表现。

P232,当组合索引的第一个索引列(通常为先导列)没有出现在查询条件中时,一般情况下该组合索引无法被使用。
组合索引最大的缺点就是当只为一部分索引列赋予了查询条件时,或者所使用的比较运算符大部分都是非=比较符时效率非常低下。
第一, 基于什么样的列创建组合索引;第二,按照什么样的顺序创建索引。

P232,离散度与列序的关系
1、如果只是在=比较符的情况下,离散度的好坏对列序没有什么大的影响。
2、对影响速度影响最大的正是使用非=等值比较符的查询条件。
3、在没有为组合索引的第一列赋予使用=比较查询条件时,即使为后面的列赋予了=比较查询条件也不会缩减数据的查询范围。
4、在决定组合索引时,=比较查询条件比离散度更重要,因此需要结合列的离散度和查询条件决定最佳组合顺序。
5、对查询范围不构成直接影响的列,首先考虑对直接缩减范围起重要作用的列,对附加性列是否会有利于提高执行效率等相关问题进行全面分析。

P239,组合索引中列序的决定准则
1、是否经常被使用
2、是否经常使用=比较查询条件
3、是否有较好的离散度
4、按照何种顺序进行排序
5、是否可以作为附加性列添加进来

P244,索引选定步骤
1、全面搜集表的读取类型
2、选定索引列对象并调查其离散度
3、为特殊读取类型选定索引
4、检查聚族
5、组合索引的构成及索引列序的决定
6、实验和测试
7、调查和修改相关应用程序
8、统一应用

P245,开发阶段读取类型的搜集
1、寻找反复执行的读取类型
2、选拔出离散度比较好的列,对齐读取类型进行调查
3、寻找经常被赋予较大范围的查询条件
4、抽出查询条件中的主要列,并对其读取类型进行调查
5、对经常需要组合使用的列的组合类型和排序顺序进行调查
6、寻找需要降序输出的情况
7、为了获得统计信息而对读取类型进行调查

P249,运行阶段读取类型的搜集
1、从应用程序代码中抽出SQL之后,将其存储在专门用来分析的表中
2、解析SQL-TRACE文件,获得SQL语句、执行计划、使用的索引、执行次数等信息
3、从共享池中直接寻找SQL

P257,在经常需要读取大范围数据且不创建汇总表就别无他法的情况下,可以通过使用聚族来提高执行速度。这里主要指单表聚族,聚族和索引对列离散度的要求有所不同,在列的离散度较差时,聚族的效率就能够得到充分的发挥;相反如果为离散度较好的列进行了聚族,则聚族的效率就无法得到充分的发挥。这时,只要为其构建比较有效的索引就可以实现快速查询数据的目的。

P276,所谓的局部范围扫描,并不是指扫描满足WHERE条件的全部数据行,而是指只要扫描了数组批量(ArraySize,运输单位)的行数后立刻返回结果,在用户再次提出输出要求之前暂时停止执行的处理方式。

P281,在全部范围扫描的执行计划中虽然有很多项目,但是如果出现了“SORT”,则可以断定是使用了全部范围扫描的方式对执行单元进行了处理。

P282,局部范围扫描的条件,从逻辑的角度看,除了读取整体数据范围之后必须要对其进行再次加工之外,所有其他查询都符合局部范围扫描的条件。通常在SQL中使用了ORDER BY将无法实现局部范围扫描,但如果哟欧化器选择的驱动索引列与ORDER BY 排序列相同,则可以按照局部范围扫描的方式进行处理。这里相同是指ORDER BY 中所使用的列的个数与顺序与索引中的列的个数和顺序完全相同。

P283,集合{1,2,2,3}和集合{2,4,6},使用UNION时得到{1,2,3,4,6};如果使用UNION ALL时得到{1,2,2,2,3,4,6}。由此可见,UNION不仅要求自身集合中的自身元素具有唯一性而且还要求集合运算后的新集合的元素具有唯一性。

P285,在RBO和CBO的FIRST_ROWS模式下,基本上是按照局部范围扫描的;而CBO的ALL_ROWS下,则按照全部范围扫描的。

P289,局部范围扫描执行速度:

P290,向局部范围扫描引导的方法
1、利用访问路径实现对SORT的代替,通过某些措施变换查询条件的角色,从而实现局部范围扫描。
2、只使用索引的局部范围扫描,满足下面三个条件中的至少一个:a,SQL中所涉及的列全部在一个组合索引中;b,能够实现索引合并操作;c,SQL中所涉及的列全部包括在几个索引中,由于满足索引连接的条件,所以可以指定索引连接的执行计划。
3、MIN/MAX处理,降序,ROWNUM=1等方式
4、FILTER型局部范围扫描,EXISTS方式
5、ROWNUM的灵活应用,ROWNUM《=10等方式
6、利用嵌套视图的局部范围扫描,将必须使用全部范围扫描的部分捆绑在嵌套视图中,以确保视图之外的部分能够以局部范围扫描的方式执行。就是分离出“嵌套视图”来。
7、利用函数的局部范围扫描
8、利用查询语句二元化特性的局部范围扫描

P341,从某种程度来说,反复连接方式(LOOP QUERY)也有其不可否认的优点,表现在无须像使用JOIN那样需要考虑集合的顺序。从DECLARE CURSOR中取出结果的同时在FOR LOOP中进行连接的反复连接方式非常类似于NESTED LOOPS的表连接方式。

P366,依据表连接方式的特征,分为两类:一是某个集合被优先读取,使得相应的列获得常量并利用它去需要另外一个集合;二是为了实现有效连接而提前执行一些准备操作后再进行连接。

P368,嵌套循环连接
SELECT * FROM TAB1 a, TAB2 b
WHERE a.KEY1=b.KEY2
AND a.FLD1=’ 111’
AND a.FLD2 like ’ AB%’
AND b.COL1=’ 01’
1、在列FLD1的索引中,从满足查询条件FLD1=’ 111’的查询范围中读取第一个索引行;
2、利用FLD1中的ROWID从表TAB1中读取对应的数据行。此时,所读取的数据行中的所有列都将获得常量值,并利用查询条件FLD2 like ’ AB%’对所读取的结果进行检验。如果满足该条件,则继续执行下一阶段的操作;否则返回“1”阶段重新开始处理下一个索引行;
3、利用表TAB1的列KEY1的常量值去表TAB2的列KEY2的索引中寻找对应的索引行。如果在KEY2的索引行没能找到对应的行,则连接失败,返回到“1”阶段重新开始处理下一个索引行;
4、如果查找到对应的索引行,则利用KEY2中的ROWID从表TAB2中读取对应的数据行。此时,如果构建了由KEY2+COL1所构成的索引,则在该阶段中直接检验所读取的数据行是否满足COL1=’ 01’;否则就必须等到下一个阶段再利用这一查询条件对所读取的数据行进行检验。此时,从表TAB2中所读取的数据行的所有列都将获得常量值;
5、利用查询条件COL1=’ 01’对所读取的数据行进行检验,并将满足条件的数据行发送到运输单位;
6、一个循环结束之后再次返回到FLD1索引中读取第二个索引行,并重新执行以上操作。如果是按照局部范围扫描的方式执行,则运输单位被填满后就直接输出结果。如果是按照全部范围扫描方式执行,则直到FLD1的查询范围结束为止将连续(NESTED)不断地反复(LOOPS)执行。

P368,排序合并连接
SELECT * FROM TAB1 a, TAB2 b
WHERE a.KEY1=b.KEY2
AND a.FLD1=’ 111’
AND a.FLD2 like ’ AB%’
AND b.COL1=’ 01’
1、按照次序从索引FLD1中读取满足查询条件FLD1=’ 111’范围中数据行后,以表TAB1中的查询条件FLD2 like ’ AB%’作为过滤查询条件对所读取的结果进行检验,并按照连接列KEY1的值对检验成功的数据进行排序;
2、按照次序从索引COL1中读取满足查询条件COL1=’ 01’范围中数据行后,按照连接列KEY2的值对读取的数据进行排序。
3、在扫描已经进行了排序的两个集合的同时,从中寻找满足KEY1=KEY2的数据行并对其进行合并,然后将合并后的数据行发送给运输单位,直到运输单位被填满为止。合并的执行步骤:对两边的值进行比较之后,从较小的一边开始向下扫描,在向下扫描的同时不断与对应集合的值进行比较,当在对应集合中找到比当前值小的值时中止当前集合的扫描,而转向对应集合的扫描;同样在扫描过程中不断与对应集合的值进行比较,当遇到比当前扫描到的值小时中止扫描并再次返回。

P393,IN-MEMORY哈希连接,是指将BUILD INPUT全部存储在内存中并为其创建哈希表,在扫描PROBE INPUT的同时实现连接。
1、依据统计信息,从两个集合中选择一个基数比较好的作为BUILD INPUT来使用,一般情况下将“1”边的集合选择为BUILD INPUT;
2、决定FAN-OUT,即决定分区的个数。
3、对BUILD INPUT的连接键进行第一次Hashing函数运算,以便决定出将要存储的分区;
4、进行第二次Hashing函数运算以获得哈希值(Hash Value);
5、利用哈希值创建哈希表,并将对应的列存储在分区的SLOT中。在这里也将SQL的SELECT-LIST中所涉及的列一起存储在SLOT中。
6、为了对PROBE INPUT进行过滤而创建位图矢量。由于位图矢量是按照唯一的值创建的,所以在BUILD INPUT中会先试图寻找该唯一值。如果不存在则直接创建,否则跳过;
7、按照这种方式对BUILD INPUT中的所有数据对象进行连续处理,直到结束为止;
8、现在开始从PROBE INPUT的查询范围中读取数据。所读取的数据行如果满足查询条件,则继续执行下一步操作;否则直接将其丢弃;
9、对所读取的第一行数据进行Hashing函数运算,并利用位图矢量对运算结果进行过滤。如果没有通过过滤(在BUILD INPUT中没能找到对应的数据行),则终止执行,返回并重新读取下一个PROBE INPUT对象;
10、对通过过滤的数据行进行第二次Hashing函数运算,并利用从哈希表中读取的相关信息寻找到相关的分区后,从SLOT中查找对应的行;
11、执行连接,完成SELECT-LIST中所扫描的行,并将其发送给运输单位;
12、反复执行这样的操作,并将完成的行连续不断地发送给运输单位;
13、指定的运输单位被填满后直接返回结果。
14、按照这种方式对PROBE INPUT中的所有数据进行连续处理,直至结束为止。

P396,延迟哈希连接,当BUILD INPUT所需要的空间大小超过了Hash Area的大小时,哈希连接就变得比较复杂了,则必须无条件地将超出的部分数据存储在磁盘上。
1、依据统计信息,从两个集合中选择一个基数比较好的作为BUILD INPUT来使用,一般情况下将“1”边的集合选择为BUILD INPUT;
2、决定FAN-OUT,即决定分区的个数。
3、对BUILD INPUT的连接键进行第一次Hashing函数运算,以便决定出将要存储的分区;
4、进行第二次Hashing函数运算以获得哈希值(Hash Value);
5、利用哈希值创建哈希表,并将对应的列存储在分区的SLOT中。在这里也将SQL的SELECT-LIST中所涉及的列一起存储在SLOT中。
6、为了对PROBE INPUT进行过滤而创建位图矢量。由于利用这里所生成的值可以实现对在下个阶段中将要执行的PROBE INPUT的过滤作用,所以在延迟哈希连接中也是把数据量比较少的集合作为BUILD INPUT来使用。
7、按照这种方式对BUILD INPUT中的所有数据对象进行处理的同时,如果超过了Hash Area的大小,则将分区的地址信息存储在分区表中病将超出部分的数据移动存储到磁盘上的对应分区中。在后来寻找到分区对吼利用该地址信息,再次从磁盘上把对应的数据加载到内存中以实现连接操作。
8、按照这种方式对BUILD INPUT中的所有数据对象进行连续处理,直到结束为止;
8、现在开始从PROBE INPUT的查询范围中读取数据。所读取的数据行如果满足查询条件,则对其进行第一次Hashing函数运算,并利用位图矢量对运算结果进行过滤。如果没有通过过滤(在BUILD INPUT中没能找到对应的数据行),则终止执行,返回并重新读取下一个PROBE INPUT对象;
10、对通过过滤的数据行进行第二次Hashing函数运算。此时,如果与PROBE INPUT所对应的BUILD INPUT存在于内存中,则读取哈希表并执行连接;否则将读取的PROBE INPUT对象存储在起所属的分区中;
11、将无法实现连接的分区存储在磁盘中;
12、按照这种方式对PROBE INPUT中的所有数据进行连续处理,直至结束为止。
13、利用分区表中的地址信息从磁盘上把没有被连接的分区对载入到内存中;
14、从重新载入到内存中的各个分区中选择一个最小的集合并为其创建哈希表。;
15、在对重新决定的PROBE INPUT扫描的同时,利用哈希表执行连接。运输单位被填满后直接返回结果。按照这种方式对剩下的素有对象进行处理,直至结束为止。

P401,表连接与子查询之间虽然具有很多非常相似的特征,但是它们最本质的区别就在于集合间的从属性上。
1、对于表连接而言,两个集合是平等关系;而子查询,则两个集合之间是从属关系。
2、从结果集合来看,表连接是集合的乘积:1*1=1,1*M=M,M*1=M,M*M=MM;而表连接的结果集合始终都是与主查询的集合类型相同。
3、继承性,对于表连接而言,可以随意使用处于连接状态下的两个集合中的任意列;但对于半连接而言,子查询可以随意使用主查询中所涉及的任意列,而主查询就无法使用自查询中所涉及的列。

循环嵌套型半连接:提供者角色,子查询优先执行;检验者角色,主查询优先执行,在子查询中添加一个与主查询列作为比较列。
排序合并型半连接:需要对子查询的唯一值做保证
过滤型半连接:EXISTS
哈希型半连接:
ANTI半连接:是指在连接条件镇南关使用了NOT的连接类型。

P418,星型(STAR)连接,当一个事实表与多个编码表进行连接时,由于每个编码表与事实表都需要一次连接,当事实表很大时,这种连接方式会比较费时。一种改变的方式,就是先对所有的编码表之间进行笛卡尔连接(因为各编码表之间不存在连接条件),然后,此VIEW再与事实表进行连接。当然,这种连接方式有一个最大的限制就是各编码表都比较小,否则它们的乘积也是相当惊人的。
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多