表的连接和其他高级调整技术.ppt
《表的连接和其他高级调整技术.ppt》由会员分享,可在线阅读,更多相关《表的连接和其他高级调整技术.ppt(60页珍藏版)》请在三一办公上搜索。
1、1、Oracle的连接非常复杂2、驱动表或者查询中第一张访问的表是获得更佳性能的关键3、如果优化器指定了错误的表作为查询中的驱动表,那么造成的差异将会天壤之别4、通常,基于成本的优化器会选择正确的表,但是表中的索引将影响它的正常工作。5、我们可以使用提示来改变表的连接顺序,但是如果需要调整多张表,那么会非常的麻烦6、如果我们需要使用提示来改变表的连接顺序,那么说明我们的索引出现了问题,连接方法嵌套连接(Nested loops join)排序合并连接(Sort-Merge join)集群连接(Cluster join)笛卡尔连接(Cartesian join)散列连接(Hash join)索引
2、连接(Index join),嵌套循环连接在嵌套循环连接中,Oracle从第一个行源中读取第一行,然后和第二个行源中数据进行对比。所有匹配的记录放在结果集中,然后oracle将读取第一个行源中的下一行。按这种方式直至第一个数据源中的所有行都经过处理。第一个行源通常称为外部表(驱动表),相应的第二个行源称为内部表。注意:使用嵌套循环连接是一种从连接结果中提取第一批记录的最快速的方法。驱动表较小、内部表连接列有唯一索引或高度可选的非唯一索引,这种场合比较适合嵌套连接。优势:快速从结果集中提取第一批记录,而不需要等待整个结果集完全确定下来。理想情况是:用户已经看到第一批记录,但是oracle还在后台
3、提取剩余记录。,1、如果内部表的连接列上没有索引,或者索引不是高度可选,嵌套循环的效率是非常低下的。2、驱动表非常庞大,那么不建议使用嵌套循环。,select/*+ordered*/ename,dept.deptnofrom dept,empwhere dept.deptno=emp.deptno/,没有走嵌套,因为两个列上都有索引。,select/*+ordered*/ename,dept.deptnofrom emp,deptwhere dept.deptno=emp.deptno/外部表是emp、内部表是dept。我们删除了外部表上的索引。,删除主键以后,主键索引也删除。,select/
4、*+ordered*/ename,dept.deptnofrom dept,empwhere dept.deptno=emp.deptno/,外表是dept(驱动表)。,第一个循环返回三行记录,第二个循环返回5行记录第三个循环返回6行记录第四个循环没有返回记录一共返回14行记录这就是嵌套循环。,驱动表,排序合并连接在排序合并连接中,oracle分别将第一个源表、第二个源表按他们各自要连接的列排序,然后将两个已经排序的源表合并。如果找到匹配的数据,就放到结果集中。在缺乏数据的选择性或者可用索引时,或者两个源表都过于庞大(超过记录数的5%)时,排序合并连接将比嵌套循环连接更加高效。排序合并连接只能
5、用于等价连接(where dept.deptno=emp.deptno),而不是where dept.deptnoemp.deptno。排序连接并不是一个很好的连接方式。,select/*+ordered*/ename,dept.deptnofrom dept,empwhere dept.deptno=emp.deptno,对两个表的连接列分别进行排序,合并,排序合并连接需要临时内存块,用于排序。我们要尽量避免磁盘排序,保证始终使用内存排序,否则性能会很低。保证内存排序的方法是:设置足够的PGA_AGGREGATE_TARGET参数或者SGA_TARGET参数,设置哪个参数取决于是专用服务器还
6、是共享服务器。,集群连接,这是一个集群表的存储方式。,集群连接实际上是嵌套连接的一种特例。如果所连接的两张行源表实际上是集群中的表。例如左面的emp和dept。并且连接是两张行源表的集群键(deptno)的等价连接,那么在oracle中就能使用集群连接。Oracle从第一张行源表中读取第一行,并在第二张行源表中使用cluster索引查找所有匹配的项。集群索引效率极高,因为两个行源表实际上存储在同一个物理块上。,集群连接有一个限制:两个行源表表必须是集群表。因此集群连接使用的很少。,散列连接HASH算法最大的好处插入和访问的速度特别快。当向集合中加入一个对象时,会调用hash算法来获得hash
7、code,然后根据hash code分配存放位置。访问的时,根据hashcode直接找到存放位置。Oracle Hash join 是一种非常高效的join 算法,主要以CPU(hash计算)和内存空间(创建hash table)为代价获得最大的效率。Hash join一般用于大表和小表之间的连接,我们将小表构建到内存中,称为Hash cluster,大表称为probe表。Hash join具有较高效率的两个原因:1.Hash 查询,根据映射关系来查询值,不需要遍历整个数据结构。2.Mem 访问速度是Disk的万倍以上。,优化器会优选选择hash join。,两个表没有索引,全表扫描。Cost
8、值是221,大约是一个大表的全表扫描的cost。,使用sort merge,主要消耗在大表的排序上。,消耗非常的大,主要消耗在连接上,因此嵌套连接是一种低效的方式。在给customerid建立索引后,效率降到116K,但这也是一个惊人的cost。嵌套查询适合驱动表非常小的场合。,我们来研究hash join的基础原理:自从 oracke 7.3 以来,oracle 提供了一种新的 join 技术,就是 hash join。Hash Join 只能用于相等连接,且只能在 CBO 优化器模式下。相对于 nested loop join,hash join 更适合处理大型结果集。Hash join
9、不需要在驱动表上存在索引。Hash join 算法的一个基本思想就是根据小的 row sources(称作 build input,我们记较小的表为 S,较大的表为 B)建立一个可以存在于 hash area 内存中的 hash table,然后用大的 row sources(称作 probe input)来探测前面所建的 hash table。Oracle 在连接键利用一个 hash 函数将 build input 和 probe input 分割成多个不相连的分区(分别记作 Si 和 Bi),这个阶段叫做分区阶段;然后各自相应的分区,即 Si 和 Bi 再做 Hash join,这个阶段叫
10、做 join 阶段。,如果内存过小,将会出现下面的情况:如果在分区后,针对某个分区所建的 hash table 还是太大的话,oracle 就采用 nested-loops hash join。所谓的 nested-loops hash join 就是对部分 Si 建立 hash table,然后读取所有的 Bi 与所建的 hash table 做连接,然后再对剩余的 Si 建立 hash table,再将所有的 Bi 与所建的 hash table 做连接,直至所有的 Si 都连接完了。这样性能将会严重降低下来。,Hash Join 算法有一个限制,就是它是在假设两张表在连接键上是均匀的,也
11、就是说每个分区拥有差不多的数据。但是实际当中数据都是不均匀的,为了很好地解决这个问题,oracle 引进了几种技术,位图向量过滤、角色互换、柱状图,这些术语的具体意义会在后面详细介绍。我们用一个例子来解释 Hash Join 算法的原理,以及上述所提到的术语。考虑以下两个数据集。S=1,1,1,3,3,4,4,4,4,5,8,8,8,8,10 B=0,0,1,1,1,1,2,2,2,2,2,2,3,8,9,9,9,10,10,11 第一步,build input 分区。分区的个数叫做 fan-out。Fan-out 是由 hash_area_size 和 cluster size 来决定的。其
12、中 cluster size 等于 db_block_size*hash_multiblock_io_count,hash_multiblock_io_count 在 oracle9i 中是隐含参数。分区数=0.8*hash_area_size/(hash_multiblock_io_count*db_block_size)大的 fan-out 导致许多小的分区,影响性能,而小的 fan-out 导致少数的大的分区,以至于每个分区不能全部存放在内存中,这也影响 hash join 的性能。,Oracle 采用内部一个 hash 函数作用于连接键上,将 S 和 B 分割成多个分区,在这里我们假设
13、这个 hash 函数为求余函数,即 Mod(join_column_value,10)。这样产生十个分区,如下表。,经过这样的分区之后,只需要相应的分区之间做 join 即可(也就是所谓的 partition pairs),如果有一个分区为 NULL 的话,则相应的分区 join 即可忽略。在将 S 表读入内存分区时,oracle 即记录连接键的唯一值,构建成所谓的位图向量,它需要占 hash area 内存的 5%左右。在这里即为 1,3,4,5,8,10。当对 B 表进行分区时,将每一个连接键上的值与位图向量相比较,如果不在其中,则将其记录丢弃。在我们这个例子中,B 表中以下数据将被丢弃
14、0,0,2,2,2,2,2,2,9,9,9,9,9。这个过程就是位图向量过滤。当 S1,B1 做完连接后,接着对 Si,Bi 进行连接,这里 oracle 将比较两个分区,选取小的那个做 build input,就是动态角色互换,这个动态角色互换发生在除第一对分区以外的分区上面。,第 1步:决定 fan-out 数。分区数=0.8*hash_area_size/(hash_multiblock_io_count*db_block_size)第 2 步:读取部分小表 S,采用内部 hash 函数(这里称为 hash_fun_1),将连接键值映射至某个分区,同时采用 hash_fun_2 函数对连
15、接键值产生另外一个 hash 值,这个 hash 值用于创建 hash table 用,并且与连接键值存放在一起。第 3 步:对 build input 建立位图向量。第 4 步:如果内存中没有空间了,则将分区写至磁盘上。第 5 步:读取小表 S 的剩余部分,重复第三步,直至小表 S 全部读完。,第 6 步:将分区按大小排序,选取几个分区建立 hash table(这里选取分区的原则是使选取的数量最多)。第 7 步:根据前面用 hash_fun_2 函数计算好的 hash 值,建立 hash table。第 8 步:读取表 B,采用位图向量进行位图向量过滤。第 9 步:对通过过滤的数据采用 h
16、ash_fun_1 函数将数据映射到相应的分区中去,并计算 hash_fun_2 的 hash 值。第 10 步:如果所落的分区在内存中,则将前面通过 hash_fun_2 函数计算所得的 hash 值与内存中已存在的 hash table 做连接。如果所落的分区不在内存中,则将相应的值与表 S 相应的分区放在一起。第 11 步:继续读取表 B,重复第 9 步,直至表 B 读取完毕。第 12 步:读取相应的(Si,Bi)做 hash 连接。在这里会发生动态角色互换。第 13 步:如果分区过后,最小的分区也比内存大,则发生 nested-loop hash join。,HASH快速的原因:1、对
17、S和B表进行了分区2、连接键进行hash运算以后,根据hash code快速的插入到相应的分区中3、我们只需要对Si和Bi进行分区内部的连接即可,而这些分区内的数量是非常少的如果hash size足够的大,那么所有的连接都发生在内存中,速度非常的快。Hash join主要的消耗发生在全表扫描大表上。,Hash 连接的原理就是生成上面的一张表,然后Si和Bi进行分区内部的连接。生成这张表的过程使用了hash算法,hash值快速的定位到相应的分区中。生成这个表的过程需要消耗内存和CPU。,1 确认大表是驱动表 2 确认涉及到的表和连接键分析过了。3 如果在连接键上数据不均匀的话,建议做柱状图。4
18、如果可以,调大 hash_area_size 的大小或 pga_aggregate_target 的值。5 Hash Join 适合于小表与大表连接、返回大型结果集的连接。HASH_AREA_SIZE在Oracle 9i 和以前,都是影响hash join性能的一个重要的参数。但是在10g发生了一些变化。Oracle不建议使用这个参数,除非你是在MTS模式下。Oracle建议采用自动PGA管理(设置PGA_AGGREGATE_TARGET和WORKAREA_SIZE_POLICY)来替代使用这个参数。MTS的PGA中,只包含了一些栈空间信息,UGA则包含在large pool中,那么实际类似h
19、ash,sort,merge等操作都是有large pool来分配空间,large pool同时也是auto管理的,它和SGA_TARGET有关。,散列连接是CBO 做大数据集连接时的常用方式,优化器使用两个表中较小的表(或数据源)利用连接键在内存中建立散列表,然后扫描较大的表并探测散列表,找出与散列表匹配的行。这种方式适用于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。排序合并连接通常情况下散列连接的效果都比排序合并连接要好,然而如果行源已经被排过序,在执行排序合并连接时不需要再排序了,这时排序合并连接的性能会优于散列连接。可以使用USE_MERGE(table_na
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 连接 其他 高级 调整 技术

链接地址:https://www.31ppt.com/p-6394305.html