(转)in 和 existITeye - 威尼斯人

(转)in 和 existITeye

2019年03月28日11时39分39秒 | 作者: 鸿光 | 标签: 分区,查询,一个 | 浏览: 407

in 和 exists差异in 是把表面和内表作hash join,而exists是对表面作loop,每次loop再对内表进行查询。一直以来以为exists比in功率高的说法是不精确的。假如查询的两个表巨细适当,那么用in和exists不同不大。假如两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:例如:表A(小表),表B(大表)1:select * from A where cc in (select cc from B) 功率低,用到了A表上cc列的索引;select * from A where exists(select cc from B where cc=A.cc) 功率高,用到了B表上cc列的索引。相反的2:select * from B where cc in (select cc from A) 功率高,用到了B表上cc列的索引;select * from B where exists(select cc from A where cc=B.cc) 功率低,用到了A表上cc列的索引。带in的相关子查询是剩下的,由于in子句和子查询中相关的操作的功用是相同的。如:select staff_name from staff_member where staff_id in(select staff_id from staff_func where staff_member.staff_id=staff_func.staff_id); 为非相关子查询指定exists子句是不适当的,由于这样会发生笛卡乘积。如: select staff_name from staff_member where staff_id exists (select staff_id from staff_func);not in 和not exists假如查询句子运用了not in 那么内表面都进行全表扫描,没有用到索引;而not extsts 的子查询仍然能用到表上的索引。所以不管哪个表大,用not exists都比not in要快。尽量不要运用not in子句。运用minus 子句都比not in 子句快,尽管运用minus子句要进行两次查询: select staff_name from staff_member where staff_id in (select staff_id from staff_member minus select staff_id from staff_func where func_id like 81%); in 与 "=" 的差异select name from student where name in (zhang,wang,li,zhao);与select name from student where name=zhang or name=li or name=wang or name=zhao的成果是相同的。

 

EXISTS、IN与JOIN,都能够用来完成形如“查询A表中在(或不在)B表中的记载”的查询逻辑。
在查询的两个表巨细适当的状况下,3种查询方法的执行时间通常是:
EXISTS = IN = JOIN
NOT EXISTS = NOT IN = LEFT JOIN
只有当表中字段答应NULL时,NOT IN的方法最慢:
NOT EXISTS = LEFT JOIN = NOT IN
可是假如两个表中一个较小,一个较大,则表大的用exists,表小的用in,由于in 是把表面和内表作hash 衔接,而exists是对表面作loop循环,每次loop循环再对内表进行查询。而不管那个表大,用not exists都比not in要快。这是由于假如查询句子运用了not in 那么内表面都进行全表扫描,没有用到索引;而not extsts 的仍然能用到表上的索引。
IN的优点是逻辑直观简略(通常是独立子查询);缺陷是只能判别单字段,并且当NOT IN时功率较低,并且NULL会导致不想要的成果。
EXISTS的优点是功率高,能够判别单字段和组合字段,并不受NULL的影响;缺陷是逻辑略微杂乱(通常是相关子查询)。
JOIN用在这种场合,往往是吃力不讨好。JOIN的用处是联接两个表,而不是判别一个表的记载是否在另一个表。

 

 

Hash Join概述 Hash join算法的一个基本思想便是依据小的row sources(称作build input,咱们记较小的表为S,较大的表为B) 树立一个能够存在于hash area内存中的hash table,然后用大的row sources(称作probe input) 来勘探前面所建的hash table。假如hash area内存不够大,hash table就无法彻底存放在hash area内存中。针对这种状况,Oracle在衔接键使用一个hash函数将build input和probe input分割成多个不相连的分区(别离记作Si和Bi),这个阶段叫做分区阶段;然后各自相应的分区,即Si和Bi再做Hash join,这个阶段叫做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算法有一个约束,便是它是在假定两张表在衔接键上是均匀的,也便是说每个分区具有差不多的数据。可是实践傍边数据都是不均匀的,为了很好地处理这个问题,oracle引进了几种技能,位图向量过滤、人物交换、柱状图,这些术语的具体含义会在后边具体介绍。 二. Hash Join原理咱们用一个比如来解说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} Hash Join的榜首步便是断定小表(即build input)是否能彻底存放在hash area内存中。假如能彻底存放在内存中,则在内存中树立hash table,这是最简略的hash join。假如不能悉数存放在内存中,则build input有必要分区。分区的个数叫做fan-out。Fan-out是由hash_area_size和cluster size来决议的。其间cluster size等于db_block_size * hash_multiblock_io_count,hash_multiblock_io_count在oracle9i中是隐含参数。这儿需求留意的是fan-out并不是build input的巨细/hash_ara_size,也便是说oracle决议的分区巨细有或许仍是不能彻底存放在hash area内存中。大的fan-out导致许多小的分区,影响功能,而小的fan-out导致少量的大的分区,以至于每个分区不能悉数存放在内存中,这也影响hash join的功能。 Oracle选用内部一个hash函数作用于衔接键上,将S和B分割成多个分区,在这儿咱们假定这个hash函数为求余函数,即Mod(join_column_value,10)。这样发生十个分区,如下表. 通过这样的分区之后,只需求相应的分区之间做join即可(也便是所谓的partition pairs),假如有一个分区为NULL的话,则相应的分区join即可疏忽。 在将S表读入内存分区时,oracle即记载衔接键的仅有值,构建成所谓的位图向量,它需求占hash area内存的5%左右。在这儿即为{1,3,4,5,8,10}。 当对B表进行分区时,将每一个衔接键上的值与位图向量相比较,假如不在其间,则将其记载丢掉。在咱们这个比如中,B表中以下数据将被丢掉 {0,0,2,2,2,2,2,2,9,9,9,9,9}。这个进程便是位图向量过滤。 当S1,B1做完衔接后,接着对Si,Bi进行衔接,这儿oracle将比较两个分区,选取小的那个做build input,便是动态人物交换,这个动态人物交换发生在除榜首对分区以外的分区上面。
版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表威尼斯人立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章

阅读排行

  • 1

    (转)in 和 existITeye

    分区,查询,一个
  • 2

    oracle正则表达式ITeye

    正则表达式,匹配,表达式
  • 3

    SQL句子的优化办法ITeye

    优化,例如,句子
  • 4
  • 5

    Oracle 存储进程的运用ITeye

    存储,进程,参数
  • 6

    Oracle替换表空间ITeye

    空间,新表,包括
  • 7
  • 8
  • 9
  • 10